翁愷老師C語言學習筆記(十)指針_指針變量就是記錄地址的變量

指針變量就是記錄地址的變量

scanf函數
· 如果能夠將取得的變量的地址傳遞給一個函數,能否通過這個地址在那個函數內訪問這個變量
· scanf("%d", &i)
· scanf()的原型應該是怎樣的?我們需要一個參數能保存別的變量的地址,如何表達能夠保存地址的變量?

scanf()是C語言中的一個輸入函數。與printf函數一樣,都被聲明在頭文件stdio.h裏,因此在使用scanf函數時要加上#include <stdio.h>。(在有一些實現中,printf函數與scanf函數在使用時可以不使用預編譯命令#include <stdio.h>。)它是格式輸入函數,即按用戶指定的格式從鍵盤上把數據輸入到指定的變量之中。

什麼樣的類型,可以接收取地址得到的地址?

指針
· 指針類型的變量就是保存地址的變量

int i;
int* p = &i; //“*”,指針符號,*p,表示p是一個指針
int* p,q;
int *p,q;

我們來看 int* p = &i;的含義,如果i的地址是0x0001,那麼p的的地址就是0001,從這裏可以得出p指向了i
當我們說p指向i時,其實就是說p的值指向了i那個變量的地址
在這裏插入圖片描述

    int* p,q;
    int *p,q;

他們的含義都帶*,表示* p*p都表示p是一個int型的指針(這裏的*靠近int或是靠近p含義都是一樣的,),而q是一個普通的int類型

指針變量
· 變量的值是內存的地址
· 普通變量的值是實際的值
· 指針變量的值是具有實際值的變量地址

~
*作爲參數的指針
· void f(int p);
· 在被調用的時候得到了某個變量的地址
· int i=0;f(&i);
· 在函數裏面可以通過這個指針訪問外面的i

void f(int *p); f函數是它是一個int類型的指針,在我們去調用這個f時,就需要給它一個地址,而不能給一個變量本身或者是這個變量的值
int i=0;f(&i); 用&符號取得變量i的地址,將這個地址賦予指針p

下面來看下例子

void f(int *p);

int main(void)
{
	int i = 6;
	printf("&i=%p\n", &i);// 打印出i的地址
	f(&i);// 將i的地址賦予f 
	return 0;
} 

void f(int *p)
{
	printf(" p=%p\n", p); // 打印出p的值,看他們是否相等	
}

運行結果

&i=0061FE9C
p=0061FE9C

這裏看出,在main裏有一個變量i=6,它的地址是 9C ,我們將9C這個地址取出來賦予了另外一個變量p,p的值是70,同時可以理解爲p是一個指針,指向了變量i

有了上面的情況後,在f函數裏面,我們有外面的main裏面的i的地址,我們不知道它是i,我麼只知道它的地址

如果不傳地址進去,只得到它的值會是什麼情況,看看下面的例子,新增g 函數

void f(int *p);
void g(int k); // 新增g函數 

int main(void)
{
	int i = 6;
	printf("&i=%p\n", &i); // 打印出i的地址
	f(&i); // 將i的地址賦予f 
	g(i); // 將i的值賦予g函數 
	return 0;
} 

void f(int *p) // 將*p的值賦予f 
{
	printf(" p=%p\n", p); // 打印出p的值,看他們是否相等	
}

void g(int k) // 
{
	printf(" k=%d\n", k); //打印出g,g得到的是i的值, 
} 

輸出結果

&i=0061FE9C
p=0061FE9C
k=6

在g函數裏,k取到的值k=i=6,k和外面的i沒有任何關係,這是之前函數課程裏的內容,現在我們通過指針變量p得到了i的地址,這使得f函數裏面擁有能夠訪問外面那個函數的地址的能力

*訪問那個地址上的變量
· *是一個單目運算符,用來訪問指針的值所指向的地址上的變量
· 拿到這個變量後,它可以拿來做左值也可以拿來做右值
· int k= p;
· p = k+1;

void f(int *p);
void g(int k); // 新增g函數 

int main(void)
{
	int i = 6;
	printf("&i=%p\n", &i); // 打印出i的地址
	f(&i); // 將i的地址賦予f 
	g(i); // 將i的值賦予g函數 
	return 0;
} 

void f(int *p) // 將*p的值賦予f 
{
	printf(" p=%p\n", p); // 打印出p的值,看他們是否相等
	printf("*p=%d\n",*p); // 打印*p的值,將*p看成一個整數的整體	
}

void g(int k) // 
{
	printf(" k=%d\n", k); //打印出g,g得到的是i的值
 
} 

輸出結果

&i=0061FE9C
 p=0061FE9C
*p=6
 k=6

在這裏,我們通過*p這個指針訪問到了int i 的值

如果我們給 *p =26時,i 的值會不會被改變?
那麼我們可以通過調用g函數訪問i的值

void f(int *p);
void g(int k); // 新增g函數 

int main(void)
{
	int i = 6;
	printf("&i=%p\n", &i); // 打印出i的地址
	f(&i); // 將i的地址賦予f 
	g(i); // 將i的值賦予g函數 
	return 0;
} 

void f(int *p) // 將*p的值賦予f 
{
	printf(" p=%p\n", p); // 打印出p的值,看他們是否相等
	printf("*p=%d\n",*p); // 打印*p的值,將*p看成一個整數的整體
	*p = 26;	
}

void g(int k) // 
{
	printf(" k=%d\n", k); //打印出g,g得到的是i的值
 
} 

輸出結果

&i=0061FE9C
p=0061FE9C
*p=6
k=26

從這裏看出,i的值被f函數調用後被改變了
我們在*p=26;時,也可以理解爲是對i進行了改變,這就是指針

**指針*左值之所以叫左值
· 是因爲出現在賦值號左邊的不是變量,而是值,是表達式計算的結果:
· a[0] = 2;// 數組,取下標運算符,a[0]是運算結果
· *p = 3; // 是運算符,p是取得p的指針的地址所代表的變量,表達是運算的結果
· 指針是特殊的值,所以叫做左值

*指針的運算符&
· 互相反作用
· *&yptr -> *(&yptr) -> *(yptr的地址) ->得到地址上的變量 -> yptr
· &yptr -> &(yptr) -> &(y) ->得到y得地址,也就是yptr -> yptr

傳入地址
· 爲什麼
· int i;scanf("%d",i);
· 當我們用scanf時,忘記&時編譯沒有報錯,運行起來就會犯錯

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