<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 牛人業(yè)話 > C語言的那些小秘密之變參函數(shù)的實(shí)現(xiàn)

          C語言的那些小秘密之變參函數(shù)的實(shí)現(xiàn)

          作者: 時(shí)間:2015-03-06 來源:網(wǎng)絡(luò) 收藏

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

          本文引用地址:http://www.ex-cimer.com/article/270588.htm

            leave指令所做的操作相當(dāng)于如下兩條指令:

            movl %ebp, %esp

            popl %ebp

            ret指令所做的操作相當(dāng)于如下指令:

            pop %eip

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

            到這兒為止是乎應(yīng)該是說結(jié)束的時(shí)候了,但是細(xì)心的讀者可能發(fā)現(xiàn)了一個(gè)問題,就是我們?cè)谧畛踅o出的代碼部分有一句紅色標(biāo)記的代碼,如下:

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

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

            #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;

            }

            運(yùn)行結(jié)果為:



            顯然運(yùn)行結(jié)果是錯(cuò)誤的,為什么會(huì)出現(xiàn)這樣的錯(cuò)誤呢,我們暫且不分析,先來看看我們接下來做的修改:

            #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) //注意對(duì)比紅色部分的變化

            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;

            }

            運(yùn)行結(jié)果如下:



            運(yùn)行結(jié)果正確。

            現(xiàn)在來分析下為什么會(huì)出現(xiàn)這兩種結(jié)果呢,看看下面我給出的這個(gè)圖解和代碼應(yīng)該就能夠很清楚的理解為什么會(huì)出現(xiàn)以上的兩種運(yùn)行結(jié)果了。



            代碼如下:

            #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;

            }

            運(yùn)行結(jié)果為:



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

            #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;

            }

            注意對(duì)比前后代碼的變化部分!!!

            運(yùn)行結(jié)果如下:



            首先看看給出的圖,int指針?biāo)赶虻膯卧加兴膫€(gè)字節(jié)的空間,而char指針?biāo)赶虻膯卧徽加幸粋€(gè)字節(jié)的空間。所以如果是整形指針想要取下一個(gè)參數(shù),只需加1,但是如果是char指針,如果當(dāng)前參數(shù)是int型,那么想要取下一個(gè)參數(shù)就要加4才能實(shí)現(xiàn)。但是值得注意的是,int*和char*所占的存儲(chǔ)單元都是4個(gè)字節(jié),這是由我們所使用的32位計(jì)算機(jī)本身確定的。為了加深大家的印象,特地給出如下代碼:

            #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;

            }

            運(yùn)行結(jié)果如下:



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

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

          樹莓派文章專題:樹莓派是什么?你不知道樹莓派的知識(shí)和應(yīng)用

          c語言相關(guān)文章:c語言教程



          上一頁 1 2 下一頁

          關(guān)鍵詞: C語言 函數(shù)

          評(píng)論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();