您的位置:网站首页 > Java工具 > 正文

C语言之编译器引出的常见问题

类别:Java工具 日期:2017-8-19 20:43:58 人气: 来源:

  C程序通常由几个小程序(。c文件)组成,编译器将这几个小程序分别编译,然后通过链接程序将它们组合在一起形成一个目标代码。由于编译器每次只能编译一个文件,因此它不能立即检查需要几个源文件配合才能发现的错误。

  C编译器会对函数的参数建立临时参数,也可能会对函数的返回值隐含传递一个指针。因为这些临时变量的隐含性存在,使得在某些情况下,特别是有指针存在的时候,会引发一系列的问题。

  我有一个数组a定义在f1.c中,但是我想在f2.c中计算它的元素个数,用sizeof可以达到这个目的吗?

  答案是否定的,你没有办法达到目的,本质原因是sizeof操作符只是在“编译时(compile time)”起作用,而C语言的编译单位是每次单个。c文件进行编译(其它语言也都如此)。因此,sizeof可以确定同一个源文件中某个数组的大小,但是对于定义在另一个源文件中的数组它为力了,因为那已经是“运行时(run time)”才能确定的事情了。

  1)、定义一个全局变量,让它记住数组的大小,在另外一个。c文件中我们通过访问这个全局变量来得到数组的大小信息(好像有点小题大做得不偿失^_^)。

  2)、在某个。h文件中用宏定义数组的大小,例如#define ARRAY_SIZE 50,然后在两个源文件中都包含这个。h文件,通过直接访问ARRAY_SIZE来得到定义在不同。c文件中的数组的大小。

  3)、设置数组的最后一个元素为特殊值,例如0,-1,NULL等,然后我们通过遍历数组来寻找这个特殊的结尾元素,从而判断数组的长度(这个办法效率低,也是笨笨的)。

  原因很简单,稍微注意一点不难发现,在定义结构list的右花括弧后面加一个分号就可以解决这个问题:

  好了,问题是解决了,但,你知道这个错误究竟导致了什么致命问题吗?问题不是表面上那么简单的,OK,让我们来看看事情背后的。

  当调用函数Func的时候,是把结构变量stY的值拷贝一份到调用栈中,从而作为参数传递给函数FUNC的,这个叫做C语言的参数值传递。我相信这个你一定很清楚,那么,你应该知道:如果函数的返回值是结构变量的话,函数应该如何将值返回给调用者呢?且看下面这段代码:

  此时函数Func的返回值是一个结构类型的值,这个返回值被放在内存中一个恐怖的地方,同时安排了一个指针指向这个地方(暂时称为“神秘指针”),而这个指针会由C语言的编译器作为一个隐藏参数传递给函数Func.当函数Func返回时,编译器生成的代码将这个由隐藏指针指向的内存区的值拷贝到返回结构stY中,从而完成将结构变量值返回给调用者。

  因为struct list {……}的定义后面没有加分号,导致主函数main (argc, argv)被编译器理解为是一个返回值为结构变量的函数,从而期望得到除了argc和argv以外的第三个参数,也就是我们提到的那个隐含传入的“神秘指针”。可是,大家知道,这里函数是main函数,main函数的参数是由程序中的启动代码(startup code)提供的。而启动代码当然认为main()天生就应该只得到两个参数,要“神秘指针”,当然没有,如此一来, main()在返回时自作主张地去调用栈中访问它的那个并不存在的第三个参数(即神秘指针),这样导致非法访问,产生致命问题。这才是这个问题的真正根源。

  1)、尽量将结构变量的指针而不是结构本身作为函数参数,否则函数调用时内存拷贝的开销可不小,尤其是对那些调用频繁、结构体大的情况。

  后果严重,运行的结果是程序崩溃,通过运行调试我们可以看到,经过GetMemory后,Test函数中的 str仍旧是NULL.可想而知,一调用strcpy(str, hello world);程序必然崩溃了事。

  C编译器总是会为函数的每个参数制作临时副本,指针参数p的副本是 _p,编译器使 _p = p.如果函数体内的程序修改了_p的内容,就导致参数p的内容作相应的修改。这就是指针可以用作输出参数的原因。在本例中,_p申请了新的内存,只是把_p所指的内存地址改变了,但是p丝毫未变。所以函数GetMemory并不能输出任何东西,如果想要输出动态内存,请使用指向指针的指针,或者,使用指向引用的指针。

  问题:头文件和包含它的。c文件一同编译,问下面的代码非常短小,看起来毫无问题,但编译器会报告一个错误,请问问题可能出现在什么地方?

  不用盯着int myint = 0;看,这一句赋值应该是C语言中最简单的语句,问题肯定不会出在它身上,那么问题只可能出现在someheader.h中,最常见的就是该头文件的最后一行的声明(函数也好,变量也好)没有用分号;结尾,那么编译器会将它和myint变量结合起来考虑,自然就会出错了。

  结论:被包含的头文件是和.c文件一起编译的,头文件中的问题会反映到.c文件编译中去的,。

  推荐:

  

0
0
0
0
0
0
0
0
下一篇:没有资料

相关阅读

网友评论 ()条 查看

姓名: 验证码: 看不清楚,换一个

推荐文章更多

热门图文更多

最新文章更多

关于联系我们 - 广告服务 - 友情链接 - 网站地图 - 版权声明 - 人才招聘 - 帮助

郑重声明:本站资源来源网络 如果侵犯了你的利益请联系站长删除

CopyRight 2010-2012 技术支持 FXT All Rights Reserved