指針變量就是記錄地址的變量
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時,忘記&時編譯沒有報錯,運行起來就會犯錯