C:为什么用%s打印null char会打印“(null)”?

为什么用%s打印空字符(’\ 0’,0)实际打印“(null)”字符串?

喜欢这段代码:

char null_byte = '\0'; printf("null_byte: %s\n", null_byte); 

…打印:

 null_byte: (null) 

…它甚至在Valgrind下运行没有错误,我得到的是编译器警告warning: format '%s' expects argument of type 'char *', but argument 2 has type 'int' [-Wformat] (注意:我在32位Ubuntu上使用gcc 4.6.3)

它是未定义的行为,但它会在您的实现上发生:

  • 传递的0的int值由%s读取为空指针
  • printf%s的处理有特殊情况代码来识别空指针和print (null)

这些都不是标准所要求的。 需要[*]的部分是varargs中使用的char作为int传递。

[*]嗯,这是必需的,因为在你的实现中, char所有值都可以表示为int 。 如果您使用了一些有趣的实现,其中char是无符号的并且宽度与int相同,则它将作为unsigned int传递。 我认为有趣的实现符合标准。

嗯,首先,你做错了。 '\0'是一个字符,应该用%c而不是%s打印。 我不知道这是否是为了实验目的而故意的。

\0的实际二进制值是,0,你正在尝试将值0转换为char *指针,这将导致无效的引用和崩溃。 您的编译器通过对%s值的特殊处理来防止这种情况。

Valgrind不会捕获它,因为它运行在生成的二进制文件上,而不是源代码(你需要一个静态分析器)。 由于编译器已将该调用转换为安全的“空指针”文本,因此valgrind不会看到任何错误。

null_byte包含0.当你在printf中使用%s时,你正在尝试打印一个字符串,这是一个char(char *)的地址。 您在代码中执行的操作是将地址0(NULL)作为字符串的地址传递,这就是输出为空的原因。 编译器警告您,您将错误的类型传递给%s修饰符。 try printf(“null_byte:%s \ n”,&null_byte);

您的printf语句正在尝试打印字符串,因此将null_bye值解释为值为null_byechar * 。 注意警告。 要么这样做

 printf("null_byte: %s\n", &null_byte); 

或这个

 printf("null_byte: %c\n", null_byte); 

因为printf是可变参数,所以通常的参数提升是在null_byte上执行的,因此它被提升( null_byte )为int ,值为0

然后printf读取一个char *指针,并将0 int解释为空指针。 您的C标准库具有将空字符串打印为(null)