关于字符串指针的操作

光庆 2月前 398

一、前言:

aardio中的字符串,是不可修改的。

我们对字符串变量重新赋值一个不同的字符串,并不是“修改数据”,而是“更换地址”,实际上是赋予了一个新的内存指针。

先看下图,理解一下aardio中字符串变量的定义方式:

在aardio中,不同的变量、字符串,如果内容一样,则会指向同一个指针。

就如上图,变量a、变量b、"哈哈哈"立即数 三者的指针是一样的。

在这种情况下,如果根据一个变量的指针修改了其内容,实际上可能会影响很多其他变量甚至 "立即数" 的内容。其后果是未知的

我猜测这也是aardio不允许直接修改字符串内容的原因之一吧。

二、获取指针的方法

aardio 中可以使用如下代码获取字符串指针的函数:

var a = "哈哈哈";
var p = raw.toPointer(a); //这是字符串"哈哈哈"的指针,同时也是变量a的指针

var p = raw.toPointer("哈哈哈"); //这是字符串"哈哈哈"的指针,同时也是变量a的指针

windows API 也提供了获取字符串指针的函数,我们可以直接使用:

var a = "哈哈哈";
var p = ::Kernel32.lstrcpynP(a,a,0); //这是字符串"哈哈哈"的指针,同时也是变量a的指针


 var p = ::Kernel32.lstrcpynP("哈哈哈","哈哈哈",0); //这是字符串"哈哈哈"的指针,同时也是变量a的指针

三、修改字符串的方法

aardio中没有提供直接修改字符串内容的方法,但是提供了修改内存数据的方法。

可以通过 raw.convert( ) 、raw.copy( ) 等函数改写字符串内存内容。

import console; 
var a = "哈哈哈";
var b = "哈哈哈";
var p = ..raw.toPointer(a);
//var p = ::Kernel32.lstrcpynP(a,0,0);
console.dump(p); //输出指针看一下
raw.copy(p,"123",3); //修改指针处内容
raw.copy(topointer(p,3),"完",3); //修改指针偏移3处内容
raw.copy(topointer(p,6),"活",3); //修改指针偏移6处内容
console.dump(a,b,"哈哈哈"); //显示原数据,看看是否被修改
console.pause(true);

可以看出,修改一个变量的内容后,其他同内容的变量,甚至立即数"哈哈哈"都被修改了。这样会造成不可预知的后果。慎用。

四、高级一点的测试,多线程中数据是否共享

因为 aardio 中,多线程是数据独立的,内存不共享,所以理论上来说,不同线程中声明的相同内容的字符串,内存地址也是不一样的。

测试一下:

import console; 
import thread
//创建a变量
var a = "哈哈哈";
var p = ..raw.toPointer(a);
console.dump(p); //输出a指针
//启动一个线程,修改"哈哈哈"内存数据
thread.invokeAndWait(
    function(){
        var b = "哈哈哈";
        var p = ..raw.toPointer(b);
        import console;
        console.dump(p); //输出b指针
        raw.copy(p,"123",3); //修改指针处内容
        console.dump(b);
    } 
)
//显示a变量数据,看看是否被修改
console.dump(a); 
console.pause(true);

测试结果:

可以看出,变量 a 与 b 的指针是不一样的。在线程中修改b的内容,并不影响a的内容。

这就是“线程内存独立”,体现了线程的安全性。

五、看一下buffer

buffer与string相比,就有独立的内存地址了,可以在不改变指针的情况下修改某部分内容。

每次 raw.buffer( ) 都会重新分配一块独立内存,而不是与其他相同内容的 buffer 指向同一内存。

看以下代码:

import console; 
//创建两个内容相同的buffer变量
var a = raw.buffer("哈哈哈");
var b = raw.buffer("哈哈哈");
console.dump(raw.toPointer(a)); //输出a指针
console.dump(raw.toPointer(b)); //输出b指针
//对a数据进行修改
a[1]='1'#;
a[2]='2'#;
a[3]='3'#;
console.dump(a)
console.dump(b)
//看一下变量指针在修改前后是否发生变化
console.dump(raw.toPointer(a)); //输出a指针
console.dump(raw.toPointer(b)); //输出b指针
console.pause(true);

执行结果:

可以看到,两个内容相同的buffer,地址是不一样的。修改一个,也不影响另一个。同时,对buffer内容进行修改,其指针也不变。

注意:以下方式给buffer赋值,会指向同一指针:

var a = raw.buffer("哈哈哈");
var b = a; // b 与 a 相当于是同一个变量。

用以下代码测试一下:

import console; 
//创建buffer变量
var a = raw.buffer("哈哈哈");
var b = a;
console.dump(raw.toPointer(a)); //输出a指针
console.dump(raw.toPointer(b)); //输出b指针
//对a数据进行修改
a[1]='1'#;
a[2]='2'#;
a[3]='3'#;
console.dump(a)
console.dump(b)
//对比变量指针是否变化
console.dump(raw.toPointer(a)); //输出a指针
console.dump(raw.toPointer(b)); //输出b指针
console.pause(true);

执行结果:

可以看出,两个变量指针一样,修改一个,另一个也随之修改。

最新回复 (2)
  • 小光芒 2月前
    0 2
  • mndsoft 2月前
    0 3
    很喜欢这种基础课,赞
返回