C 是';printf(“n%d”、“a、a)”和“x27”;定义明确?
我认为这个结果是有意的 但当我执行下一个时,我得到了一个不同的结果C 是';printf(“n%d”、“a、a)”和“x27”;定义明确?,c,initialization,printf,C,Initialization,Printf,我认为这个结果是有意的 但当我执行下一个时,我得到了一个不同的结果 #include <stdio.h> int main(void) { int i = 0; printf("abc %n %d", &i, i); printf("\n%d\n", i); } int main(void) { int sdf; printf("abc %n %d", &sdf,
#include <stdio.h>
int main(void) {
int i = 0;
printf("abc %n %d", &i, i);
printf("\n%d\n", i);
}
int main(void) {
int sdf;
printf("abc %n %d", &sdf, sdf);
printf("\n%d\n", sdf);
int i;
printf("abc %n %d", &i, i);
printf("\n%d\n", i);
}
产生了:
abc1
4.
我不知道为什么第一个printf()
中的I
的结果是1
甚至,我发现了更奇怪的行为:
int main(void) {
int i; // not initialize
printf("abc %n %d", &i, i);
printf("\n%d\n", i);
}
使用此输出:
abc1
4.
abc随机值
4.
第一个总是显示1
,但其他显示随机值(我认为这是垃圾值)
我认为垃圾值是故意的,但我不明白为什么第一个值有不同的结果。结果定义得很好。
i
和i
的地址被传递到printf
。然后printf将值分配给i。但是因为在调用之前传递了i
,printf将在调用之前打印i
的值
#include <stdio.h>
int main(void) {
int i = 0;
printf("abc %n %d", &i, i);
printf("\n%d\n", i);
}
int main(void) {
int sdf;
printf("abc %n %d", &sdf, sdf);
printf("\n%d\n", sdf);
int i;
printf("abc %n %d", &i, i);
printf("\n%d\n", i);
}
后面的代码段使用未初始化的变量,将首先打印此未确定的值。稍后的行为将与per snipped 1相同
未初始化的变量将具有未确定的值。如果变量类型具有陷阱表示(这里不是这种情况),那么它也可以是UB,但由于执行环境相同,因此很可能会看到相同的值。如果您在其他操作系统、其他计算机或使用其他编译器上运行它,它们可能会有所不同
printf(“%n%d”,&a,a)
在printf中定义得好吗
如果a
具有类型int
(相当于有符号int
)且不符合const
-条件,则为是,否则为否。在定义明确的情况下,打印调用时a
的值,并且在调用返回后,a
将具有值0
这里的关键点可能是,函数调用的参数在输入被调用函数之前进行求值,并按值传递。在参数求值和函数体中第一条语句的执行之间有一个序列点,因此调用函数读取a
并由printf
写入这一事实并不存在任何特殊问题
[…]当我执行下一个时,我得到了一个不同的结果
#include <stdio.h>
int main(void) {
int i = 0;
printf("abc %n %d", &i, i);
printf("\n%d\n", i);
}
int main(void) {
int sdf;
printf("abc %n %d", &sdf, sdf);
printf("\n%d\n", sdf);
int i;
printf("abc %n %d", &i, i);
printf("\n%d\n", i);
}
我不知道为什么第一个printf()中的“I”的结果是1
没有人知道。既没有初始化也没有赋值的自动变量的值是不确定的。此处的注意事项与标题问题中的注意事项相同:
printf
的参数列表中的表达式i
在执行printf
的任何部分之前进行计算,因此,printf
稍后将为其赋值这一事实并不影响它接收到的值。存储类auto
的未初始化局部整数变量的值,存储在堆栈区域中,为。因此,打印它时,绝对需要一个随机值
这就是为什么,在你的输出中
abc 1
4
值1
也是垃圾
事实上,它是堆栈中的第一个位置,其值可以是不同的更改系统和/或编译器。我的猜测是,它的值是1,因为它表示“ghostargc
”,它是一个非常特殊的函数,即使函数没有参数定义,也会出现,并且它的值是1
由于argc
表示用于从命令行调用程序的参数数(至少1:可执行文件名),因此有一种方法可以验证这种情况:以这种方式调用程序
abc 1
4
abc Random_Value
4
这将使argc变为2,因此第一个printf
显示的值也应变为2
出于好奇,我在我的机器上编译了您的第二个示例(W10 64位操作系统下带有gcc
compiler的DevC++),以此来测试这个hypotensis。我确认了两项声明:
argc
存在于堆栈中,并影响未初始化局部变量的初始值uninitVars.exe后输出
executableName foo
执行uninitVars.exe dog后输出
abc
0
abc
1
执行uninitVars.exe dog cat后的输出
abc
0
abc
2
因此,我的堆栈的前四个字节似乎总是设置为0(它们是返回值的位置吗?),而第二个实际上是argc
,即使它没有在main()
原型中显式定义
相反,第二次打印显示不同的值,因为它是在两次printf
调用之后定义的,它们的执行会在堆栈中写入几个字节(其中一些是地址,这解释了为什么值总是不同的,因为进程的地址是虚拟的,并且总是不同的)。首先,不能在同一行中打印%n
的结果,i
将保留其先前的值。关于随机值,虽然您尚未初始化i
和sdf
,但它们具有随机值(很可能为0,但没有保证)。在C语言中,如果全局变量未初始化,则其值为0,但局部变量将具有未初始化的值(随机)。如果所讨论的变量未初始化,则该行为充其量是未指定的,充其量是未定义的
局部变量i
和sdf
未初始化,这意味着它们的值不确定。正式定义见本协议第3.19节,具体如下:
3.19.2
1不确定值
未指定的值或陷阱表示形式
3.19.3
1未指定值
相关t的有效值