亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

水滴石穿C語言之編譯器引出的問題

2019-11-17 05:16:42
字體:
來源:轉載
供稿:網友
基本解釋
  • 本節主要探討C編譯器下面兩方面的特點所引發的一系列常見的編程問題。
  • 對C文件進行分別編譯:
    C程序通常由幾個小程序(.c文件)組成,編譯器將這幾個小程序分別編譯,然后通過鏈接程序將它們組合在一起形成一個目標代碼。由于編譯器每次只能編譯一個文件,因此它不能立即檢查需要幾個源文件配合才能發現的錯誤。
  • 對函數的參數和返回值建立臨時變量
    C編譯器會對函數的參數建立臨時參數,也可能會對函數的返回值隱含傳遞一個指針。因為這些臨時變量的隱含性存在,使得在某些情況下,非凡是有指針存在的時候,會引發一系列的問題。
  • C文件中所包含的頭文件會和C語言一同編譯

    C語言中被包含的頭文件是和.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等,然后我們通過遍歷數組來尋找這個非凡的結尾元素,從而判定數組的長度(這個辦法效率低,也是笨笨的)。

   問題:函數返回值隱含傳遞指針

  下面的代碼可以正常工作,但是在程序結束時會有一個致命錯誤產生。究竟是什么原因呢?

strUCt list
{
 char *item;
 struct list *next;
}

main (argc, argv)
{
 ...
}
  答案與分析:

  原因很簡單,稍微注重一點不難發現,在定義結構list的右花括弧后面加一個分號就可以解決這個問題:

struct list
{
 char *item;
 struct list *next;
};//缺了這個分號可不行!
  好了,問題是解決了,但,你知道這個錯誤究竟導致了什么致命問題嗎?問題不是表面上那么簡單的,OK,讓我們來看看事情背后的真相。

  首先看一看下面這段代碼:

VOID Func ( struct my_struct stX)
{
 .......
}
struct my_struct stY = {...};
Func (stY);
  當調用函數Func的時候,是把結構變量stY的值拷貝一份到調用棧中,從而作為參數傳遞給函數FUNC的,這個叫做C語言的參數值傳遞。我相信這個你一定很清楚,那么,你應該知道:假如函數的返回值是結構變量的話,函數應該如何將值返回給調用者呢?且看下面這段代碼:

struct my_structFunc (VOID)
{
 .......
}
struct my_struct stY = Func();
  此時函數Func的返回值是一個結構類型的值,這個返回值被放在內存中一個陰暗恐怖的地方,同時安排了一個指針指向這個地方(暫時稱為“神秘指針”),而這個指針會由C語言的編譯器作為一個隱藏參數傳遞給函數Func。當函數Func返回時,編譯器生成的代碼將這個由隱藏指針指向的內存區的值拷貝到返回結構stY中,從而完成將結構變量值返回給調用者。

  你明白了上述所講的東東,那么今天問題的真正原因也就呼之欲出了:

  因為struct list {...}的定義后面沒有加分號,導致主函數main (argc, argv)被編譯器理解為是一個返回值為結構變量的函數,從而期望得到除了argc和argv以外的第三個參數,也就是我們上面提到的那個隱含傳入的“神秘指針”??墒?,大家知道,這里函數是main函數,main函數的參數是由程序中的啟動代碼(startup code)提供的。而啟動代碼當然認為main()天生就應該只得到兩個參數,要“神秘指針”,當然沒有,如此一來, main()在返回時自作主張地去調用棧中訪問它的那個并不存在的第三個參數(即神秘指針),這樣導致非法訪問,產生致命問題。這才是這個問題的真正根源。

  建議:

   1)、盡量將結構變量的指針而不是結構本身作為函數參數,否則函數調用時內存拷貝的開銷可不小,尤其是對那些調用頻繁、結構體大的情況。

   2)、結構定義的后面一定要加分號,經過上面我的大段講述,我相信你不會犯相同的錯誤 問題:編譯器會給函數的參數隱含制造臨時副本

  請問運行下面的Test函數會有什么樣的結果?

