新聞中心

        EEPW首頁 > 嵌入式系統 > 牛人業話 > C語言的那些小秘密之變參函數的實現

        C語言的那些小秘密之變參函數的實現

        作者: 時間:2015-03-06 來源:網絡 收藏

          其中有幾條指令在此講解下。

        本文引用地址:http://www.104case.com/article/270588.htm

          leave指令所做的操作相當于如下兩條指令:

          movl %ebp, %esp

          popl %ebp

          ret指令所做的操作相當于如下指令:

          pop %eip

          如果有對AT&T匯編語法規則不懂的,可以看看我前面寫的那篇文章。

          到這兒為止是乎應該是說結束的時候了,但是細心的讀者可能發現了一個問題,就是我們在最初給出的代碼部分有一句紅色標記的代碼,如下:

          #define va_start(arg, start) arg = (va_list)(((char*)&(start)) + sizeof(start))

          為什么要把這句代碼單獨拿出來講解呢,肯定是有原因的,因為((char*)&(start)) +sizeof(start)這句代碼的特殊性在于使用了(char*)進行強制轉換,在這里為什么不使用(int*)進行強制轉換呢,如改為如下代碼:

          #include

          #include

          #define va_list void*

          #define va_arg(arg, type) *(type*)arg; arg = (char*)arg + sizeof(type);

          #define va_start(arg, start) arg = (va_list)(((int*)&(start)) + sizeof(start)) //修改為(int*)

          int sum(int nr, ...)

          {

          int i = 0;

          int result = 0;

          va_list arg = NULL;

          va_start(arg, nr);

          for(i = 0; i < nr; i++)

          {

          result += va_arg(arg, int);

          }

          return result;

          }

          int main(int argc, char* argv[])

          {

          printf("%dn", sum(4, 100,100,100,100));

          printf("%dn", sum(3, 200, 200, 200));

          return 0;

          }

          運行結果為:



          顯然運行結果是錯誤的,為什么會出現這樣的錯誤呢,我們暫且不分析,先來看看我們接下來做的修改:

          #include

          #include

          #define va_list void*

          #define va_arg(arg, type) *(type*)arg; arg = (char*)arg + sizeof(type);

          #define va_start(arg, start) arg = (va_list)(((int*)&(start)) + sizeof(start)/4) //注意對比紅色部分的變化

          int sum(int nr, ...)

          {

          int i = 0;

          int result = 0;

          va_list arg = NULL;

          va_start(arg, nr);

          for(i = 0; i < nr; i++)

          {

          result += va_arg(arg, int);

          }

          return result;

          }

          int main(int argc, char* argv[])

          {

          printf("%dn", sum(4, 100,100,100,100));

          printf("%dn", sum(3, 200, 200, 200));

          return 0;

          }

          運行結果如下:



          運行結果正確。

          現在來分析下為什么會出現這兩種結果呢,看看下面我給出的這個圖解和代碼應該就能夠很清楚的理解為什么會出現以上的兩種運行結果了。



          代碼如下:

          #include

          int main()

          {

          int a = 12;

          int *p_int = &a;

          char *p_char = (char*)&a;

          printf( "%d t", sizeof(char));

          printf( "%d t", sizeof(int));

          printf( "%d t", p_int+1);

          printf( "%d t", p_char+1);

          return 0;

          }

          運行結果為:



          修改以上紅色部分的代碼,得到如下代碼:

          #include

          int main()

          {

          int a = 12;

          int *p_int = &a;

          char *p_char = (char*)&a;

          printf( "%d t", sizeof(char));

          printf( "%d t", sizeof(int));

          printf( "%d t", p_int+1);

          printf( "%d t", p_char+4);

          return 0;

          }

          注意對比前后代碼的變化部分!!!

          運行結果如下:



          首先看看給出的圖,int指針所指向的單元占有四個字節的空間,而char指針所指向的單元只占有一個字節的空間。所以如果是整形指針想要取下一個參數,只需加1,但是如果是char指針,如果當前參數是int型,那么想要取下一個參數就要加4才能實現。但是值得注意的是,int*和char*所占的存儲單元都是4個字節,這是由我們所使用的32位計算機本身確定的。為了加深大家的印象,特地給出如下代碼:

          #include

          int main()

          {

          int a = 12;

          int *p_int = &a;

          char *p_char = (char*)&a;

          printf( "%d t", sizeof(char*));

          printf( "%d t", sizeof(int*));

          return 0;

          }

          運行結果如下:



          到此為止就是真的該結束了,總不能沒完沒了的講下去吧,呵呵……

          很多代碼僅僅是修改了一點,我都貼出了完整的代碼,是希望你在閱讀的過程中能直接copy過去,看看運行效果,加深下印象。還是那句話,C語言博大精深,我還是C語言菜鳥,以上內容難免有錯。

        樹莓派文章專題:樹莓派是什么?你不知道樹莓派的知識和應用

        c語言相關文章:c語言教程



        上一頁 1 2 下一頁

        關鍵詞: C語言 函數

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 商丘市| 金阳县| 西贡区| 太谷县| 远安县| 岐山县| 和林格尔县| 横山县| 安陆市| 阳东县| 车致| 江都市| 睢宁县| 德昌县| 玛纳斯县| 七台河市| 长泰县| 青阳县| 多伦县| 高邑县| 湟源县| 化州市| 武城县| 临西县| 西乡县| 汝阳县| 肃南| 蓬安县| 嘉定区| 华坪县| 金湖县| 松潘县| 花莲县| 庆元县| 仁怀市| 承德市| 星子县| 高唐县| 荣成市| 黄石市| 平原县|