總結
基礎
- 程序結構是三種: 順序結構、選擇結構(分支結構)、循環結構。
- 讀程序都要從main()入口, 然后從最上面順序往下讀(碰到循環做循環,碰到選擇做選擇),有且只有一個main函數。
- 計算機的數據在電腦中保存是以二進制的形式,數據存放的位置就是他的地址。
- bit是位,指為0或1。byte是指字節,一個字節=八個位。
- 每個C語言程序寫完后,都是先編譯,后鏈接,最后運行。(.c→.obj→.exe)這個過程中注意.c 和.obj 文件是無法運行的,只有.exe文件才可以運行。
常考
- 編譯預處理不是C語言的一部分,不占運行時間,不要加分號。
C語言編譯的程序稱為源程序,它以ASCII數值存放在文本文件中。 #define PI 3.1415926;
這個寫法是錯誤的,一定不能出現分號。- 每個C語言程序中main函數是有且只有一個。
- 在函數中不可以再定義函數。
- 算法:可以沒有輸入,但是一定要有輸出。
- break可用於循環結構和switch語句。
- 逗號運算符的級別最低,賦值的級別倒數第二。
- int *p 中 *p 和 p 的差別:簡單說*p 是數值,p 是地址!
- *p:可以當做變量來用;*的作用是取后面地址 p 里面的數值。
- p:是當作地址來用。可以用在 scanf 函數中:scanf("%d",p);
- *p++ 和 (*p)++的之間的差別:(筆試重點)
- *p++:是地址會變化。
口訣:取當前值,然后再移動地址! (*p)++:是數值會要變化。
口訣:取當前值,然后再使數值增加 1。例題:int *p,a[]={1,3,5,7,9};
p=a;
請問*p++和(*p)++的數值分別為多少?
*p++:這個本身的數值為1。由於是地址會增加一,所以指針指向數值3了。
(*p)++:這個本身的數值為1。由於++表示數值會增加,指針不移動,但數值1由於自加了一次變成了2。
- *p++:是地址會變化。
- 二級指針:
- *p:一級指針:存放變量的地址。
**q:二級指針:存放一級指針的地址。
常考題目:
int x=7; int *p=&x, **q=p;
問你:*p 為多少?*q為多少?**q為多少?
*p=7,*q=p,**q=7
再問:**q=&x 的寫法可以嗎?不可以,二級指針只能存放一級指針的地址。
- 程序進行編譯時,並不為形式參數分配存儲空間。只有在被調用時,形式參數才臨時地占有存儲空間。
形式參數(形參)存儲類別默認“auto”
形參用關鍵字auto作存儲類別的聲明時,關鍵字“auto”可以省略,auto 不寫則隱含確定為“自動存儲類別”,它屬於動態存儲方式。 - 函數的存儲類型是函數定義時函數名前面的數據類型前面的存儲類型。
函數的存儲類型默認“extern”,表示該函數屬外部函數(即 可以被本 C 文件外的其他 C 源程序文件中的函數調用)- extern:(External)
對整個工程可見,其他文件可以使用extern外部聲明后直接使用。也就是說其他文件不能再定義一個與其相同名字的變量了(否則編譯器會認為它們是同一個變量) - static:代表靜態全局
僅對當前文件可見,其他文件不可訪問,其他文件可以定義與其同名的變量,兩者互不影響。
- extern:(External)
重點
- strlen 和 sizeof 的區別(重點):
sizeof:(求實際存儲空間)
相當於是個宏一樣的東西,因為它只是一個運算符,而不是函數,編譯時展開為常數,編譯的時候有每個變量的定義表,sizeof通過查表確定變量占用的空間,這是分配內存給process 之前要確定的。
其實可以簡單的理解sizeof是針對"類型"的,而非"變量",但此時不能這樣看,如:
sizeof("HELLO");
括號中不是字符數組const char *,而是一個"字符串",所以結果大小為 5。
但字符數組:char *ps = "HELLO"; //字符數組 sizeof(ps) = 4 //只是指針的大小,即 地址(整數類型占4個字節) sizeof(*ps) = 1 //*ps+0代表數組第一個元素的大小,即ps[0] char as[8]; sizeof(as) = 8 //因為as的類型為 char [8],這個大小的確是8 sizeof(*as) = 1 //*as+0代表數組第一個元素的大小,即as[0] char aa[8][9]; sizeof((char *)aa) = 4 //還是 char * char arr[100] = "HELLO"; sizeof(arr) = 100 //和賦什么值沒什么關系,關鍵是"類型"是什么 int func(char p[100]) { sizeof(p) = 4; //C/C++中不能傳數組,只能傳指針,所以任何數組都會隱式轉成指針形式進行操作。 }
strlen:(求字符串長度,即 字符個數,不包括結束符)
它是一個函數,參數是 const char*,搞清楚它的實現,就是碰到'\0'(字符串結尾,就停止計數,但不包括'\0')。所以它不是看類型而是看變量,取決於變量賦的什么值。
- 函數的遞歸一定會考。
兩種重要的數組長度:
char a[]={'a','b','c'};
數組長度為3,字符串長度不定(因為沒有'\0'結束符)。sizeof(a)為3。
char a[5]={'a','b','c'};
數組長度為5,字符串長度3。sizeof(a)為5。
char a[]={'a','b','c'};
這是一個字符數組,占3個字節。
char a[]="abc";
則不同,它是一個字符串,最后還有一個'\0'結束符,占4個字節。- scanf 和 gets 的區別:
如果輸入的是 good good study!scanf("%s",a);
只會接收 good。考點:不可以接收空格。(遇到空格或回車就終止)
gets(a);
會接收 good good study!考點:可以接收空格。(遇到回車終止)
指針考點:
char ch[]="iamhandsome";
char *p=ch;
問你:*(p+2) 和 *p+2 的結果是多少?
*(p+2) = 'm', *p+2 = 'k'解析:
第一個是地址+2,所以取m;
第二個則是數值+2,即 ASCII碼值+2,ijk,所以取k。- 字符串的賦值:
C語言中沒有字符串變量,所以用數組和指針存放字符串:char ch[10]={"abcdefgh"};
對char ch[10]="abcdefgh";
對char ch[10]={'a','b','c','d','e','f','g','h'};
對char *p="abcdefgh";
對char *p;
對ch="abcdefgh";
錯!數組名不可以賦值!(只能一個一個循環賦值)char *p={"abcdefgh"};
錯!大括號是數組用的,相當於集合,而指針類型不能用大括號
逗號表達式:
將兩個及其以上的式子聯接起來,從左往右逐個計算表達式,整個表達式的值為最后一個表達式的值。
(2,3,4)的表達式的數值就是4。
z = (2,3,4);
(整個是賦值表達式),這個時候z的值為4。
z = 2,3,4;
(整個是逗號表達式,即(z = 2),(3),(4);
),這個時候z的值為2,這個(z = 2,3,4)式子的值為4。用途:
for(i=0,j=0; i<10; i++)
,像這樣聯接式子,因為for中的每個區域只能放一個式子,所以需要逗號表達式聯接多個式子。
宏定義defind
問題:
#define f(x) (x\*x)
和#define f(x) x\*x
之間的差別。
define是C語言中的宏定義關鍵字,其定義格式如下:
#define [MacroName] [MacroValue]
宏定義分為普通宏定義和帶參數的宏定義
普通宏定義:
#define PI (3.1415926)
帶參數的宏定義 (宏函數):
#define max(a,b) ((a)>(b)? (a),(b))
注意:變量在宏中要用括號括起來。
因為,在C語言中define宏定義在編譯時,會被展開,進行“傻瓜式”替換,也稱為“字面”替換,如果沒有括號有可能會產生歧義。如:
int a,b,c,d,e; a=1; b=2; c=6; d=4; e = f(a+b)*f(c+d) ; //理論值e=9*100=900 #define f(x) (x*x) 替換結果為:e =(a+b*a+b)*(c+d*c+d) = 5*34=170 #define f(x) x*x 替換結果為:e = a+b*a+b*c+d*c+d=1+2+12+24+4=43 #define f(x) ((x)*(x)) 替換結果為:e = ( (a+b)*(a+b)*(c+d)*(c+d) )=3*3*10*10=900
這個才是我們想要的結果!
字符
字符數據的合法形式:
'1' 是字符占一個字節,"1"是字符串占兩個字節(含有一個結束符號)。
'0' 的 ASCII 數值表示為 48,'A'的 ASCII 數值是 65,'a' 的 ASCII 數值是 97,
一般表示單個字符錯誤的形式:'65' "1"
字符是可以進行算術運算的,記住:'0'-0=48注意:這個48不用記,用的時候直接'0'-0,就可以轉換字符和數字了。
記憶:0Aa:486597,486 看 re0 的應該知道,597 就是486+111。大寫字母和小寫字母轉換的方法:
'A'+32='a'
相互之間一般是相差32。注意:這個32不用記,要用的時候直接'a'-'A',就可以得出轉換大小寫的數值了。
在ASCII碼表中,A比a先,所以ASCII碼小
類比:A比a先,所以生日年份比a小。字符型和整數是近親:兩個具有很大的相似之處
char a = 65;
printf("%c", a);
得到的輸出結果:a
printf("%d", a);
得到的輸出結果:65
轉義字符
轉義字符分為一般轉義字符、八進制轉義字符、十六進制轉義字符。
- 一般轉義字符:\0、 \n、 \'、 \"、 \\。
- 八進制轉義字符'\ddd':(其中d為常數,ddd表示三位8進制數)(以0開頭的表示八進制)
'\141'=97
是合法的, 前導的0是不能寫的。 - 十六進制轉義字符'\xhh':(其中h為常數,hh表示兩位16進制數)(以0x開頭的表示十六進制)
'\x6d'=109
才是合法的,前導的0不能寫,並且x是小寫。
進制名稱 | 英文 | 縮寫 |
---|---|---|
二進制 | Binary | B |
八進制 | Octal | O |
十進制 | Decimal | D |
十六進制 | Hexadecimal | H |
輸入輸出
格式符
格式說明 | 表示內容 | 注釋 |
---|---|---|
%d | 整型十進制 int | Decimal |
%ld | 長整型 long int | Long Decimal |
%f | 浮點型 float | Float |
%lf | 雙精度浮點型 double | Long Float |
%% | 輸出一個百分號 | % |
%c | 字符 char | Char |
%s | 字符串 | String |
%o | 八進制 | Octal |
%#o | 帶前導(0)的八進制 | |
%x | 十六進制 | Hexadecimal |
%#x | 帶前導(0x)的十六進制 | |
%p | 指針的值,輸出地址符 即 地址 |
Pointer |
%md | 整型,m為總長度(常數)(默認為正數+) | 右對齊(數軸左-右+) 即 不足的話,左邊補上空格 |
%-md | 整型,m為總長度(常數)(負數-) | 左對齊 即 不足的話,右邊補上空格 |
%m.nf | 浮點型 m為總字符長度(包含小數點) n為小數長度 |
要進行四舍五入 當實際的顯示大於m,那就按實際輸出,也就是m無意義了 %3d 對應 1234 的話,就是1234 沒有空格 |
舉例說明:
printf("%2d",123);
第二部分有三位,大於指定的兩位,原樣輸出 123
printf("%5d",123);
第二部分有三位,小於指定的五位,左邊補兩個空格 123
printf("%10f",1.25);
小數要求補足 6 位的,沒有六位的補 0,。結果為 1.250000
printf("%5.3f",125);
小數三位,整個五位,結果為 1.250(小數點算一位)
printf("%3.1f",1.25);
小數一位,整個三位,結果為 1.3(要進行四舍五入)
輸入
要特別注意的是:
scanf("%d,%d", &x, &y);
scanf 的第二個部分一定要是地址!
指定輸入的長度:(一般用空格或回車進行間斷)
終端輸入:1234567
scanf("%2d%4d%d",&x,&y,&z);
x 為 12,y 為 3456,z 為 7
終端輸入:1 234567 由於 1 和 2 中間有空格,所以只有 1 位給 x
scanf("%2d%4d%d",&x,&y,&z);
x 為 1,y 為 2345,z 為 67字符和整型是近親:
int x=97;
printf("%d",x);
結果為 97
printf("%c",x);
結果為 a輸入時候字符和整數的區別:
scanf("%d",&x);
這個時候輸入 1,特別注意表示的是整數 1
scanf("%c",&x);
這個時候輸入 1,特別注意表示的是字符'1',ASCII 為整數 49。%*d
:scanf("%d%d%*d%d",&a,&b,&c);
跳過輸入的第三個數據。
輸入:1 2 3 4
即 a=1,b=2,c=4printf("%*d",len,a);
將整數a按len個字符的寬度顯示。
*號告訴printf待打印字符的顯示寬度從后面的參數列表中提取,指定是多少就按多少個字符寬度顯示。
如printf("%5d",a);
將整數a按5個字符的寬度顯示。
x保留n位小數,第n+1位四舍五入:((int)\((x*10^n+0.5)/10.0^n\))
y=(int)(x*100+0.5)/100.0
這個保留兩位小數,對第三位小數四舍五入
y=(int)(x*1000+0.5)/1000.0
這個保留三位小數,對第四位小數四舍五入
y=(int)(x*10000+0.5)/10000.0
這個保留四位小數,對第五位小數四舍五入這個有推廣的意義,注意 x = (int)x 這樣是把多余的小數部分去掉。
注意:這個只去掉了分子的小數部分,把分子化為了整型,當除以分母時,又恢復了浮點型。
基本表達式
注意:C 語言中是用非 0 表示邏輯真,用 0 表示邏輯假。
逗號表達式:
將兩個及其以上的式子聯接起來,從左往右逐個計算表達式,整個表達式的值為最后一個表達式的值。
(2,3,4)的表達式的數值就是4。
z = (2,3,4);
(整個是賦值表達式),這個時候z的值為4。
z = 2,3,4;
(整個是逗號表達式,即(z = 2),(3),(4);
),這個時候z的值為2,這個(z = 2,3,4)式子的值為4。用途:
for(i=0,j=0; i<10; i++)
,像這樣聯接式子,因為for中的每個區域只能放一個式子,所以需要逗號表達式聯接多個式子。- 賦值表達式:(可以連續賦值)
- 計算賦值運算符右側表達式的值。(“=”為賦值運算符)
- 將賦值運算符右側表達式的值賦給左側的變量。
將賦值運算符左側的變量的值作為表達式的值。(注意與逗號表達式的右側區分)
這就是連續賦值可以的原因。而連續比較大小關系不行,因為它表達式的值是bool類型(即 真假),當連續比較時數值會發生改變(變成0或者1)。
例如:x=y=3
就相當於x=(y=3)
結果都為3,這種連續賦值是可以的。
特別注意:而與之相對的連續關系表達式1<0<2
是不行的,這個從數學的角度出發肯定是錯的,但是如果是 C 語言那么就是正確的!因為 1<0 為假得到 0,表達式就變成了 0<2 那么運算結果就是 1,為真!
- 關系表達式:(不能連續比較)
- 表達式的數值只能為 1(表示真),或 0(表示假)。
如 9>8 這個關系表達式是真的,所以 9>8 這個表達式的數值就是 1。 如 7<6 這個關系表達式是假的,所以 7<6 這個表達式的數值就是 0 - 易錯:int x=1,y=0,z=2; x<y<z 是真還是假?
帶入為 1<0<2,從數學的角度出發肯定是錯的,但是如果是 C 語言那么就是正確的!因為 1<0 為假得到 0,表達式就變成了 0<2 那么運算結果就是 1,為真! - 等號和賦值的區別!一定記住"="就是賦值,"=="才是等號。
- 表達式的數值只能為 1(表示真),或 0(表示假)。
- 邏輯表達式:(表達式的數值只能為 1(表示為真),或 0(表示假))
- 共有 &&、||、! 三種邏輯運算符號。
- ! > && > || 優先的級別。
- 表示 x 小於 0 大於 10 的方法:0<x<10 是不行的。
先計算 0<x 得到的結果為 1 或則 0;再用 0,或 1 與 10 比較得到的總是真(為 1)。所以一定要用 (0<x)&&(x<10)表示比 0 大比 10 小。 注意短路現象。考試比較喜歡考到。
短路現象:為了要提高效率。在邏輯運算時候,如果值已經能決定整個表達式的值,就不會再往右繼續運算了。
例如:在if里有個&&,如果左邊的值為假,就不會再算右邊的真假。
----------------------------------------------------------------------------------------
短路現象常見的有,短路與(&&)和短路或(||)(當執行結果已經可以確定,則后面的將不再執行了)
若a && b ,如果a 的值為假,則整個表達式的值就為假,它是從左向右計算的。所以執行該表達式后,b 的值還是它的初始值,即不進行運算。
若a || b ,如果a 的值為真,整個表達式的值就為真,執行順序同上。b 的真假由最初的真假來判斷,也就是說,當a 為真時,b 則不進行運算了。例如:(m=a>b)&&(n=c>d),當a b c d 分別為1,2,3,4,m=n=1時,由於 a>b 為0,則m =0。而后面的不再執行,所以n=1而不是0。
- switch 語句:
- 執行的流程一定要弄懂!
- 注意有 break 和沒有 break 的差別,
- 沒有 break 時候,只要有一個 case 匹配了,剩下的都要執行
- 有 break 則是直接跳出了 swiche 語句。
- switch 只可以和 break 一起用,不可以和 continue 用。
switch(x) { //(x:是整型常量,字符型常量,枚舉型數據) case 1: … //Case 中不可以是變量。 case 2: … }
循環結構:(先執行while中的表達式(這樣才能判斷是否循環))
注意:不管循環不循環,都要執行while中的表達式才能判斷是否循環,不能說一眼看出0--不循環了,就不--了,計算機還是要--的。
1
int k=1 ; while(--k); printf("%d",k);
結果為0
解析:先執行while中的表達式,減1,然后為0(不能循環),終止循環(循環執行次數0),輸出0。
2
int k=1 ; while(k--); printf("%d",k);
結果為-1
解析:先執行while中的表達式,取1(可以循環),減1,循環,第二次執行while中的表達式,取0(不能循環),減1,終止循環(循環執行次數1),但是仍然-1了。
函數
函數:是具有一定功能的一個程序塊,是 C 語言的基本組成單位。
- 函數不可以嵌套定義。但是可以嵌套調用。
- 函數名缺省返回值類型,默認為int。
- C 語言由函數組成,但有且僅有一個 main 函數!是程序運行的開始!
函數的參數可以是常量,變量,表達式,甚至是函數調用。
請問 sum 的結果是多少?add(int x,int y){return x+y;} main() { int sum; sum=add(add(7,8),9); }
結果為 24- 一定要注意參數之間的傳遞
實參和形參之間傳數值和傳地址的差別。
傳數值,形參的變化不會改變實參的變化。
傳地址,形參的變化會有可能改變實參的變化。 - 函數聲明的考查:
- 函數一定要有:函數名,函數的返回類型,函數的參數類型。
- 不一定要有:形參的名稱。
int *fun(int a[] , int b[]) { ………… }
已經知道函數是這樣。這個函數的正確的函數聲明怎么寫?
int *fun(int *a , int *b);
這里是函數聲明的寫法,注意數組就是指針
int *fun(int a[] , int b[]);
這種寫法也是正確的
int *fun(int b[] , int c[]);
這種寫法也是正確的,參數的名稱可以隨便寫
int *fun(int * , int *);
這種寫法也是正確的,參數的名稱可以不寫
指針
定義 | 含義 |
---|---|
int i; | 定義整型變量 i |
int *p; | p 為指向整型變量的指針變量 |
int a[n]; | 定義整型數組 a,它有 n 個元素 |
int *p[n]; | 定義指針數組 p,它由 n 個指向整型數據的指針元素組成 |
int (*p)[n]; | p 為指向含有 n 個元素的一元數組的指針變量 |
int f(); | f 為返回整型數值的函數 |
int *p(); | p 為返回一個指針的函數,該指針指向整型數據 |
int (*p)(); | p 為指向函數的指針,該函數返回一個整型值 |
int **p; | p 是一個指針變量,它指向一個指向整型數據的指針變量 |
- int *p 中 *p 和 p 的差別:簡單說*p 是數值,p 是地址!
- *p:可以當做變量來用;*的作用是取后面地址 p 里面的數值。
- p:是當作地址來用。可以用在 scanf 函數中:scanf("%d",p);
- *p++ 和 (*p)++的之間的差別:(筆試重點)
- *p++:是地址會變化。
口訣:取當前值,然后再移動地址! (*p)++:是數值會要變化。
口訣:取當前值,然后再使數值增加 1。例題:int *p,a[]={1,3,5,7,9};
p=a;
請問*p++和(*p)++的數值分別為多少?
*p++:這個本身的數值為1。由於是地址會增加一,所以指針指向數值3了。
(*p)++:這個本身的數值為1。由於++表示數值會增加,指針不移動,但數值1由於自加了一次變成了2。
- *p++:是地址會變化。
- 二級指針:
- *p:一級指針:存放變量的地址。
**q:二級指針:存放一級指針的地址。
常考題目:int x=7;int*p=&x,**q=p;
問你:*p 為多少?*q為多少?**q為多少?
*p=7,*q=p,**q=7
再問:**q=&x 的寫法可以嗎?不可以,二級指針只能存放一級指針的地址。
- 三名主義:
- 數組名:表示第一個元素的地址。數組名不可以自加,他是地址常量名。
- 函數名:表示該函數的入口地址。
- 字符串常量名:表示第一個字符的地址。
傳數值和傳地址:
void fun(int a,int b) { int t; t=a;a=b;b=t; } main() { int x=1,y=3; fun(x,y); printf("%d,%d",x,y); }
這個題目答案是 1 和 3。
傳數值,fun 是用變量接受,所以 fun 中 的交換不會影響到 main 中的 x 和 y 。
傳數值,形參的變化不會影響實參。void fun(int *a,int *b) { int t; t=*a;*a=*b;*b=t; } main() { int x=1,y=3; fun(&x,&y); printf("%d,%d",x,y); }
這個題目的答案就是 3 和 1。
傳地址,fun 用指針接受!這個時候 fun中的交換,就會影響到 main 中的 x 和 y。
傳地址形參的變化絕大多數會影響到實參!函數返回值是地址,一定注意*號。
int *fun(int *a,int *b) { //可以發現函數前面有個*,這個就說明函數運算結果是地址 if(*a>*b) return a; //return a 可以知道返回的是 a 地址。 else return b; } main() { int x=7,y=8,*max; max = fun(&x,&y); //由於 fun(&x,&y)的運算結果是地址,所以用 max 來接收。 printf("%d",*max) }
數組
數組:存放的類型是一致的。多個數組元素的地址是連續的。
- 數組的初始化,一維和二維的,一維可以不寫,二維第二個[]一定要寫
int a[]={1,2} 合法。 int a[][4]={2,3,4}合法。 但 int a[4][]={2,3,4}非法。
科普:
- '0':代表 字符'0',對應ASCII碼值為 0x30(也就是十進制的48);
- '\0':代表 空字符\0(轉義字符)(輸出為空),對應ASCII碼值為 0x00(也就是十進制的0),用作字符串結束符;
- 0:代表 數字0,若把 數字0 賦值給 某個字符,對應ASCII碼值為 0x00(也就是十進制0);
- "0":代表 一個字符串,字符串中含有 2個字符,分別是 '0' 和 '\0'。
一維數組
當所賦初值少於所定義數組的元素個數時,將自動給后面的元素補以初值0。
例:給a數組中所有元素賦初值0
int a[10]={0};對於字符型數組也同樣補以初值 0,即 '\0'。(而不是'0','0'對應的ASCII碼為48)
(C語言中,'\0'表示的空字符,則其對應的ASCII碼值為0。)
(而NULL為空指針,ASCII碼也是0)例如:
char c[5]={'@'};
相當於:
char c[5]={'@','\0','\0','\0','\0'};
- 一維數組的初始化:(當所賦初值少於所定義數組的元素個數時,將自動給后面的元素補以初值0。)
int a[5]={1,2,3,4,5};
合法
int a[5]={1,2,3, };
合法(未設置的部分為0)
int a[5]={1,2,3};
合法
int a[]={1,2,3,4,5};
合法,后面決定前面數組的大小!
int a[5]={1,2,3,4,5,6};
不合法,賦值的個數多余數組的個數了 一維數組的定義;
int a[5];
定義時數組的個數不是變量一定是常量。
int a[1+1];
合法,個數是常量 2,是個算術表達式
int a[1/2+4];
合法,同樣是算術表達式
int x=5,int a[x];
不合法,因為個數是 x,是個變量
#define P 5 int a[P];
合法,define 后的的 P 是符號常量,只是長得像變量
一維數組的重要概念:
- 對 a[10]這個數組的討論。
- a 表示數組名,是第一個元素的地址,也就是元素 a[0]的地址。(等價於&a)
- a 是地址常量,所以只要出現 a++,或者是 a=a+2 賦值的都是錯誤的。
- a 是一維數組名,所以它是列指針,也就是說 a+1 是跳一列。
- 對 a[3][3]的討論。
- a 表示數組名,是第一個元素的地址,也就是元素 a[0][0]的地址。
- a 是地址常量,所以只要出現 a++,或者是 a=a+2 賦值的都是錯誤的。
- a 是二維數組名,所以它是行指針,也就是說 a+1 是跳一行。
- a[0]、a[1]、a[2]也都是地址常量,不可以對它進行賦值操作,同時它們都是列指針,a[0]+1,a[1]+1,a[2]+1 都是跳一列。
- 注意 a 和 a[0] 、a[1]、a[2]是不同的,它們的基類型是不同的。前者是一行元素,后三者是一列元素。
二維數組
- 二維數組的初始化
int a[2][3]={1,2,3,4,5,6};
合法,很標准的二維的賦值。
int a[2][3]={1,2,3,4,5, };
合法,后面一個默認為 0。
int a[2][3]={{1,2,3,} {4,5,6}};
合法,每行三個。
int a[2][3]={{1,2,}{3,4,5}};
合法,第一行最后一個默認為 0。
int a[2][3]={1,2,3,4,5,6,7};
不合法,賦值的個數多於數組的個數。