C 字符串指针。int 指针 vs char 指针

ehp*_*k86 0 c pointers c-strings

我想知道为什么 * p+1输出 k 而不是 "o"?我试过用调试器运行它,但似乎仍然无法解决这个问题。

    char name[] = "john q public";
    int *p = name;
    printf("%c\n", *p+1); // output expected -> o, but got k
    printf("%c", name[0]); // output as expected -> j
Run Code Online (Sandbox Code Playgroud)

当我尝试在 for 循环中输出名称时,我得到了奇怪的值。

    int  len = strlen(name);
    for(int i=0; i<len; i++ ){
        printf("%c", *p++); //expected -> john q public, but got -> j ucem n 1 
    }
Run Code Online (Sandbox Code Playgroud)

Dav*_*ica 5

为什么'k'

你声明:

char name[] = "john q public";
Run Code Online (Sandbox Code Playgroud)

访问时,name转换为指向第一个元素的指针(指向 的指针'j'C11 标准 - 6.3.2.1 其他操作数 - 左值、数组和函数指示符 (p3)

您分配:

int *p = name;
Run Code Online (Sandbox Code Playgroud)

因此p'j'将存储(例如p指向'j')的内存位置(地址)作为其值。然后你打印printf("%c\n", *p+1);derefereing p(eg *p) 是字符'j'ASCII Table 和 Description , j + 1 == k,所以你的输出'k'是完全预期的。

j ucem n 1??

您声明int *p指针类型控制指针算术。因此按字节(通常为 4 字节)而不是字节(1 字节)p++前进。那么让我们看看:psizeof(int)sizeof(char)

    john q public
    -------------
    0123456789012
    ^   ^   ^   ^   4-bytes per p++
    |
    p
Run Code Online (Sandbox Code Playgroud)

增加 4 个字节,您拥有j uc...where...指示您通过访问数组末尾以外的内存来调用未定义行为的位置name- 所有赌注都已关闭。

始终在启用警告的情况下编译

始终在启用警告的情况下进行编译,并且没有警告的情况下编译之前不要接受代码。要启用警告添加-Wall -Wextra -pedantic到您的gcc/clang编译字符串(也考虑添加-Wshadow到阴影变量的警告)。对于VScl.exe在 Windows 上),使用/W3. 所有其他编译器都有类似的选项。阅读并理解每个警告——然后去修复它。他们将识别任何问题,以及它们发生的确切线路。通过聆听编译器告诉您的内容,您可以学到很多东西。

如果您在启用警告的情况下进行编译,您会发现:

warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
 int *p = name;
Run Code Online (Sandbox Code Playgroud)