易截截图软件、单文件、免安装、纯绿色、仅160KB

谈C中scanf陷阱

原文地址:http://westsoftware.blog.163.com/blog/static/2609410920091953456841/
      最近一直在看Andrew Koening写的书籍,可以说学习C/C++或者从事这方面的开发的人员非常值得一看的书籍,这里我推荐看看《C陷阱与缺陷》与《C/C++沉思录》。
      这里先来看看《C陷阱与缺陷》一段代码。
#include <stdio.h>
int main()
{
int i;
char c;
//printf("i address:%ld\n",&i);
//printf("c address:%ld\n",&c);
for(i=0 ; i<5; i++)
{
scanf("%d",&c);
printf("%d ",i);
}
return 0;
}

这么精小的一段代码,看看运行结果将会是什么?请看清楚C是字符变量。
刚开始的时候,对他讲的东西不是很明白,为了更加清楚,分析相关内存结构。
由于scanf指向的是一个整形指针,此时C接收字符录入,所以在给C输入数据的数据的时候,会将i的一些内存地址进行覆盖,怎么覆盖的呢?在FC6下,会将i的低端地址覆盖成C的高端地址,不知道这么说能不能明白?就是说C实际接收了一个整形变量,但是C存不下,多出的那部分怎么办呢?就将C的高端地址位覆盖成I的低端地址位了,所以I的值一直都是0,所以在运行此程序是一个死循环状态。
上面注释掉那两段,可以打印看看C与I的地址。我这里打印的地址是连续的。
但是在VC6中,是可以正常运行的,这就是我说的内存地址覆盖方式不一样,换句话说,怎么覆盖是有编译器决定,这里我是这么猜想,VC覆盖内存的时候是C的左彻的那段内存而不覆盖I的内存地址,所以在VC中能正常。
这也是一个猜想,怠于证实。而在FC中是“往右”进行覆盖。
所以开发的时候,一定要注意,这种陷阱一旦走进去的,就很难调试,有时候也有一种“凑巧”来避开这个问题,差错就更加不好查。希望在以后开发的时候能给大家有一定的参考。


相关文档:

C语言指针与数组(C专家编程)

1.区别(主要的):指针需要增加一次额外的提取操作
     编译器为每个变量分配一个地址(左值)。这个地址编译时可知,而且该变量在运行时一直保存于这个地址。相反,存储于变量中的值(它的右值)只有在运行时才可知。如果需要用到变量中存储的值,编译器就发出指令从地址读入变量值并将它存于寄存器中。
  ......

C/C++ 字节对齐问题

VC中下面几个结构体大小分别是多少呢
struct MyStruct
{
    double m4;
    char m1;
    int m3;
};
struct MyStruct {
    char m1;
    double m4;
    int m3;
};
#pragma pack(push)   ......

C若干实用小技巧

Visual C++6.0(5.0)开发工具功能非常强大,但是对于初学者来说,却有很多细节的问题需要注意。作者搜集整理了以下一些实用小技巧,希望对初学者有所帮助。
  1:使用vc开发项目时,常会遇到这种情况:
    即明明只改动了一个文件,却要把整个项目全部重新编译连接一次。刚刚连接好,一运行,又提示 ......

C/C++ 的全局变量初始化与不初始化的区别

在C语言里,全局变量如果不初始化的话,默认为0,也就是说在全局空间里:
int x =0; 跟 int x; 的效果看起来是一样的。但其实这里面的差别很大,强烈建议大家所有的全局变量都要初始化,他们的主要差别如下:
编译器在编译的时候针对这两种情况会产生两种符号放在目标文件的符号表中,对于初始化的,叫强符号,未初始化的 ......
© 2009 ej38.com All Rights Reserved. 关于E健网联系我们 | 站点地图 | 赣ICP备09004571号