首先,看段代碼
1 #include <stdio.h>
23 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級優先級(左結合) ,逗號運算符。