我遇到了这个问题:
#include<stdio.h>
int main()
{
char str[25]="Catch me, if u can!";
printf("%s\n",&str+2);
return 0;
}
任何人都可以向我解释&str+2
的含义吗?这是如何运作的?
答案 0 :(得分:5)
&str
返回类型为char (*)[25]
的指针。这意味着,该指针指向的内存大小为sizeof(str)
,i。即25.根据正常的指针算法,向此值添加2将产生类型为char (*)[25]
的指针,该指针将指向str
数组末尾之后的25个字节。打印它很可能是未定义的行为。
答案 1 :(得分:4)
str
是一个类型为“25 char”的表达式。在大多数情况下,数组会自动转换为指向其第一个元素的指针。因此,在str+2
中,str
被转换为指向数组中第一个char
的指针,并且,当添加2时,结果是指向第三个char
的指针在数组中。
但是,根据C 2011 6.3.2.1 3,当数组类型的表达式是sizeof
,_Alignof
,一元&
运算符的操作数时,或者是字符串文字用于初始化数组,不会发生此自动转换。因此,在&str+2
中,str
不会转换为指针;它仍然是25个字符的数组。然后&str
是一个指向25个字符的数组的指针。当向它添加2时,结果是概念上指向25 char数组数组的第三个元素的指针。
但是,指针算法仅在数组内定义,直到数组末尾的虚构元素。 (另外,出于指针运算的目的,单个对象被视为具有一个元素的数组。)因为我们只有一个25个char的数组而不是25个char的数组,所以没有第三个要指向的元素,并且&str+2
未定义。
答案 2 :(得分:1)
首先,你在那里做的事情最多会导致未定义的行为。
str
是一个符号,它与堆栈中字符串开头的内存地址相关。 &str
在堆栈符号上无效,使用该符号将导致未定义的行为。您可能想要的是str + 2
,它是指向字符串中第3个字节的指针,因此
printf("%s\n",str+2);
将打印"tch me, if u can!\n"
答案 3 :(得分:0)
定义数组时:
char str[25] = "Catch me, if you can!";
你得到的是在堆栈上保留25个字节的间隔,并放入以下内容:
@Address @Address
0xbfa7fc13 0xbfa7fc2C
| |
V V
[C][a][t][c][h][ ][m][e][,][ ][i][f][ ][y][o][u][ ][c][a][n][!][\0][\0][\0][\0]
查看str的地址:
printf("%#x, %#x\n", str, &str);
您将看到0xbfa7fc13
,0xbfa7fc13
。相同的值,因为数组从它的地址开始。当你向str添加2时,你将指向字符串的下方:
0xbfa7fc13 + 2 =
0xbfa7fc15
|
V
[t][c][h][ ][m][e][,][ ][i][f][ ][y][o][u][ ][c][a][n][!][\0][\0][\0][\0]
所以打印:
printf("%s\n", str+2);
只是将字符串向下倾斜一点。但是,如果你在str
的地址中添加2,那么它会自动地*为你提供你所添加的任何大小:
&str + 2 ==> &str + 2 * sizeof(str) ==> &str + 50 ==> 0xbfa7fc45
正如您所看到的那样,地址已经超出了数组在堆栈中的位置,因此打印:
printf("%s\n",&str+2);
如果幸运的话,只要吐出50个字节的数据,直到发现'\0'
为止。它是未定义的行为,所以它几乎可以做任何事情。