1

我遇到了这个问题:

#include<stdio.h>
int main()
{
 char str[25]="Catch me, if u can!";
 printf("%s\n",&str+2);
 return 0;
}

谁能解释我的意思&str+2?这是如何运作的?

4

4 回答 4

5

&str返回类型的指针char (*)[25]。这意味着,该指针指向的内存大小将是sizeof(str),即 25。根据正常的指针算法,将 2 加到该值将产生一个类型的指针,该指针将指向数组char (*)[25]末尾后 25 个字节。str打印它很可能是未定义的行为。

于 2012-11-30T18:33:32.330 回答
4

str是一个类型为“25 个字符的数组”的表达式。在大多数情况下,数组会自动转换为指向其第一个元素的指针。因此, instr+2str转换为指向char数组中第一个的指针,并且当添加 2 时,结果是指向char数组中第三个的指针。

但是,根据 C 2011 6.3.2.1 3,当数组类型的表达式是一元运算符sizeof,的操作数,或者是用于初始化数组的字符串文字时,不会发生这种自动转换。因此, in ,不会转换为指针;它仍然是一个 25 个字符的数组。然后是一个指向 25 个字符的数组的指针。将 2 添加到此时,从概念上讲,结果是指向 25 个字符数组的数组的第三个元素的指针。_Alignof&&str+2str&str

但是,指针运算仅在数组内部定义,直到数组末尾的虚构元素。(此外,为了指针算术,单个对象被视为具有一个元素的数组。)由于我们只有一个 25 字符数组而不是 25 字符数组数组,因此没有第三个元素可以指向,并且&str+2是未定义的。

于 2012-11-30T18:52:01.467 回答
1

首先,您在那里所做的最多会导致未定义的行为。

str是一个符号,它与字符串开始的堆栈上的内存地址有关。&str在堆栈符号上无效,使用它将导致未定义的行为。您可能想要的是str + 2指向字符串中第三个字节的指针,因此

printf("%s\n",str+2);

将打印"tch me, if u can!\n"

于 2012-11-30T18:36:08.447 回答
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);

你会看到0xbfa7fc130xbfa7fc13。相同的值,因为数组从它的地址开始。当您将 2 添加到 str 时,您将指向字符串的下方:

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);

只会把绳子往下扔一点。但是,如果您将 2 添加到 的地址str,那么它将自动为您 * 按您要添加的任何大小的大小:

&str + 2 ==> &str + 2 * sizeof(str) ==> &str + 50 ==> 0xbfa7fc45

如您所见,该地址已超出数组在堆栈上的位置,因此打印:

printf("%s\n",&str+2);

'\0'如果幸运的话,只会吐出数组后 50 字节的任何垃圾,直到找到 a 为止。这是未定义的行为,所以它几乎可以做任何事情。

于 2012-11-30T19:11:39.293 回答