使用指针遍历字符串

String traversal using pointers

我正在尝试使用指针打印字符串的每四个字符。

我能够使用以下代码实现它:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char const *argv[]){

char* string = "WhatTheeHell";
char* p = string;

while(*p != '[=10=]'){
    printf("%c\n", *p);
    p += 4;
}

return 0;

}

这正确地给我输出了:

W

T

H

现在,我尝试了另一种方法,根据我对指针算法的了解,这种方法应该可行,因为我机器上的 int 大小是 4 个字节。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char const *argv[]){


    char* string = "WhatTheeHell";
    int* p = (int*)string;

    while(*p != '[=11=]'){
        printf("%c\n", *p);
        p += 1;
    }

    return 0;

}

当我为此打印输出时,它给了我 WTH 后跟四个换行符。

我的问题,为什么要打印四个换行符?难道不应该是在打印 H 之后,*p 在字符串文字的末尾给出了一个 NULL 字符并且循环终止了吗?

当您将 *p[=11=] 进行比较时,*p 不是单个字符,而是一个(大概)four-byte 值(在比较之前,字符被提升为整数).
无法保证在字符串的 [=11=] 之后还有其他零字节:这是未定义的行为。

因此你的循环会继续,直到它偶然达到一个零整数。

"%c\n"打印时,只考虑整数的低位字节;如果它的值为零(没有任何保证)它不会打印任何可见的东西,只是下面的 \n

对于初学者来说,第一个程序是无效的。如果一个字符串的字符数不能被 4 整除,你将有未定义的行为,因为指针可以使用指针算法指向字符串之外

p += 4;

演示程序中显示的有效方法如下所示

#include <stdio.h>

int main( void )
{
    const char *s = "WhatTheeHell";
    const size_t STEP = 4;

    if ( *s )
    {
        const char *p = s;
        do
        {
            printf( "%c\n", *p );
            for ( size_t i = 0; i < STEP && *p; ++i, ++p );
        } while ( *p );            
    }
}

它的输出是

W
T
H

第二个你的程序也是无效的。对于初学者来说,字符串文字没有必要按 sizeof( int ) 对齐(而且通常 sizeof( int ) 可以大于或小于 4)。所以程序已经有未定义的行为。

在这种情况下

*p != '[=13=]'

sizeof( int ) 字节(不是单个字节)与整数常量 '[=18=]' 进行了比较。因此,当指针指向字符串内部时(如果没有零字节,甚至超出字符串),比较将始终为 true

顺便也注意在C中sizeof( '[=20=]' )等于sizeof( int ).