天天看點

C語言關于變量定義未使用編譯警告warring1.警告warring的産生2.總結

C語言關于變量定義未使用編譯警告warring

  • 1.警告warring的産生
    • 1.1具體警告warring
    • 1.2解決方案
      • 1.2.1利用attribute 機制
      • 1.2.2利用void關鍵字
  • 2.總結

1.警告warring的産生

在日常寫代碼的過程中,定義的變量有時候隻需要接收某個變量,僅僅對這個變量進行指派,變量沒有進行實際運算操作,這個時候編譯器就會有警告。如果是這個原因導緻的警告warring,你不處理也不會影響程式的運作。但是當你的工程所有編譯的時候,總有幾個warring影響你的最終結果,你要是個完美主義者或者是個處女座,總想解決這幾個warring。

1.1具體警告warring

1.Keil MDK會有如下警告:

**..main\main.c(36): warning:  #177-D: variable "i" was declared but never referenced
uint8_t i = 0;
           

2.IAR的編譯警告資訊:

告訴你在main.c源檔案的第36行,有個變量i聲明了但沒有使用,這些編譯的器的警告資訊描述都是大同小異。

3.用gcc編譯器,打開警告資訊編譯:

gcc test.c -o test -Wall
           

編譯資訊如下:

test.c: In function ‘main’:
test.c:6:6: warning: variable ‘a’ set but not used [-Wunused-but-set-variable]
  int a = 0;
      ^
           

告訴你在main.c源檔案的第6行,有個變量a聲明了但沒有使用。

1.2解決方案

如何解決這個樣的問題,這裡給出兩個解決方案(其實我也就隻知道這兩個,哈哈~~):

1.2.1利用attribute 機制

attribute 單詞意思屬性,就是用于配置變量或者代碼段的屬性。我們常用配置結構體的位元組對齊,或者将代碼編譯到記憶體的固定位址。我們這裡利用其中的一個屬性__attribute__((unused))來表示這個變量可能會沒有使用到,如下例子:

1 #include <stdio.h>
  2
  3 int main(void)
  4 {
  5     int a __attribute__((unused));
  6
  7     return 0;
  8 }
           

就是告訴編譯器變量a定義了,但有可能是不使用,是以編譯器就不會有警告,因為你已經提前打過招呼了。

為了驗證增加這個屬性會不會對變量有所影響,我們将代碼改回有警告的:

1 #include <stdio.h>
  2
  3 int main(void)
  4 {
  5     //int a __attribute__((unused));
  6     int a;
  7
  8     return 0;
  9 }
           

我們可以将看編譯後的反彙編檔案進行對比發現檔案都是一樣的,如下是main函數部分的反彙編:

是以這兩段的程式是一樣的,增加屬性并不會改變什麼性質。

120 00000000004004d6 <main>:
121   4004d6:   55                      push   %rbp
122   4004d7:   48 89 e5                mov    %rsp,%rbp
123   4004da:   b8 00 00 00 00          mov    $0x0,%eax
124   4004df:   5d                      pop    %rbp
125   4004e0:   c3                      retq
126   4004e1:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
127   4004e8:   00 00 00
128   4004eb:   0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
           

1.2.2利用void關鍵字

void在C語言的作用,很多時候使用僅僅用于無參數傳回,這隻是一個很基本的功能。很多時候我們定義函數指針、NULL的時候,我們都會使用到void這個關鍵字。void的意思是空、無的意思,我們利用這個特性将變量操作一波,如下:

1 #include <stdio.h>
  2
  3 int main(void)
  4 {
  5     //int a __attribute__((unused));
  6     int a;
  7     (void)(a);
  8     return 0;
  9 }
           

這裡我們将變量a引用了一次,在前面增加(void),這樣就能夠避免編譯器的警告,可以了解為告訴編譯器我已經調用了這個變量,并且操作了它,這樣編譯器就不會有警告資訊了。我們通過反彙編能夠發現,這樣操作以後,和前邊attribute的是一樣的,并不影響代碼。

2.總結

最後我們得出結論,這兩種花裡胡哨的操作,其實不改變程式的任何執行,隻不過是為了去除編譯器的警告。正常使用的話會選擇用void的比較多(就目前我發現),這個也比較好了解,因為我們寫代碼是給别人看的。通過這兩種方法有沒有發現C語言是越學越不懂,越學越有趣呢。最後的最後我們在程式設計的時候一定要做到0 error和0 warring,這樣才是一名好的打工仔!!

繼續閱讀