Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 是';printf(“n%d”、“a、a)”和“x27”;定义明确?_C_Initialization_Printf - Fatal编程技术网

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,因为它表示“ghost
argc
”,它是一个非常特殊的函数,即使函数没有参数定义,也会出现,并且它的值是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的有效值