- 论坛徽章:
- 0
|
>> (1)如果buf2的声明不是char *buf2="efgh";而是char buf2[]="efgh";那么编译就会提示g(&buf2);失败
前面 scutan 已经说了。
定义为 char buf2[] = "efgh" 时, &buf2 的类型是 char (*)[],而不是 char **,
所以编译器会因类型不符报错。
对指针的各种提取操作,包括*,**,*** 等形式,汇编能力强的话,最好的理解还是从编译器角度来看,
否则还是老老实实看文档,多做实验。
1、
void f(char* s)
{
s[0]='8';
s[1]='9';
}
--------------------------
编译器对 s 指针及其提取操作,s[0] = '8'; 会作如下处理:
mov eax,
mov [eax], '8'
>> 是s变量里的值,不是变量本身。地址值通过s传过来,给了eax,
然后通过[eax] 往这个地址做 store 操作。
2、
void g(char **s)
{
*s=global;
}
-------------------------------------
编译器对 *s = global; 的处理大概如下:
mov eax,
mov eax, [eax]
mov [eax], global ---> global 一般是立即数
>> 多了一层提取操作。
地址值通过 s 传过来给了 eax ,然后取这个地址里面的值,当作是地址值。
然后,再通过 [eax] 把这个当作是地址值的地址上 (取出来的值),做 store 操作。
也就是对 ** 类型的操作示范。
可以想象,如果:
char c = 'a';
g(&c);
>> 强行通过 &c, 给g(),会有什么后果?
mov eax, &c ---> c 变量本身的地址值
mov eax, [eax] ----> 这还没出现问题,eax 的值为 'a' (65)
mov [eax], global ----> 往 65 这个地址写东西,只有出错了。
若:char *p = &c;
g(&p);
>> 调用端:
lea eax, c ---> offset c
mov [p], eax ---> [p] = offset c
lea eax, p ---> offset p
push eax
这是正确的使用方法
3、
g(char*s)
{
char** ps=&s
... ...
}
形参 s 与实参址是不同的,一般如:s => [ebp+8] (callee)
实参 => [ebp-XX] (caller) |
|