《c語言中級》知識點總結:
1. sizeof關鍵字:
編譯時確定,sizeof(對象),sizeof(類型),sizeof 對象,sizeof(指針)=4.
int a[5]; sizeof(a) = 20; sizeof(&a) = 20;
2. c語言不允許定義空結構體; c++允許, sizeof() = 1
3. char *a = “hello” “world”; //a為”helloworld”
pintf(“\32” “3\n”) = printf(“\323”);
printf(“\172\n”);//八進制172 ascii對應值
printf(“\0x60”);//十六進制60h ascii對應值
printf(“\60” “3\n”);// 03
4. a[0] = *(a+0), 是一個表達式,0[a]也行,a代表數組第一個元素的首地址。
int a[10]; &a+1指向了a[9]後面,整行加一
對數組名求址&a會導致數組維數上升,變成了數組指針int (*)[10]
5. 有符號數和無符號數運算,結果轉化為無符號數。
static int i = 10; 指定i本文件使用
extern int a;/ extern a; 聲明a來自其他文件
6. const的作用
const int x = 2; 或者 int const x = 2;
const int *a 或者 int const *a; //a可變,a指向的對象不可變;
int * const a; //const修飾指針a,指針a不可變。
const可以修飾輸入參數、返回值、成員函數
7. const指針
一個指向const對象的指針不能賦值給指向非const對象的指針,但反過來可以
(非const可以賦給const)
(1).const int i = 10;
const int *p = &i; //p指向const int
int *q = p; //非法
(2).const int i = 10;
const int **p1;
int *p2;
p1 = &p2;
*p1 = &i; //相當於p2 = &i,但直接p2 = &i非法
*p2 = 20;//修改了常量const int,具體結果在環境上測試
8. typedef int array[10]; //typedef int[10] array;
array a;
array b[5]; //b[5][10]
array *c; //(*c)[10] , (*c)[10]要用二維數組賦值,++往下移動一行
array *c[4];// int (*c[4])[10],指向二維數組的指針數組
一維數組int a[10]中的a等價於定義了一個指向元素的指針---> int * const a;
二維數組int b[3][4]的b等價於定義了一個指向一維數組為元素的指針--->int (*const b)[4]
int b[3][5];
*(*(b+2)+0) b中第二行第0列的值;
*(b+2) b中第二行首地址,*()有降維的作用
b+2 為b[2][0]的地址,類型為int[][5],沒降維
9. 結構體對齊規則
(1).結構體中變量的首地址能被該成員大小與對齊基數中的較小者所整除;
(2).結構體總大小為結構體最寬基本類型成員大小與對齊基數中的較小者的整數倍,不足時填充。
(3).確定偏移位置及大小時,將復合類型(如結構體)當做一個整體看待。
struct a struct b
{ int ii; { int i;
double dd; struct a a;
}aa; double d;
sizeof(aa) = 16; }b;
sizeof(bb) = 32;
10. scanf
scanf用%c格式輸入時,空格和轉義字符都為有效輸入;
輸出% 需要printf(“%%”); \a鳴響 %[字符集] %[^\n] %i
11. 常量
#define const 字面常量 枚舉
12. 頭文件 < > 與 “”
< > 直接在系統默認路徑下找,找不到就報鏈接錯誤;
“ “ 先在當前路徑下找,找不到再在系統路徑下找,再找不到就返回鏈接錯誤
13. 數據類型決定:(1). 數據占用內存空間大小;(2).存儲格式; (3).運算規則---行為
存儲類型決定: 存儲區域,區域決定了作用范圍和生命周期。
14. 內存分區
c++內存分為五個區: 堆(new)、棧(局部變量、函數參數)、全局/靜態存儲區、自由存儲區(malloc)、常量區。
c語言分為四個區: 堆(malloc)、棧(局部變量、函數參數)、全局/靜態存儲區、常量區。
15. 堆區內存使用四要素:
int *p = (int*)malloc(10*sizeof(int));
if (null == p) return;
free(p);
p = null;
16.
17. 千萬不要返回指向棧內存的指針和引用,可以返回靜態局部變量,靜態局部變量在函數外存在但不可見。
18. typedef陷阱
typedef char* pstr;
定義const pstr,我們希望是const char *,但實際是char * const
19. 指針
(1).無類型指針void*p,不能加減一個整數,只能進行賦值、比較、sizeof操作。
(2).static 局部變量指針必須用全局變量初始化;
(3).不同類型的指針不能求差,指針差為(字節數/類型) sizeof(&a[5]-&a[0]) = 4;
(4).int a[10]; a是個常量,一個地址; vc sizeof(&a)=40; gun sizeof(&a) = 4;
(5). int a [8][9]; int(*p)[9] = a;
(6). char *p = “abcd”; p[0]=’m’; //非法,p指向常量區,不能修改;
(7).char *p = “hello”; //錯誤的寫法,因為p指向了常量區,而p是指向變量的指針,意味著可修改所指數據,應該改為const char *p = “hello”.
(8). 任何類型的指針大小都為4個字節。
22. 指針與const
(1) int (2) * (3) p; (1)和(2)位置:p指向的不能修改 (3)位置:p不能修改
char **p; p----> char * ----> char;
const char**p p----> const char * ---->const ch
char * const *p p---->char * const ----->char
20. 函數與指針
函數的返回值和形參列表共同構成函數類型;
typedef float (*pf) (int,double) //函數指針
int (*p)[3]; //二維數組指針,大元素,每行有三列
int *ptr[3][4];//二維指針數組
int *(*ptr)[4];//指向二維指針數組的指針
int (*myfun())(int *, int *)//定義一個函數,返回類型為函數指針
int (*s[10])(int) //含有10個函數指針的數組
char(*(*fun())[4])(int *p)
----> char(*)(int *p) (*)[4] fun()//定義了一個函數,返回類型為指向二維數組的指針,數組的元素也為函數指針
char (*(*(*q)())[5])()
---->char (*)() (*)[5] (*q)() //定義了一個函數指針,指向的函數返回類型為指向二維數組的指針,數組中的元素也是一個函數指針
21. 指針與函數參數
指向指針的指針作為形參,如void f(int **pp),作用是對作為指針的實參傳址,如f(&p);
函數名是地址常量,可賦值給對應的指針變量----函數指針
函數指針賦值: pfun = 函數名: 把函數名看做函數的入口地址
pfun = &函數名: 把函數看做名字,取其地址
調用: (*pfun)(實參列表)
pfun(實參列表)
void myfun(int x) {printf(“%d”,x);}
void main {
void (*pfun)();
pfun = myfun;
myfun(10); //四種調用方式都是ok的
(*myfun)(10);
pfun(10);
(*pfun)(10);
}
22. (1).不要在函數調用處(參數列表中)寫表達式;
(2).後++,求值時間要後到整個表達式求完值後,參數中的後++到形實結合後++;
(3).函數調用結果只能用於初始化非靜態變量,static char *p = (char *)malloc(20)---->錯誤;
(4).static不作用與形參,會失去靜態性;
(5).避免函數有記憶功能(不要使用static局部變量);函數中少修改static全局變量,避免影響其他函數;
(6).函數默認有extern修飾,函數和全局變量可以用static修飾限定為本文件使用;
(7).兩層循環,多的應該放裡面,減少循環次數。
23. 預處理
(1).預處理語句以#開頭,不加”;”,獨占一行,可放於任意位置;
(2).預處理在編譯之前,條件編譯、宏、條件包含;
(3).預處理之前還有預處理:消除續行,檢查函數名,去掉注釋;
(4).宏定義不是C語句,不是函數,不是類型定義,宏值多於一項一定要加(),防止優先級錯誤;
(5).宏中的’#’使變量字符串化;
(6).宏中的’##’使變量連接起來,#define TEST(a,b) a##b TEST(2,3); --->23;
(7).宏的參數不能用表達式;
(8).用const取代無參宏,用inline取代有參宏;
(9). (void)printf(“Beijing.\n”); void顯式拋棄返回值.
24. 頭文件
(1).頭文件包含會引發重復定義變量,可以用條件編譯解決:
#ifndef _FILENAME_H_
#define _FILENAME_H_
#endif
(2).頭文件中不要定義較大的static全局變量,如結構數組等;