C與指針瑣碎點

1、結構體定義結束要有分號,函數定義沒有分號;
2、結構體【結構體數組】變量初始化可以用大括號形式,但C中不能用大括號進行賦值,注意賦值和初始化的區別;
3、條件編譯的三種類型:

#define A 1 #define A #define A
#if A #ifdef A #ifndef A
#define B 1 #define B 1 #define B
#else #else #else
#define D 1 #define D 1 #define D
#endif #endif #endif


4、strlen函數的判斷條件:*string++!='\0'

5、左值與右值的理解:

數組名是一個指針常量

左值意味着一個位置,右值意味着一個值

——參見《C和指針》[《POINTERS ON C》]Kenneth A. Reek著 5.4.3&6.11節指針表達式

6、printf中%s輸出是輸出字符串時所用的格式符,在輸出項中給出字符指針變量名string,則系統先輸出它所指向的一個字符數據,然後自動使string加1,使之指向下一個字符,然後在輸出一個字符......如此直到遇到字符串結束標誌'\0'爲止。可以進行字符串的整體輸出

printf中%c輸出則需要給定變量,而不是地址,例如:

char *p_char= 'F';

printf("%c",*p_char);

而printf("%c",p_char);則不會輸出


7、字符型指針與數值型指針的最大不同在於:

char *a="china";

printf("%s\n",a);【給定指針地址,輸出的是指針指向的內容】

int *a;

int i=10;

a=&i;

printf("%d\n",a);【輸出的是變量i的地址,而非指針所指向的內容】

printf("%d\n",*a);【輸出的是指針所指向的內容】

8、二級指針應用於指針數組,可以方便進行指針數組元素的自增索引或遍歷

【可以將二級指針看從存在三類可用地址,一類是&p,一類是p+i,也就是指針數組元素的地址,最後一類是*p,也就是字符串的首地址】

char *name[]={"ABC","DEFdhoa","GHJL:","hoaf"}; //定義字符指針數組

char **p;

p=name;//二級指針的初始化,或者p=&name,結果都是一樣的

*(p+1)表示D的地址,即"DEFdhoa"

*(p+2)表示G的地址,即"GHJL:"

*p+1表示B的地址

*(p+1)+1表示E的地址

*(*p+1)表示B

9、能否看出下述兩個圖執行結果的差別

例一:

for( vp = & values[N_VALUES]; vp > &values[0];)

*--vp=0;

例二:

for( vp = & values[N_VALUES-1]; vp >= &values[0];vp--)

*vp=0;

標準允許指向數組元素的指針與指向數組最後一個元素後面的那個內存位置的指針進行比較,但不允許與指向數組第一個元素之前的那個內存位置的指針進行比較。即vp++可以,數組元素後面越界的第一個指針仍能與數組元素指針比較,但是vp--存在問題。


10、使用指針容易出現的錯誤



11、指針用NULL初始化,感覺沒有什麼意義,也就是空指針意義不大,除了可以作爲函數的返回值


12、位操作:

指定位置一:value | 1<<bit_number

指定位清零:value & ~(1<<bit_number)

測試指定位的值:value & 1<<bit_number


13、while(scanf("%d",&n),n!=EOF) //while(scanf("%d",&n)!=EOF)也行

在 UNIX中, EOF表示能從交互式 shell (終端) 送出 Ctrl+D (習慣性標準)。在微軟的 DOS 與 Windows 中能送出 Ctrl+Z。


14、statistic 關鍵字

因爲static變量也就是靜態變量,在程序運行過程中被聲明後就會一直保存在內存裏,所以只能聲明一次,第二次再訪問那個函數時,給靜態變量聲明同時初始化的語句就不再執行了,而靜態變量的值始終保存在內存裏,也就是上次改變以後的值。沒有static修飾的函數中的變量,只在函數被執行時佔用內存,函數執行完畢後就被銷燬,數據也就不存在了,所以每次都要聲明,值也就不會變。

15、‘%’求餘運算



16、函數形參:

function_name(char array[])使用時等價於function_name(char *array)

function_name(char array[10])也同樣表示數組名傳遞,但是數組大小限定爲10

只有數組名才能當做地址使用而不使用指針,變量名不可以這樣做,只能用取址符號獲得變量的內存地址

17、抽象數據類型就是把一些有一定關聯的基本數據類型打包,然後當做新的數據類型使用。c++類使得抽象數據類型的可操作性更強了,真正實現了面向對象。