void GetMemory2(char **p, int num)
{
 *p = (char *)malloc(num);
}

void Test(void)
{
 char *str = NULL;
 GetMemory(&str, 100);
 strcpy(str, "hello");
 PRintf(str);
}
  答案與分析:

  這是林銳的《C/C++高質量編程指南》上面的例子,拿來用一下。

  這樣調用會產生如下兩個后果:

  1)、能夠輸出hello

  2)、內存泄漏

   另一個相關問題:

  請問運行Test函數會有什么樣的結果?


void GetMemory(char *p)
{
 p = (char *)malloc(100);
}

void Test(void)
{
 char *str = NULL;
 GetMemory(str);
 strcpy(str, "hello world");
 printf(str);
}
  答案與分析:

  后果嚴重,運行的結果是程序崩潰,通過運行調試我們可以看到,經過GetMemory后,Test函數中的 str仍然是NULL??上攵徽{用

strcpy(str, "hello world");
  程序必然崩潰了事。

  原因分析:

   C編譯器總是會為函數的每個參數制作臨時副本,指針參數p的副本是 _p,編譯器使 _p = p。假如函數體內的程序修改了_p的內容,就導致參數p的內容作相應的修改。這就是指針可以用作輸出參數的原因。在本例中,_p申請了新的內存,只是把_p所指的內存地址改變了,但是p絲毫未變。所以函數GetMemory并不能輸出任何東西,假如想要輸出動態內存,請使用指向指針的指針,或者,使用指向引用的指針。

  問題:頭文件和包含它的.c文件一同編譯問

  下面的代碼非常短小,看起來毫無問題,但編譯器會報告一個錯誤,請問問題可能出現在什么地方?

#include "someheader.h"
int myint = 0;
  答案與分析:

  不用盯著int myint = 0;看,這一句賦值應該是C語言中最簡單的語句,問題肯定不會出在它身上,那么問題只可能出現在someheader.h中,最常見的就是該頭文件的最后一行的聲明(函數也好,變量也好)沒有用分號";"結尾,那么編譯器會將它和myint變量結合起來考慮,自然就會出錯了。

  這個問題主要是提醒你,在定位問題時思路要拓寬一點,可能要考慮一下所包含的頭文件是否有問題。

  結論:被包含的頭文件是和.c文件一起編譯的,頭文件中的問題會反映到.c文件編譯中去的,切記。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品三级美女白浆呻吟| 亚洲人成77777在线观看网| 91久久在线观看| 清纯唯美日韩制服另类| 国产亚洲人成a一在线v站| 日本中文字幕久久看| 日韩大陆欧美高清视频区| 国产精品偷伦免费视频观看的| 亚洲精品国产成人| 成人有码视频在线播放| 亚洲第一福利网| 日本午夜人人精品| 亚洲aaa激情| 欧美俄罗斯乱妇| 九九热这里只有精品免费看| 欧美亚洲国产日韩2020| 高清视频欧美一级| 欧美视频在线免费| 亚洲九九九在线观看| 成人av在线亚洲| 国产一区二区三区直播精品电影| 久久久久久成人精品| 国产精品影院在线观看| 国产精品丝袜一区二区三区| 91九色视频在线| 精品久久中文字幕久久av| 色综合久久悠悠| 青青草原一区二区| 日韩免费在线播放| 国产成人精品视频在线| 国产一区二区三区视频在线观看| 国产91网红主播在线观看| 91精品啪aⅴ在线观看国产| 久久综合国产精品台湾中文娱乐网| 91精品久久久久久久久久入口| 国产欧美一区二区白浆黑人| 日韩成人在线播放| 欧美www视频在线观看| 午夜精品久久久久久久白皮肤| 亚洲天堂日韩电影| 欧美肥老妇视频| 亚洲xxxxx| 欧美午夜精品久久久久久久| 国内精久久久久久久久久人| 日本高清+成人网在线观看| 欧美日韩亚洲网| 日韩在线视频观看正片免费网站| 国内精品免费午夜毛片| 久久99精品国产99久久6尤物| 国产精品亚洲自拍| 久久久电影免费观看完整版| 国产精品视频免费观看www| 国产精品久久久久久久9999| 午夜精品福利在线观看| 精品成人乱色一区二区| 狠狠躁夜夜躁久久躁别揉| 日本国产一区二区三区| 高跟丝袜欧美一区| 自拍偷拍亚洲精品| 欧美不卡视频一区发布| 国产亚洲成av人片在线观看桃| 大胆欧美人体视频| 这里只有精品久久| 国产精品久久久久久久久久尿| 亚洲视频在线观看| 欧美电影免费观看高清完整| 日韩在线www| 日韩亚洲精品电影| 欧美大人香蕉在线| 亚洲一区www| 久久久精品亚洲| 日韩精品高清在线观看| 日韩福利伦理影院免费| 亚洲国产精品成人一区二区| 国产在线视频2019最新视频| 精品无人国产偷自产在线| 亚洲色图日韩av| 国产精品入口夜色视频大尺度| 欧美成人午夜免费视在线看片| 中文字幕亚洲欧美日韩高清| 国产精品免费电影| 久久艹在线视频| 97成人超碰免| 欧美日韩精品在线播放| 亚洲精品电影久久久| 国产精品一区二区电影| 精品调教chinesegay| 国产香蕉精品视频一区二区三区| 亚洲免费精彩视频| 2019中文字幕免费视频| 91在线色戒在线| 亚洲欧洲日产国码av系列天堂| 国产成人福利视频| 亚洲精品日韩在线| 日韩风俗一区 二区| 成人97在线观看视频| 国产成人鲁鲁免费视频a| 日韩成人在线视频网站| 亚洲男子天堂网| 亚洲成人黄色在线| x99av成人免费| 国模视频一区二区| 91大神福利视频在线| 日韩欧美国产骚| 欧美成人手机在线| 亚洲在线免费看| 91免费看视频.| 欧美日韩中文字幕日韩欧美| 91精品国产精品| 伊人久久免费视频| 国产精品视频午夜| 国产亚洲欧美日韩美女| 亚洲毛片一区二区| 欧美体内谢she精2性欧美| 2019亚洲男人天堂| 亚洲国产高潮在线观看| 精品高清一区二区三区| 日本精品性网站在线观看| 欧美性精品220| 2019精品视频| 欧美日韩综合视频| 久久69精品久久久久久久电影好| 精品中文字幕在线观看| 亚洲第一av网站| 一区二区亚洲精品国产| 国产免费一区二区三区在线观看| 中文字幕国产亚洲| 免费91麻豆精品国产自产在线观看| 97热在线精品视频在线观看| 精品丝袜一区二区三区| 日韩理论片久久| 国产一区二区三区在线播放免费观看| 最近2019中文字幕mv免费看| 国产精品va在线播放| 最新69国产成人精品视频免费| 美女999久久久精品视频| 午夜精品久久久久久99热| 欧美性生交xxxxx久久久| 亚洲伊人久久综合| 国模精品视频一区二区三区| 国产一区红桃视频| 国产精品成人免费电影| 欧美激情视频播放| 2019中文字幕免费视频| 欧美日韩一区二区免费在线观看| 国产精品成人一区二区三区吃奶| 亚洲欧美国产va在线影院| 久热精品视频在线观看一区| 91久久精品国产91性色| 久久天天躁狠狠躁夜夜爽蜜月| 日韩av一区二区在线观看| 国产日韩欧美自拍| 国产91色在线播放| 最近日韩中文字幕中文| 国产亚洲一区二区精品| 久久躁狠狠躁夜夜爽| 亚洲国产欧美一区二区三区久久| 日本电影亚洲天堂| 麻豆国产精品va在线观看不卡| 欧美成人免费小视频| 日韩在线视频免费观看| 国产一区在线播放| 亚洲精品日韩av| 日本一区二区在线免费播放|