#include<stdio.h>的意思就是講預處理器用名叫stdio.h的庫函數頭文件的內容替換#include指令語句
這個整條語句叫做預處理指令 stdio.h才叫頭文件
在C語言中數組參數是以引用(reference)形式進行傳遞的,也就是傳地址
1、puts()函數和printf()函數輸出字符串的區別:
puts()函數,輸出一串字符串,並且會在末尾進行換行操作
使用printf()輸出字符串就不會進行換行
2、特殊字符表示:
三字母詞:幾個字符的序列,表示另外一個字符
例如:??( 表示一個[字符 ??)表示 ]
??< 表示一個{ ??>表示}
有的編譯環境也許會不處理三字母詞,vs2017就不處理
轉義字符:
如果在某個地方想要使用某個特定字符,但是這個字符在這裏有其他的意義,導致不可以使用該字符,這是就應該使用轉義字符,將特定字符作爲單個字符來處理,
\” 表示”
\\ 表示\
\r 表示回車
\t 表示製表符,一個製表符代表8個空格
\’ 表示’
\b 表示退格鍵(backspace)
3、#if 0
.........
#endif 也可以進行註釋代碼,功能要比/**/強大的多
4、註釋/**/裏面不可以有單獨的 */必須是成對出現的
5、長整形和整形以及短整形:
長整形並不一定比整形大,短整形也不一定比整形小
規定:長整形至少應該和整形一樣長,短整形最大和整形一樣大
Char 0------127
Sign char -127----127
Unsigned char 0------255
Short int -32767------32767
int -32767-------32767
Unsigned short int 0-------65535
Long int
6、枚舉類型:
enum{ cup,yellow ,blue,black
}name;
大括號中的單詞分別代表的是0 1 2 3
聲明爲枚舉類型的變量實際上是數類型, enum name; 你實際上可以給name賦值爲數字都可以
另外枚舉類型的變量的大小都是4字節
7、浮點類型:
Double 類型至少和float類型一樣長
所有的浮點類型至少能夠容納從10^-37到10^37之間的任何值
8、指針:
int *a;
變量名是a 類型是int*
int* a;與int *a;
int* a,b,c; 寫成這樣很容易誤認爲b,c也是指針變量,實際上不是的
定義指針變量最好定義成 int *a;
Char *pArr=”張三”;將字符串常量賦值給char*類型的指針變量pArr
9、typedef:
Typedef char* ptr_to_char;
ptr_to_char a; a是一個指向char類型的指針變量
使用typedef 和 #define 的區別:
使用#define 重命名指針類型是無效的,typedef是可以的
例如:
#define d_ptr_to_char char*
Typedef char *ptr_to_char
聲明變量:
d_ptr_to_char a,b; 這樣執行之後a被成功聲明成了指針類型的變量,但是b仍然是字符變量
ptr_to_char a,b;這樣執行之後a,b兩個 變量全是指針變量
10、常量:
Const 聲明的常量樣子和變量一樣,只是他們的值是不允許修改的
常量的聲明:
int const a;
const int a; 兩種方式是一樣的
那麼既然常量的值是不可以修改的,那麼就需要在聲明是直接初始化
或者作爲函數中形參的值,由實參進行賦值
指針和const 混合使用:
只需要記住const修飾的是其後面的變量,就像下面的例子:
int const *a; 也可以寫成 const int *a; //因爲*a是被const修飾的,所以*a是一個常量,也就是說指針所指向的值是個常量
Int *const a; 不可以寫成const *int a; //因爲a是被const修飾的,所以a是個常量,又因爲a是一個指針,所以指針是個常量
Int const *const a; //這種情況,因爲後面的const修飾的a,但是因爲a是一個指針,所以指針是個常量,又因爲前面的const修飾的是*a,所以*a是個常量,也就是指針所指向的值十個常量,所以這種用法是:指針和指針所指向的值都是常量
11、作用域:
四種不同類型的作用域:
1文件作用域
2函數作用域
3代碼塊作用域
4原型作用域
12、c語言內存四區:
內存四區模型:
操作系統給C/C++編寫的程序分配內存,通常將分配的內存劃分爲以下四個區域:
1.棧區:存放局部變量,用完由操作系統自動釋放
2.堆區:動態分配給程序的內存區域,由程序員手動釋放
3.數據區:
分爲兩種:
(1)常量區:存放常量,一般是字符串常量
(2)全局區/靜態區:存放全局變量和靜態變量
4.代碼區:
存放可執行代碼的區域
13:、goto語句:
14、getchar()返回的是int類型的值
15、逗號操作符:
16、指針:
每個計算機的內存有數以億計的位組成,每個位可以容納0或1,但是由於每個位所能表示的值的範圍太有限,所以由幾個位組成一個單位,來進行容納範圍更大的值
間接訪問操作符*
具有從右往左結合的結合性
指針的指針:
int a = 12;
int *b = &a;
int **c = &b;
只要從右往左結合性一步步看就很好理解
A 相當於 12
b &a
*b a,12
C &b
*c *b, b,&a
**c *b , a,12
指針的類型:去掉變量名剩下的就是指針的類型 int*
指針指向的類型: 去掉變量名和*剩下的就是 int
*的運算級別高於+的運算級別,但是小於++的運算級別
char str[10] = "ABCDE";
char *p = str;
單獨執行下面的一個語句:
printf("*p=%c\n",*p); 結果是A
printf("*p++=%c\n",*p++); 結果也是A
printf("*++p=%c\n", *++p); B
printf("++*p=%c\n", ++*p); B
需要注意的是++p得到的是p後面的那一個數的地址,不是僅僅只用p的地址加1,而是p的地址加上 類型所佔的字節數*1
也就是說++p 《===》 p+(sizeof(int)*1)
如果p的地址是 10011
那麼++p的地址就是 10015
17、 如何在函數中使用可變參數?
頭文件stdarg.h va_list類型的變量 訪問可變參數
Va_startva_arg va_end
18、 數組
int b[10] ,b[0]是int類型的 b是什麼類型呢?因爲數組名錶示數組的地址,所以在這裏b就是指向int類型的指針常量,注意不是指針變量,所以你無法修改b的值,因爲數組的地址是一定的,因此數組名的值是一個指針常量
所以不可以使用a++。必須使用a+1
int a[10];
Int *b=a;和int *b=&a[0],有區別嗎?
回答:因爲數組名錶示的就是數組的首個元素的地址,所以上面的兩條賦值語句是完全一樣的
除了優先級之外,下標引用和間接訪問是完全一樣的
數組中看着很奇怪但是是正確的語句:
5[a] 是和 a[5] 完全一樣的
因爲a[5] 如果使用間接訪問訪問的寫法就是 *(a+5)那麼和 *(5+a)不是一樣的嘛
所以也是可以寫成 5[a] 是完全沒有問題的
指針與下標的運行效率比較:
多維數組數組名錶示含義:
Int a[5][10];
數組名a可以看做是一個一維數組,它包含五個元素,只是每個元素又包含十個整形元素
因爲a是指向數組的第一個元素,也就是數組首元素的地址,所以a是一個指向一個包含十個整形元素的數組的指針,簡單說a就是數組指針
例如int a[3][5]
數組名a指向第一行 是數組指針
a+1指向第二行
a+2 指向第三行
*a表示 a[0]這個指向5個元素的一維數組 是數組
*(a+1) 表示 a[1] 是個數組
*(a+2) 表示 a[2] 是個數組
使用間接訪問表示a[2][4]這個元素 *(*(a+2)+4)
其他語言允許寫成a[3,5]
但是在C語言中標a[3,5]僅僅是表示a[5] ,如果沒有越界的話還好
指向數組的指針:
例如
int a[5], *p=a;
int a[3][5], *p=a;
第一行語句是合法的,p是一個指向一維數組的指針
但是第二句就是非法的,因爲 a本身就是一個指向數組的指針,將一個數組指針賦給一個指針,是不可以的 除非p也是一個數組指針 可以這樣寫 int (*p)[5] =a; 下標的優先級高於間接訪問所以要加括號
作爲函數參數的多維數組;
Int a[5];
Fun(a);
這樣的一維數組 函數原型可以是一下這樣的
Void fun(int a[])
或者 void fun(int * a) 因爲一維數組名只是首元素的地址,所以形參使用一個指針變量即可
那麼對於這樣的二維數組呢?
Int a[3][5];
Fun(a);
函數原型可以是一下兩種:
Void fun(int a[][5])
或者 void fun(int (*p)[5])
這是因爲二維數組名,表示的是一個數組指針,所以形參必須也是數組指針
那麼爲什麼需要第二個數字5,而不是第一個數字3呢?因爲編譯器必須知道第二個及以後各維的長度,才能對各下標進行求值
對於多維數組如何初始化:
二維數組:
int b[3][5] =
{
{1,2,3,4,5},
{1,1,1,1,1},
{1,1,1,1,1},
};
三維數組:
int a[2][3][4] =
{
{
{1,1,1,1},
{1,1,1,1},
{1,1,1,1},
},
{
{2,2,2,2},
{3,3,3,3},
{4,4,4,4},
},
};
四維數組:
對於多維數組初始化時從前面的中括號往後面看的
數組指針:
表示是一個指針,指向的是一個數組的地址
int (*p)[5]
指針數組:
表示是一個數組,只是數組的元素存放的是地址
除了類型之外,指針變量和普通變量很相似,只是普通變量是存放的數字,指針變量是存放的變量的地址罷了,
那麼有數組,當然也可以有指針數組,數組元素中是存放的地址罷了
int * p[10]; p是一個int* 類型的指針數組,可以存放十個整形變量的地址
一維數組名取地址表示什麼?
int a[5];
&a和a 和&a[0] 的值都是一樣的,但是&a的類型是 int (*)[5] 是一個數組指針
a+1表示 數組的首地址加上 1*sizeof(int)
然而 &a+1表示 數組的首地址加上 1*sizeof(a) ,也就是加上的一個數組的佔的所有的字節長度
int a[4][5]; 假設數組的首地址爲1000的話
那麼 a=1000
A+1=1020
A[1]=1020
*(a+1) =1020
A[1]-1=1016
指針函數與函數指針:
返回值是某一種指針的函數叫做指針函數
指針指向函數的地址叫做函數指針、
函數指針除了將函數名用函數指針代替,其他和函數一樣
函數指針的定義和初始化:和函數原型一樣
Int min(int x,iny y); 函數原型
Int (*p) (int x,int y);
函數指針:
字符串:
要注意strlen()函數返回的是無符號整形類型的值
第十章:結構和聯合:
數組是相同元素的集合
結構也是一些值的集合,這些值稱爲他的成員
結構的聲明:
Struct tag
{
member-list
} variable-list;
下標引用和點操作符的優先級是一樣的,他們的結合性都是從左往右
->優先級高於*也高於 &
++高於* 但是+小於*
動態申請內存:
Malloc() 成功返回的是void*類型的指針,失敗返回NULL(相當於0)
申請的是一塊連續的內存
Int *p=malloc(25*sizeof(int)); //申請100字節的內存(假設int類型佔4個字節)
初始化:
for(int i=0;i<25;i++)
*p++=0;
或者
for(int i=0;i<25;i++)
P[i]=0;
Free() 釋放內存函數,必須是釋放一整塊,不能是一部分