指針:
1.指針的概念:
內存區的每一個字節有一個編號,這就是 ‘地址’,由于通過地址能找到所需的變量單元,而地址指向該變量單元,所以將地址形象化稱為 ‘指針’。C/C++中是可多繼承的指針,而Java中是單繼承指針。
2.為什么要用指針?
解決跨區域(不同作用域,不同代碼塊)之間的數據交互。
3.指針變量:
如果有一個變量專門用來存放另一變量的地址(即指針),則它稱為 ‘指針變量’。指針變量的值是地址(即指針)。指針變量本身在內存里面占據8個字節。
注意??:指針是一個地址,而指針變量是存放地址的變量。
4.怎樣定義和使用指針變量:
“&” :取地址運算符。&a 是變量a的地址。
“” :指針運算符(或稱‘間接訪問’ 運算符),p代表指針變量p指向的對象
(1)定義指針變量的一般形式為:
類型名 * 指針變量名;
eg: int *point_1, *point_2;
注意??:定義指針變量時必須指定基類型。可以在定義指針變量時同時對它初始化
(2)一個變量的指針的含義包括兩個方面:
一是以存儲單元編號表示的純地址(如編號為2000的字節);一是它指向的存儲單元的數據類型(如 int,char,float等)。
注意??:指針變量中只能存放地址(指針),不能將一個整數賦給一個指針變量。地址只能用地址符 “&” 得到并賦給一個指針變量。
eg:
float b =20;
int c = 10;
int *a=b;? 指針變量只能存地址,不能存具體值
int *a=&b;?整型指針只能存整形數據的地址
int *a = &c;??
float *d = NULL;NULL指向內存的起始地址 0x00
(3)數組和指針的關系:
數組名并不是一個變量 ,沒有分配內存空間。 而指針變量有內存空間。
(4)指針實際使用:
a. 定義一個數組,系統會為其分配內存空間,可以存值
int num[10]={0};
b. 定義一個指針變量,系統只為變量本身分配8個字節內存空間,但無法存值,因為系統沒有為其分配可賦值的內存空間
int *p;
c. 如果想給指針指向的區域賦值
//1.指針變量已經指向某塊區域
//2.指針指向一個數組
//3.動態分配內存
a. 用 malloc 函數開辟動態存儲區,其函數原型為:
void * malloc (unsigned int size);
其作用是在內存的動態儲存區中分配一個長度為 size 的連續空間。
b. 用 calloc 函數開辟動態存儲區,其函數原型為:
void * calloc (unsigned n, unsigned size);
其作用是在內存的動態存儲區分配 n 個長度為 size 的連續空間,這個空間一般比較大,足以保存一個數組。
c. 用 realloc 函數重新分配動態存儲區,其函數原型為:
void * realloc (void *p, unsigned int size);
如果已經通過 malloc 函數或 calloc 函數獲得了動態空間,想改變其大小,可以用 realloc 函數重新分配。
d. 用 free 函數釋放動態存儲區,其函數原型為:
void free (void *p);
其作用是釋放指針變量 p 所指向的動態空間,使這部分空間能重新被其他變量使用。p 應是最近一次調用 malloc 或 calloc 函數時得到的函數返回值。
1).分配一個屬于自己的內存空間 必須由自己釋放
2).普通變量的內存空間由系統分配和釋放
3).若之前分配的內存空間不夠或多余了 則必須重新分配 重新分配用(在malloc基礎上):realloc
5.通過指針引用數組:
(1)所謂數組元素的指針就是數組元素的地址。可以用一個指針變量指向一個數組元素:
eg:
int a[10]={1,3,4,6};
int *p;
p=&a[0];
(2)引用數組元素可以用下標法:a[i]形式,也可以用指針法:如 *(p+i) 或 *(a+i) 即通過指向數組元素的指針找到所需的元素。
(3)在指針指向一個數組元素時可以對指針進行以下運算:
加一個整數:(用+或+=),如p+1;
減一個整數:(用-或-=),如p-1;
自加運算:如p++,++p;
自減運算:如p--,--p;
兩個指針相減,如p1-p2,只有p1和p2都指向同一數組中的元素才有意義。
注意??:
a. 如果p的初值為&a[0],則p+i和a+i就是數組元素a[i]的地址,或者說它們指向a數組序號為i的元素。
b. *(p+i) 或 *(a+i) 是 p+i 或 a+i 所指向的數組元素,即 a[i]。例如 *(p+5) 或 *(a+5) 就是 a[5]。即 *(p+5), *(a+5) 和 a[5] 三者等價。
結構體:
建立結構體類型:
struct 結構體名
{成員表列};
成員都應進行類型聲明,即:類型名 成員名定義結構體類型變量:
(1)先聲明結構體類型,再定義該類型的變量
(2)在聲明類型的同時定義變量。其一般形式為:
struct 結構體名
{
成員表列
}變量名表列;
(3)不指定類型名而直接定義結構體類型變量。其一般形式為:
struct
{
成員表列
}變量名表列;結構體變量的初始化和引用:
(1)在定義結構體變量時可以對它的成員初始化。初始化列表是用花括號括起來的一些常量,這些常量依次賦給結構體變量中的個成員。
(2)可以引用結構體變量中成員的值,引用方式為:
結構體變量名,成員名
“ . ” 是成員運算符,在所有的運算符中優先級最高。
(3)如果成員本身又屬一個結構體類型,則要用若干個成員運算符,一級一級的找到最低的一級的成員,且只能對最低級的成員進行賦值或存取以及運算。
(4)對結構體變量的成員可以像普通變量一樣根據其類型進行各種運算。
(5)同類的結構體變量可以互相賦值。
(6)可以引用結構體變量成員的地址,也可以引用結構體變量的地址。結構體數組:
(1)定義結構體數組一般形式是:
a. struct 結構體名
{成員表列} 數組名[數組長度];
b. 先聲明一個結構體類型,然后再用此類型定義結構體數組:
結構體類型 數組名[數組長度];
(2)對結構體數組初始化的形式是在定義數組的后面加上:
= {初值表列};
- 結構體指針:
假設聲明一個 struct Student 結構體類型,struct Student p 定義為為指向 struct Student 類型數據的指針變量 p,‘num’ 為 struct Student 中的一成員變量。C 語言允許把 (p).num 用 p->num 代替, “-> ”代表一個箭頭, p->num 表示 p所指向的結構體變量中的 num 成員。
如果 p 指向一個結構體變量 stu ,以下3種用法等價:
a. stu. 成員名;
b. (*p).成員名;
c. p->成員名;
鏈表:
- 鏈表是動態的進行存儲分配的一種常見的數據結構。
2.鏈表有一個“頭指針”變量,它存放一個地址,該地址指向一個元素。
3.鏈表中每一個元素稱為“結點”,每個結點都包括兩部分:
(1)用戶需要用的實際數據
(2)下一個結點的地址
文件的輸入輸出:
1.一個文件要有一個唯一的文件標識,以便用戶識別和使用。文件標識包括3部分:
(1)文件路徑;
(2)文件名主干;
(3)文件后綴。
2.文件類型指針:
(1)緩沖文件系統中,每個被使用的文件都在內存中開辟一個相應的文件信息區用來存放文件的有關信息,這些信息都保存在一個結構體變量中,該結構體類型由系統聲明,取名為:FILE。
(2)要引用 FILE 類型變量,一般不通過給 FILE 類型的變量命名來引用這些變量,而是設定一個指向 FILE 類型變量的指針變量來引用這些 FILE 類型變量。比如,定義一個指向文件型數據的指針變量 fp:FILE * fp; 通過該文件指針變量能夠找到與它關聯的文件。
-
用函數打開與關閉文件
(1)用 fopen 函數打開數據文件
fopen 函數的調用方式為:fopen(文件名,使用文件方式);
eg:
Xnip2019-08-04_18-31-59.png
(2)用 fclose 函數關閉數據文件
fclose 函數的調用方式為:fclose(文件指針);
注意??:打開了一個文件一定要關閉
-
使用文件的方式:
r : 只讀 w : 只寫 a : 追加
rb : 只讀 wb : 只寫 ab: 追加
r+ : 讀寫 w+ : 讀寫 a+ : 讀寫
rb+ : 讀寫 wb+ : 讀寫 ab+ : 讀寫
常用下面的方法打開一個文件:
Xnip2019-08-04_17-56-23.png
5.向文件讀寫字符:
(1)向文本文件讀入字符:
函數名:fgetc
調用形式:fgetc(fp)
(2)向文本文件輸出字符:
函數名:fputc
調用形式:fputc(ch,fp)
6.向文件讀寫字符串:
(1)向文本文件讀入字符串:
函數名:fgets
函數原型:
char * fgets(char * str,int n,FILE * fp);
調用形式:fgets(str,n,fp)
功能:從 fp 指向的文件讀入一個長度為(n-1)的字符串,存放到字符數組 str 中。
eg:
(2)向文本文件輸出字符串:
函數名:fputs
函數原型:
int fputs(char * str,FILE * fp);
調用形式:fputs(str,fp)
功能:把 str 所指向的字符串寫到文件指針變量 fp 所指向的文件中。
今日總結感悟:A day of Tired, boring, unreadable .