fgets,優先級問題導致Segmentation fault

首先,看段代碼

 

 1 #include <stdio.h>

  2 
  3 int main()
  4 {
  5     char buffer[BUFSIZ+1];
  6     FILE *fpin;
  7 
  8     if((fpin = fopen("test","r") == NULL))
  9     {
 10         printf("can't open test.\n");
 11         return 1;
 12     }
 13 
 14     while(fgets(buffer,BUFSIZ,fpin) != NULL)
 15     {
 16         if(fputs(buffer,stdout) == EOF)
 17         {
 18             printf("fputs error to pipe.\n");
 19             return 1;
 20         }
 21     }

 22 }

這段代碼運行會產生段錯誤:Segmentation fault

經過調試gdb調試發現段錯誤是第14行代碼處 fgets(buffer,BUFSIZ,fpin) 產生的。

這裏的fpin 是 NULL。

在編程中以下幾類做法容易導致段錯誤,基本是是錯誤地使用指針引起的 
1)訪問系統數據區,尤其是往 系統保護的內存地址寫數據最常見就是給一個指針以0地址 
2)內存越界(數組越界,變量類型不一致等) 訪問到不屬於你的內存區域 

所以再查找fpin 是 NULL的原因

仔細看第8行代碼

if((fpin = fopen("test","r") == NULL))

因爲 == 的優先級高於 = 且  ==號是左結合,=是右結合,所以這句話等價於

fpin = ( fopen("test","r") == NULL )  

即 fopen的返回值 與 NULL做 邏輯比較運算,將返回的NULL 複製給fpin,

所以這句話並沒有起到檢查fpin指針的作用

故第8行代碼應該爲

if((fpin = fopen("test","r"))== NULL)


運行結果正常:

zyx@zyx-Lenovo:~/Desktop/pipe$ cat test 
hello,aa!
the second line!
i know i can!
you can too!
zyx@zyx-Lenovo:~/Desktop/pipe$ ./segment 
hello,aa!
the second line!
i know i can!
you can too!


另附C運算符優先級表:

C語言運算符分類
  1級優先級(左結合) 
  () 圓括號;[]下標運算符;->指向結構體成員運算符;. 結構體成員運算符。 
  2級優先級(右結合) 
  !邏輯非運算符;~按位取反運算符;++前綴增量運算符;--前綴減量運算符;+正號運算符;-負號運算符;(類型)類型轉換運算符;*指針運算符;&地址運算符;sizeof長度運算符。 
  3級優先級(左結合) 
  *乘法運算符;/除法運算符;%取餘運算符。 
  4級優先級(左結合) 
  +加法運算符;-減法運算符。 
  5級優先級(左結合) 
  <<左移運算符;>>右移運算符。 
  6級優先級(左結合) 
  <、<=、>、>=關係運算符。 
  7級優先級(左結合) 
  ==等於運算符;!=不等於運算符。 
  8級優先級(左結合) 
  &按位與運算符。 
  9級優先級(左結合) 
  ^按位異或運算符。 
  10級優先級(左結合) 
  |按位或運算符。 
  11級優先級(左結合) 
  &&邏輯與運算符。 
  12級優先級(左結合) 
  ||邏輯或運算符。 
  13級優先級(右結合) 
  ? :條件運算符。 
  14級優先級(右結合) 
  =、 +=、 -=、 *=、 /=、 %=、 &=、 ^=、 |=、 <<=、 >>=賦值運算符。 
  15級優先級(左結合) 
  ,逗號運算符。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章