一、前言:
aardio中的字符串,是不可修改的。
我们对字符串变量重新赋值一个不同的字符串,并不是“修改数据”,而是“更换地址”,实际上是赋予了一个新的内存指针。
先看下图,理解一下aardio中字符串变量的定义方式:
![](https://aardio.online/upload/files/20240612/1718151084.png)
在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);
![](https://aardio.online/upload/files/20240612/1718152235.png)
可以看出,修改一个变量的内容后,其他同内容的变量,甚至立即数"哈哈哈"都被修改了。这样会造成不可预知的后果。慎用。
四、高级一点的测试,多线程中数据是否共享
因为 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);
测试结果:
![](https://aardio.online/upload/files/20240612/1718161622.png)
可以看出,变量 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);
执行结果:
![](https://aardio.online/upload/files/20240612/1718162137.png)
可以看到,两个内容相同的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);
执行结果:
![](https://aardio.online/upload/files/20240612/1718162309.png)
可以看出,两个变量指针一样,修改一个,另一个也随之修改。