所以我有这个代码
FILE* file = fopen("file.txt", "r");
if(file == NULL)
{
printf("Failed to open file.\n");
return NULL;
}
fseek(file, 0L, SEEK_END);
long bufferSize = ftell(file);
fseek(file, 0L, SEEK_SET);
char* buffer = (char*) malloc(bufferSize);
if(buffer == NULL)
{
printf("Failed to allocate memory for buffer.\n");
return NULL;
}
fread(buffer, sizeof(char), bufferSize, file);
fclose(file);
当使用 printf("%s", buffer) 打印到控制台时,这似乎工作得很好,但我想知道这是否会导致缓冲区溢出,或者是否错误,因为末尾似乎没有空终止符。 假设 file.txt 中正好有 4 个字符。当 bufferSize 计算出来时,它将是一个 long 值,值为 4。因此,当我调用 malloc(bufferSize) 时,我正在创建一个大小为 4 字节的缓冲区,不占空值终结者字符。我到处都看到人们阅读整个文本文件的例子,他们使用这样的代码,但这不应该用文件中的字符创建一个 char* 而没有结束空终止符吗?我应该使用 malloc(bufferSize + 1) 分配此缓冲区并添加空终止符吗?
最佳答案
This seems to work perfectly fine when printing to console with printf("%s", buffer)
似乎工作得很好是 undefined behavior 的完美体现.
should i be allocating this buffer using malloc(bufferSize + 1) and adding a null terminator character?
如果您希望将 %s
printf
格式说明符与指向可打印字符的连续字节的指针一起使用,则这些字节需要以零字节终止。或者相反,%s
printf
格式说明符需要以零结尾的字节序列。否则,会发生未定义的行为。
所以:
- 您的输入文件包含零字节,因此
%s
停止输出。 - 您需要自己提供一个零终止字节,以确保
%s
知道在哪里停止。 - 或者您可以自己迭代字节
for (...) { printf("%c", buffer[i]); }
或者(假设bufferSize
低于INT_MAX
,所以可能是这样)只需通过指定精度来告诉printf
何时停止格式说明符,例如:printf("%.*s", (int)bufferSize, buffer);
否则将会发生未定义的行为。
关于关于为与 fread 一起使用的 char* 分配内存的 C 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61003564/