消息关闭
    暂无新消息!
printf函数中没有修改变量的值,却会影响相关变量的值吗?

#include <stdio.h>
int main()
{
int *p,z=43,a=100,b=1767,c=15164;
p=&a;
//printf("%d,%d,%d,%d,%d\n",&p,&z,&a,&b,&c);//本行注释与否对结果有影响?
printf("%d\n",*p);
printf("%d\n",*(++p));
printf("%d\n",a);
return 0;
}

这段代码,在VC6.0里编译运行,和在支持TDM-GCC 4.9.2 32-bit Release编译器的Dev-C++ 5.11里编译运行,差异较大。

1、首先说在Dev-C++ 5.11里.
不注释第一个printf语句,编译运行得到的输出结果是:
2293484,2293480,2293476,2293472,2293468
100
43
100

从第一行可以看到,先声明的变量被分配在高地址,后声明的变量被分配在低地址。所以后面的三个printf输出是没有问题的。

但是!

注释掉(或者删除掉)第一个printf语句后,编译运行得到的输出结果则变成:
100
2293472
100

不明白中间那个怎么变成了一个地址。难道有没有第一个printf语句还会对这些变量的值产生影响?

2、再来看在VC 6.0里的情况。
不注释第一个printf语句,编译运行得到的输出结果是:
1245052,1245048,1245044,1245040,1245036
100
43
100

注释掉(或者删除掉)第一个printf语句后,编译运行得到的输出结果为:
100
43
100

从没有注释掉第一条printf语句看到的情况表明,在VC 6.0里,也是一样的内存分配情况,即:先声明的变量被分配在高地址,后声明的变量被分配在低地址。而且第一条printf注释与否,对后面三个printf语句的运行没有影响。


3、请问,在GCC编译器里出现的这种奇怪结果,到底是因为什么?

9个回答

︿ 1
#include <time.h>
#include <stdlib.h>
#include <windows.h>
int main() {
    int a,b[11];//本来是b[10],为判断哪句越界,故意声明为b[11]

    srand((unsigned int)time(NULL));//按两次F11,等黄色右箭头指向本行时,调试、新建断点、新建数据断点,地址:&b[10],字节计数:4,确定。
    while (1) {//按F5,会停在下面某句,此时a的值为10,b[10]已经被修改为对应0..4之一。
        b[(a=rand()%11)]=0;
        Sleep(100);
        b[(a=rand()%11)]=1;
        Sleep(100);
        b[(a=rand()%11)]=2;
        Sleep(100);
        b[(a=rand()%11)]=3;
        Sleep(100);
        b[(a=rand()%11)]=4;
        Sleep(100);
    }
    return 0;
}
︿ 1
同意2楼,*(++p)会随机对应到内存中的某块数据
这是非安全的操作
︿ 1
变量怎么排是未定义的,VS调试时,各变量地址之间有12字节的间隔,所以++p 这种写法没什么意义
︿ 0
深究这个问题还是挺有意思的。不要只抓着那些编程的原则不放。看看编译器,看看进程运行的内存状态,再来研究这个有趣的问题,蛮好玩的。
︿ 0
感谢各位大神回复。
主要是想弄清楚,有printf与没有printf,为什么造成后面的输出不一致。当然,++p确实不应该这样使用,但这个不是本问题的重点。
经过提示,再进行跟踪调试发现,VS在有无printf编译后,变量位置没有发生变化,所以有没有printf没有影响输出。而gcc在有无printf的编译结果,变量的位置是不一样的,所以造成两次输出不一致。
︿ 0
VS和GDB都有数据断点功能专门用来解决此类问题。
关键是看楼主学不学得会了。
︿ 0
不用试图找什么原因。
代码中使用 *(++p) 就是错的,除非p是数组,否则任何可能的后果都要自负。
不要对编译器做什么假设,因为编译器实现的只是语言的标准,标准不会规定一些细节的,原因在于C语言的设计原则,追求效率,相信程序员。即使是同一编译器,在不同的OS上,实现细节也有不同;即使是同一OS上,同一编译器的不同版本,实现细节也可能有不同。
一句话,不要做无意义的讨论。
︿ 0
#include <stdio.h>
int main()
{
    int *p, z = 43, a=100, b=1767, c=15164;
    p = &a;
    //printf(" %p,%p,%p,%p,%p\n", &p,&z,&a,&b,&c);//本行注释与否对结果有影响?
    printf("%p, %p\n", &b, &c);
    printf("%d\n",*p);
    printf("%p\n", p);
    printf("%d\n",*(++p));

    printf("%d\n",a);
    printf("%p, %p\n", &b, &c);

    return 0;
}

打印地址,建议使用%p或%P;
加上printf行应该是改变了函数栈上变量的位置。