C 如果不';在声明它之后,你不能定义它吗?

C 如果不';在声明它之后,你不能定义它吗?,c,memory,C,Memory,所以如果一个人写 char *buffer; 在C语言中,人们会期望没有无限的内存放入缓冲区。那么我能在那根绳子里放多少东西呢?我问这个问题是因为我正在使用fread()函数从文件中读取内容,并且担心该变量的内存何时会用完。它是否会在需要更多内存时进行扩展?如果不希望程序崩溃或表现出未定义的行为,则什么都不做。这只是一个指针,如果你不初始化它,它会指向某个东西,它可能在你的程序内存空间中,也可能不在。如果是,你可以很高兴地覆盖其他内容;如果不是,操作系统将使您的程序崩溃。当您将缓冲区定义为ch

所以如果一个人写

char *buffer;

在C语言中,人们会期望没有无限的内存放入缓冲区。那么我能在那根绳子里放多少东西呢?我问这个问题是因为我正在使用fread()函数从文件中读取内容,并且担心该变量的内存何时会用完。它是否会在需要更多内存时进行扩展?

如果不希望程序崩溃或表现出未定义的行为,则什么都不做。这只是一个指针,如果你不初始化它,它会指向某个东西,它可能在你的程序内存空间中,也可能不在。如果是,你可以很高兴地覆盖其他内容;如果不是,操作系统将使您的程序崩溃。

当您将
缓冲区定义为
char*buffer
在函数体中,仅定义未初始化的指针。你既不能读也不能写。事实上,你甚至无法解读它的价值。以下所有语句都调用未定义的行为:

int main() {
    char *buffer;
    char c = *buffer;  // undefined behavior: reading from an uninitialized pointer
    *buffer = '\0';    // undefined behavior: writing through an uninitialized pointer
    printf("%p\n", (void *)buffer);  // undefined behavior: reading an uninitialized variable
}
在使用此指针之前,必须将其初始化为指向实际对象,即
字符的数组

    char array[100];
    buffer = array;    // you can write up to 100 bytes to buffer[0] through buffer[99]

    buffer = malloc(100);  // same unless `malloc()` returned NULL

但是假设我开始给它写信(或者稍后初始化它?)。在我无法放入任何其他内容之前,我将写入多少内容?如果我达到该限制,会发生什么?如果您
buffer=malloc(1024)
,您将获得1024字节(如果
malloc
失败,则将一无所获)。你可以
realloc
(注意,它可能会移动指针)来获取更多。Re“如果你不初始化它,它指向某个东西”:未初始化的popinter不需要指向任何东西。它根本不一定有一个值,并且在不同的时间可能有不同的值。未初始化的对象具有不确定的值;它可以是未指定的值或陷阱表示。在C标准中,“未指定值”具有特殊含义;C 2018 3.19.3将其定义为“相关类型的有效值,本文件在任何情况下均未对选择的值施加任何要求”,这意味着每次使用它时,它可能会有所不同。好吧,它指向内存中的某个地方,@EricPostpischil,因此是“某物”。无可否认,我的措辞含糊不清。@AKX:不,它不一定指向某个地方。第一,它可能指向一些根本不是记忆的东西;地址可能不仅没有被映射,甚至对于计算机体系结构来说都是无效的。第二,它可能根本没有价值<如果未初始化
缓冲区,则C标准允许code>printf(“%p%p%p\n”),(void*)缓冲区,(void*)缓冲区,(void*)缓冲区)
打印三种不同的结果。换句话说,如果一个对象没有初始化,它所持有的值的模型就不适用……读取一个未初始化的变量并不是天生的未定义行为。在这种情况下,是因为
缓冲区
“可能已声明
寄存器
”(C 2018 6.3.2)。但是,如果代码是
printf(“%p%p\n”,(void*)和buffer,(void*)buffer),该行为将被不完全指定,但不是未定义的(除非C实现具有指针的陷阱表示,并且
缓冲区
碰巧具有这种表示)因为
buffer
不能声明
register
@EricPostpischil:我指的是C实现可能有指针的陷阱表示,而
buffer
恰好有这样的表示。在这种情况下,仅将
buffer
传递到
printf
具有未定义的行为。我看不出
register
有什么不同,因为编译器可以忽略此存储类。在我给出的示例中,同时打印
&buffer
buffer
,将
buffer
传递到
printf
并没有未定义的行为。
register
的参与是因为C标准中的规则明确指出:“如果左值指定了一个自动存储持续时间的对象,该对象本可以用
register
存储类声明(从未获取其地址),并且该对象未初始化(未使用初始值设定项声明,且在使用前未对其进行赋值),行为未定义。”(我之前的引用有错误;它是6.3.2.12,而不是6.3.2。)