3

如果我们在 C 编程中将变量声明为整数而不定义值,那么 printf 会从缓冲区打印一些垃圾值。有什么方法可以防止打印垃圾值吗?

我想检查是否可以在编译时完成某些事情?如果可能的话?

4

5 回答 5

12

是的。初始化变量。

于 2010-08-11T09:26:28.377 回答
1

维基百科说:

在计算中,未初始化变量是已声明但在使用前未设置为确定的已知值的变量。它会有一些价值,但不是可预测的。因此,这是一个编程错误,也是软件中常见的错误来源

所以将其初始化为默认值。

于 2010-08-11T09:30:41.790 回答
1

在编译时,大多数编译器(例如 GNU 编译器)可以识别未初始化变量的使用位置。但是,您可能需要设置标志,例如为-WallGNU 编译器设置标志。

变量的值已经存在,尽管它可以是任何值。即它是变量的“初始”状态。

因此,您必须初始化变量以避免垃圾。

当一个变量x被声明时,它已经&x为这个变量名引用的内存分配了一个部分。未初始化的值和变量已经放置在内存地址中。假设您初始化了一个vint 类型的变量。它被分配到一个内存地址,它是&vint * 类型的。因此,地址&v将被放置到内存中一个未使用的开放位置。

在 main 函数中考虑这段代码:

int x; 
// A number of bytes (in this case, sizeof(int), usually 4 B) already allocated
// starting at a memory location &x.

printf("Value at address %p: %d", &x, x); 
// Value at &x may be any int, which is unpredictable

编译此代码时,会出现此警告消息,其中SOME_DIRECTORY是任意目录:

SOME_DIRECTORY>gcc -Wall -g sampleprogram.c -o sampleprogram
sampleprogram.c: In function 'main':
sampleprogram.c:8:5: warning: 'x' is used uninitialized in this function [-Wuninitialized]
     printf("Value at address %p: %d", &x, x);

存储器的起始值,就像电路一样,是不可预测的。不管你的价值为什么是随机垃圾。这也是一种未定义行为,这意味着 C 编译器的国际标准没有设置任何要求,因此任何事情都可能发生。这是一个非常糟糕的错误,可能会导致多个难以追踪的错误和故障。

于 2018-04-04T05:54:07.100 回答
1

如果您正在定义局部变量,那么没有。编译器不会为您初始化它们。堆栈的增长和收缩取决于被调用的函数及其局部变量。编译器在每次函数调用时清除所有内存是没有意义的。

但是,如果将全局变量放在.bss中,则它们的初始值可以为 0,这是缩小程序大小的优化。

于 2018-04-04T07:08:01.627 回答
0

您当然希望使用所有警告和调试信息进行编译:gcc -Wall -Wextra -g使用GCC。然后很可能你会收到警告,你应该改进你的代码以得到任何警告。

当然,您应该初始化您的变量。顺便说一句,这样的初始化代码很短,并且运行得非常快。并且在某些情况下(使用 eg -O1gcc能够优化(使用as-if 规则)并删除无用的初始化。因此,根据经验,不要害怕“无用”的初始化。

您应该养成初始化大多数变量的习惯(很少有例外,例如某些PRNG的种子),实际上是所有变量。在少数情况下,如果您不是故意初始化变量并希望它保留一些垃圾值,请在注释中记录(但不要指望垃圾真的是随机的;实际上它仍然可能始终相同)。

阅读有关未定义行为的更多信息。害怕UB

请记住,变量是源代码中的名称。变量在运行时不存在(只有位置存在)。它们可以被编译器删除,它们有时可能位于调用堆栈的调用框架的某个插槽中,它们可以进入某个寄存器,等等......

于 2018-04-04T05:58:14.130 回答