【问题标题】:Null termination of string not working it seems字符串的空终止似乎不起作用
【发布时间】:2019-09-10 04:04:18
【问题描述】:

在这两个版本中:

//VERSION 1
char *c=malloc(10);
c[0]='h';
c[1]='i';
c[2]='\0';
c[3]='l';

printf("%s\n",c);

我得到了预期的结果,即正在打印hi

现在在这个:

//VERSION 2
char *c;
size_t siz=8;

c=malloc(sizeof(char)*(siz+1));  //char size is 1 byte on system

getline(&c,&siz,stdin);
c[siz]='\0';
printf("%s\n",c);

输入值'hello world'时,输出是'hello world' - 我期待它在读取第9个字节后不会打印任何东西(它是设置为\0)。

为什么两者有区别?

这是因为第 2 版中的指针 c 指向 stdin 并且 `\0' 修改在流中不起作用吗?如果是,那么为什么编译器现在会发出任何警告或错误?

【问题讨论】:

  • 调用getline()siz是什么?
  • 1 应该可以工作,对于 2,请参阅 man getline(3) "如果 *lineptr 设置为 NULL 并且 *n 设置为 0 之前调用,然后getline() 将分配一个缓冲区来存储该行。"
  • @DavidC.Rankin 知道了 - 一定是调整大小的问题,那么为什么 \0 的分配即使使用 -Wall 也不会生成错误/警告消息?
  • 因为在 C 中,边界检查是程序员的责任,C-Standard 中没有要求发出任何诊断(尽管一些编译器现在会标记它) 此外,c[siz] 是分配siz+1 范围内——因此分配没有任何问题。 (但如果您没有检查来自getline 的返回,则所有投注都关闭,字符串末尾的 nul-terminating 毫无意义)
  • @DavidC.Rankin 我的问题是因为c 指向stdin - 不应该将任何东西(在本例中为\0)分配给stdin 生成错误/警告?

标签: c


【解决方案1】:

正如您自己在 cmets 中所指出的,getline 将检查指针和大小参数,以查看在流中的行超过给定缓冲区大小的情况下是否需要重新分配(或分配)缓冲区(@ 987654322@ 大小为 0 的缓冲区是普通分配而不是重新分配)。发生这种情况时,指针和大小参数都会更改以匹配新缓冲区(请记住,您传递了指向缓冲区指针和大小参数的指针,而不仅仅是参数本身,引用而不是值)。

因此,在您的示例中,在分配大小为 9 个字符(在您的情况下为 9 个字节)的缓冲区之后;您的 c 指针设置为至少有 9 个可用字节的内存,siz 仍然是 8。但是,在键入超过 8 个字符(包括新行)的行(如 "hello world\n")后,缓冲区将重新分配到适合整个字符串 "hello world\n\0",即 13 个字节,并且大小参数更改为 13。因此,当 getline 返回时,c 指向这个新缓冲区,siz 是 13。你不需要添加一个空终止,因为getline 为您完成它(假设它成功)。然后你正在做的是将c[13] 设置为'\0',幸运的是,当你访问缓冲区末尾时没有触发任何异常(创建字符串"hello world\n\0\0")。

对于您要查找的结果,保留原始大小,就像在宏中一样:

#define SIZE 8
char* c;
size_t siz = SIZE;
c = malloc(sizeof(char) * (siz +1));
getline(&c, &siz, stdin); // if you type something longer than 8 bytes including new line, it will trigger the realloc and siz will be changed
c[SIZE] = '\0'; // prematurely end the string at 8 bytes
printed("%s\n", c); // now you'll get shorter strings, noting siz will still keep the full length for you

【讨论】:

    猜你喜欢
    • 2019-11-22
    • 1970-01-01
    • 2015-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多