将非空终止字符串传递给printf会导致意外值

Lun*_*nja 12 c string printf

这个C程序给出了一个奇怪的结果:

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

int main(int argc, char *argv[])
{
   char str1[5] = "abcde";
   char str2[5] = " haha";

   printf("%s\n", str1);
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

当我运行此代码时,我得到:

abcde haha
Run Code Online (Sandbox Code Playgroud)

我只想打印第一个字符串,从代码中可以看出.
为什么要打印它们?

mis*_*mer 34

"abcde"由于C字符串中的空终止字符,实际上长度为6个字节.当你这样做:

char str1[5] = "abcde";
Run Code Online (Sandbox Code Playgroud)

您没有存储空终止字符,因此它不是正确的字符串.

当你这样做:

char str1[5] = "abcde";
char str2[5] = " haha";
printf("%s\n", str1);
Run Code Online (Sandbox Code Playgroud)

恰好是第二个字符串存储在第一个字符串之后,尽管这不是必需的.通过调用printf非null终止的字符串,您已经导致了未定义的行为.

更新:

正如clcto的注释中所述,可以通过不显式指定数组的大小并让编译器根据字符串来确定它来避免这种情况:

char str1[] = "abcde";
Run Code Online (Sandbox Code Playgroud)

或者使用指针,如果它适用于您的用例,尽管它们不相同:

char *str1 = "abcde";
Run Code Online (Sandbox Code Playgroud)

  • 建议使用`chr str1 [] ="abcde";`来防止这种情况? (4认同)

hac*_*cks 19

这两个字符串str1str2没有空终止.因此声明

 printf("%s\n", str1);  
Run Code Online (Sandbox Code Playgroud)

将调用未定义的行为.
printf逐字符串地打印字符,直到遇到'\0'字符串中不存在的字符.在这种情况下,printf继续超过字符串的结尾,直到它在内存中的某处找到空字符.在你的情况下,它似乎printf超过字符串的结尾"abcde"并继续打印第二个字符串中的字符," haha"这是偶然位于内存中的第一个字符串之后.

更好地改变块

   char str1[5] = "abcde";
   char str2[5] = " haha";  
Run Code Online (Sandbox Code Playgroud)

 char str1[] = "abcde";
 char str2[] = " haha";  
Run Code Online (Sandbox Code Playgroud)

避免这个问题.

  • ..或遭受难以接近的记忆的段错误. (2认同)

das*_*ght 11

从技术上讲,这种行为并不是意料之外的,它是未定义的:您的代码将指针传递给缺少空终止符的C字符串printf,这是未定义的行为.

但是,在您的情况下,编译器会在内存中背靠背放置两个字符串,因此在打印后会printf运行到null终结器中str2,这会解释您得到的结果.

如果您只想打印第一个字符串,请为null终止符添加空格,如下所示:

char str1[6] = "abcde";
Run Code Online (Sandbox Code Playgroud)

更好的是,让编译器为您计算正确的大小:

char str1[] = "abcde";
Run Code Online (Sandbox Code Playgroud)


gio*_*gim 6

您已调用未定义的行为.这里:

   char str1[5] = "abcde";
Run Code Online (Sandbox Code Playgroud)

str1有五个字母以上的空格,但没有空终止符.然后,您尝试传递非null终止字符串以printf进行打印的方式,调用未定义的行为.

通常,在大多数情况下,将非空终止字符串传递给期望(C)字符串的标准函数并不是一个好主意.