使用指针遍历字符串
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 )
.
我正在尝试使用指针打印字符串的每四个字符。
我能够使用以下代码实现它:
#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 )
.