Mid*_*lue 135 c arrays pointers
考虑:
char amessage[] = "now is the time";
char *pmessage = "now is the time";
Run Code Online (Sandbox Code Playgroud)
我从C编程语言第2版中读到,上述两个陈述没有做同样的事情.
我一直认为数组是一种操作指针来存储一些数据的便捷方式,但显然情况并非如此...... C中数组和指针之间的"非平凡"差异是什么?
Joh*_*ode 144
这是一个假设的内存映射,显示了两个声明的结果:
0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07
0x00008000: 'n' 'o' 'w' ' ' 'i' 's' ' ' 't'
0x00008008: 'h' 'e' ' ' 't' 'i' 'm' 'e' '\0'
...
amessage:
0x00500000: 'n' 'o' 'w' ' ' 'i' 's' ' ' 't'
0x00500008: 'h' 'e' ' ' 't' 'i' 'm' 'e' '\0'
pmessage:
0x00500010: 0x00 0x00 0x80 0x00
Run Code Online (Sandbox Code Playgroud)
字符串文字"now is the time"存储为内存地址0x00008000的16元素char数组.该存储器可能不可写; 最好假设它不是.您永远不应尝试修改字符串文字的内容.
声明
char amessage[] = "now is the time";
Run Code Online (Sandbox Code Playgroud)
在内存地址0x00500000处分配一个16元素的char数组,并将字符串文字的内容复制到它.这个记忆是可写的; 你可以将amessage的内容改为你心中的内容:
strcpy(amessage, "the time is now");
Run Code Online (Sandbox Code Playgroud)
声明
char *pmessage = "now is the time";
Run Code Online (Sandbox Code Playgroud)
在内存地址0x00500010处为char分配一个指针,并将字符串文字的地址复制到它.
由于pmessage指向字符串文字,因此不应将其用作需要修改字符串内容的函数的参数:
strcpy(amessage, pmessage); /* OKAY */
strcpy(pmessage, amessage); /* NOT OKAY */
strtok(amessage, " "); /* OKAY */
strtok(pmessage, " "); /* NOT OKAY */
scanf("%15s", amessage); /* OKAY */
scanf("%15s", pmessage); /* NOT OKAY */
Run Code Online (Sandbox Code Playgroud)
等等.如果你改变pmessage指向amessage:
pmessage = amessage;
Run Code Online (Sandbox Code Playgroud)
然后它可以在任何地方使用amessage可以使用.
Wal*_*t W 96
没错,但这是一个微妙的区别.基本上,前者:
char amessage[] = "now is the time";
Run Code Online (Sandbox Code Playgroud)
定义一个数组,其成员位于当前作用域的堆栈空间中,而:
char *pmessage = "now is the time";
Run Code Online (Sandbox Code Playgroud)
定义一个指针,该指针位于当前作用域的堆栈空间中,但在其他位置引用内存(在此处,"现在是时间"存储在内存中的其他位置,通常是字符串表).
另请注意,由于属于第二个定义的数据(显式指针)未存储在当前作用域的堆栈空间中,因此未指定它将在何处存储并且不应进行修改.
编辑:正如Mark,GMan和Pavel所指出的,当在这些变量中的任何一个上使用address-of运算符时,也存在差异.例如,&pmessage返回一个char**类型的指针,或一个指向chars指针的指针,而&amessage返回一个char(*)[16]类型的指针,或一个指向16个字符数组的指针(如,一个char**,需要被解除引用两次作为litb指出).
Joh*_*itb 12
数组包含元素.指针指向它们.
第一种是简短的说法
char amessage[16];
amessage[0] = 'n';
amessage[1] = 'o';
...
amessage[15] = '\0';
Run Code Online (Sandbox Code Playgroud)
也就是说,它是一个包含所有字符的数组.特殊初始化为您初始化它,并自动确定它的大小.数组元素是可修改的 - 您可以覆盖其中的字符.
第二种形式是指针,只指向字符.它不直接存储字符.由于数组是字符串文字,因此您无法获取指针并写入指向的位置
char *pmessage = "now is the time";
*pmessage = 'p'; /* undefined behavior! */
Run Code Online (Sandbox Code Playgroud)
这段代码可能会在你的盒子上崩溃.但它可能会做任何它喜欢的事情,因为它的行为是不确定的.
我无法在其他答案中添加有用的内容,但我会注意到,在Deep C Secrets中,Peter van der Linden详细介绍了这个例子.如果你问这些问题,我想你会喜欢这本书.
PS您可以为其分配新值pmessage.您无法为其分配新值amessage; 它是不可改变的.
| 归档时间: |
|
| 查看次数: |
51254 次 |
| 最近记录: |