C語言中容易被忽略的細節(第四篇)

轉載時自己也能回顧一遍,所以還是有必要轉載的。

第一篇鏈接:C語言中容易被忽略的細節(第一篇)

第二篇鏈接:C語言中容易被忽略的細節(第二篇)

第三篇鏈接:C語言中容易被忽略的細節(第三篇)


1、void*類型的指針不能參與算術運算,只能進行賦值、比較和sizeof操作的原因?

指針的算術運算還要包含指針所指對象的字節數信息。


2、不能把“&”單獨用於一個非變量的東西。不能對字面常量使用“&”來取其地址,因爲字面常量保存在符號表中,沒有地址概念。數組名是一個指針常量,不能修改數組名的值。例如以下語句1與語句2是等價的:

  1. int a[10];                  //語句1  
  2. int *const a;               //語句2  
  3.   
  4. int b[3][4];                //語句1  
  5. int (*const b)[4];          //語句2  
  6.   
  7. int c[3][4][5];             //語句1  
  8. int (*const c)[4][5];       //語句2  


3、return 0與exit(0)的幾點區別

(1)exit結束正在運行的整個程序,只要調用exit就結束,它將參數返回給OS,把控制權交給操作系統;return退出當前函數,返回函數值,把控制權交給調用函數;

(2)exit是系統調用級別,它表示一個進程的結束;return是語言級別的,它表示調用堆棧的返回。

(3)main函數結束時也會隱式地調用exit函數,它將刪除進程使用的內存空間,同時把錯誤信息返回給父進程。

(4)main函數返回一個整型值與該值調用exit是等價的。


4、static修飾符是一個能夠減少命名衝突的有用工具。例如:static int a;將a的作用域限制在一個源文件內,對於其他源文件,a是不可見的。可以在多個源文件中定義同名的變量a,只要所有的變量a都被定義爲static,或者僅僅只有其中一個變量不是static。static修飾符也適用於函數。


5、C語言允許程序員寫操作前控制產生的輸出數據量,這種控制能力是通過庫函數setbuf實現的。例如:setbuf(stdout, buf);語句將通知輸入/輸出庫,所有寫入到stdout的輸出都使用buf作爲輸出緩衝區,直到buf緩衝區被填滿或程序員直接調用fflush,buf緩衝區的內容才實際寫入到stdout中。緩衝區的大小由系統頭文件<stdio.h>中的BUFSIZ定義。《C陷阱與缺陷》中有一個例子:

  1. #include <stdio.h>  
  2.   
  3. int main(void)  
  4. {  
  5.     char c;  
  6.     char buf[BUFSIZ];  
  7.     setbuf(stdout, buf);  
  8.     while ((c = getchar()) != EOF)  
  9.         putchar(c);  
  10.   
  11.     return 0;  
  12. }  

以上程序是錯誤的。buf緩衝區最後一次被清空是在main函數結束之後,作爲程序交回控制給操作系統之前C運行時庫所必須進行清理工作的一部分。在此之前buf字符數組已經被釋放了。修改的方法有3種:

(1)定義緩衝數組爲靜態數組static char buf[BUFSIZ];

(2)將緩衝數組拿到main函數外;

(3)動態分配緩衝區,程序中並不主動釋放分配的緩衝區。setbuf(stdout, malloc(BUFSIZ));

備註:

(1)由於緩衝區是動態分配的,所以main函數結束時並不會釋放該緩衝區,這樣C運行時庫進行清理工作時就不會發生緩衝區已釋放的情況。

(2)如果malloc調用失敗,返回NULL指針,此時標準輸出不需要進行緩衝。

(3)對於由寫操作打開的文件,調用fflush將導致輸出緩衝區的內容被實際地寫入該文件。


6、爲什麼向函數傳遞多維數組時候不需要說明第一維長度而必須說明其他維長度?

(1)數組元素在內存中按照“行優先”規則存儲,需要列數確定一行有多少元素;

(2)編譯器在計算元素地址時不需要數組第一維的長度,但需要所有其他維的長度信息;

(3)C/C++不對數組進行越界訪問檢查,對編譯器來說不需要知道第一維的長度。


7、C語言將多維數組轉換爲數組指針。以下4種表達方式是等價的:
  1. a[i][j];  
  2. *(a[i] + j);  
  3. (*(a + i))[j];  
  4. *(*(a + i) + j);  

8、在語義上,下標操作符返回的是一個元素的引用。例如語句1和語句2是等價的:

  1. //語句1  
  2. a[3] = 100;       
  3.   
  4. //語句2  
  5. int &ri = a[3];  
  6. ri = 100;  

9、不能使用一個元素類型的指針來接收動態創建的多維數組的返回地址,因爲一個多維數組在語義上並不等價於一個指向其元素類型的指針,它等價於一個“指向數組的指針”。例如以下用法是正確的:

  1. char *q = new char[5];  
  2. delete []q;   
  3.   
  4. char (*p)[4] = new char[5][4];  
  5. delete []p;  

10、(1)標號(lable)是具有函數作用域的唯一一種標識符。無論標號定義在函數哪行,函數內嵌套多深,它都能在函數體內任何一個地方訪問到。標號一般用在goto語句中,如果goto語句沒有使用到該標號,那麼該標號將被忽略。(2)當局部變量與某一個全局變量同名時,在函數內部將遮蔽該全局變量。此時在函數內部可通過一元作用域解析運算符來引用全局變量,如::a。

轉載自:http://blog.csdn.net/mengwang024/article/details/40734969

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