18、stdarg.h——可變參數列表(原理:函數參數是以棧的形式存取,從右至左入棧

function(type1 para1,...)
{
va_list argp;//定義一個可變參數列表
va_start(argp,para1);//初始化把argp變量設置爲指向可變參數部分的第一個參數,也就是para1的後面那個參數
...
va_arg(argp,int);//獲取可變參數的當前參數,返回指定類型並將指針指向下一參數,該宏接受兩個參數,va_list變量和參數列表中下一個參數的類型,返回當前指向參數的值,並使va_list變量指向下一個可變參數
...
va_end(argp);//清空va_list可變參數列表
}
這些宏存在兩個基本的限制:1.這些宏無法判斷實際存在的參數的數量;2.這些宏無法判斷每個參數的類型

19、#define DEBUG(...) printf(__VA_ARGS__)

20、ERROR——"initializer element is not a constant"

 In C, global variables can only be initialized with constants, such as numeric values, NULL or fixed strings.

21、sizeof(數組名)返回的是該數組的長度,以字節爲單位

22、C語言中編譯器是不對數組的下標進行檢查,因此編寫代碼要注意防止越界

效率不是唯一的因素,通常代碼的可讀性和簡介性更重要

23、C循環效率的提高



24、儘量避免使用全局變量,本着函數“內聚性”強,“耦合性”弱的特點,函數之間只通過形參進行交互。

全局變量可供本文件的其它函數使用,存放於靜態存儲區;

局部變量只能供函數自身使用,

靜態局部變量(static)存放在靜態存儲區,兩個特點:只進行一次初始化賦值,並保留函數執行的結果;編譯會自動初始化爲0;

自動局部變量(auto)存放在動態存儲區,三個特點:每次調用臨時分配,函數結束則回收內存空間;編譯器不會進行初始化,所以結果是未知的;只有自動局部變量和形參能聲明成寄存器變量(register);

extern全局變量是爲了擴展變量的作用域,一般全局變量作用域是從變量聲明處到文件結束,如需要在更早處或別的文件中使用,則需在更早出或需要調用的文件中extern聲明;

static全局變量是爲了全局變量只能被本文件使用,而不能被其他文件引用;

static函數爲內部函數,只能被本文件的其它函數調用,而不能被其他文件引用,用於解決不同文件中的同名的內部函數;

extern函數爲外部函數,在需要調用的文件中使用,表示該函數是在其他文件中定義的外部函數;

25、關於二維數組的指針作爲函數參數

形參一:funcation_name(int *array,...)

函數使用形式包括:

*array++,通過array的自增遍歷二維數組的所有元素;
定義新的數組指針,int (*p)[10]=array;再使用(*(p+i)+j)來指定特定的數組元素;

形參二:function_name(int *array[10],...)

這種形式的指針可以直接來指定特定位置的元素,使用方法如上所示。

26、string.h

使用字符串函數首先要確保buffer足夠大,其次要注意下面的小細節:

char * strcpy(char *str1,char *str2)函數中如果str2字符串合法(含有'\0',即NUL字符),則不會產生異常錯誤;

對於strncpy則不會自動添加'\0',因此使用此函數時就要小心,以防越界造成的程序崩潰


對於strncat會在拷貝完成後,自動加上'\0'字符。

27、字符及字符串函數

字符串處理函數:(string.h)


字符處理函數:(ctype.h)



內存操作函數


28、printf打印百分號"%%"

29、關於const修飾的問題

function(char *const str,...):不能對str進行'++'操作,但可以使用*str='*'改變其值

function(char const *str,...):可以對str進行'++'操作,但不可以使用*str='*'來改變其值,如果使用“char *temp=(char *)str;”,則可以間接修改*str的值。

對進行傳入指針,最好進行拷貝,以便隨時恢復指針原始值

30、void main(int argc,char **argv[ ])

argc=執行所帶參數個數+1;

argv[0]表示字符串"./a.out"的首地址;

argv[1]表示命令所帶第一個參數的地址;

31、字符指針與字符數組區別

區別一:字符數組保存的字符串存放在內存的棧中,而字符指針指向的字符串保存在內存的靜態存儲區中

區別二:字符數組保存的字符串屬於字符串變量,可以被修改,而字符指針指向的字符串是屬於字符串常量,不能被修改。


【會出現:訪問了不存在的內存地址、訪問了系統保護的內存地址、訪問了只讀的內存地址等等情況

32、結構體

【結構體變量名不能作爲指針常量,只能代表變量,與數組名作爲指針常量有區別】

a、結構體可以進行整體賦值

typedef

{

...

}List;

List ls1,ls2;

ls1={...};

ls2=ls1;

b、結構體指針'+1'操作

如果該結構體指針指向一個結構體數組,加一表示後面那個結構體元素;

如果指向某個結構體,則爲非法操作,因爲對標量值加一;

c、結構體位對齊,即sizeof(結構體變量)不等於實際的成員佔字節的總和

具體詳見

http://www.cnblogs.com/dolphin0520/archive/2011/09/17/2179466.html

http://jayji.info/struct-bound-align/

33、數組的元素存儲於內存中連續的位置,當一個數組聲明時,它所需的內存在編譯時就被分配。

符號NULL定義於"stdio.h",它的字面常量是0;

內存動態分配函數在ANSI標準中建議在“stdlib.h”頭文件包含,而很多編譯器則要求用“malloc.h”,而不是“stdlib.h”;

malloc分配動態內存後要手動初始化,而calloc分配內存過後初始化爲0;


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