1.指針變量的聲明和初始化
指針就是把內存地址做為其值的變量。
(1)指針是一個變量
(2)普通變量直接引用了一個值
如:
那么a的值就是3。
(3)指針變量只存放內存地址
(4)指針存放的內存地址往往存放有實際的值,但也可能是另外一個指針
如:
int a = 3;
int * aptr = &a;//把a的地址通過取地址運算符賦給指針變量 aptr
printf ("%p", aptr);//打印出指針的值,用16進制的方式
printf ("%p", &a);//打印出a的地址,用16進制的方式
(5)指針變量名間接應用了一個值,我們使用間接引用運算符來取得具體的值
printf (”%d”, *aptr);
(6)指針必須初始化,可以把指針初始化為NULL
NULL在中定義,它的值是0
使用NULL使程序具有可讀性。
注意:
& 取地址運算符 取得任何變量的地址
如:
int a;
int *aptr;
int c[5];
//使用&運算符取得地址,并打印出來
printf ("%p\n", &a);//取得整型變量a的內存地址
printf ("%p\n", &aptr);//取得指針變量aptr的內存地址
printf ("%p\n", &c[0]);//取得數組第一個元素的內存地址
* 比較讓大家迷惑的是它在這里有兩種不同的用法,但實際上它們并不是同樣的
(1)和具體的數據類型一起構成對應的指針類型
*在聲明語句表示變量是一個指針
int *
float *
char *
double *
(2)間接引用運算符
int a = 3;
int * aptr = &a;//把a的地址通過取地址運算符賦給指針變量 aptr
printf ("%d", *aptr);//通過a的地址間接引用變量a的值
思考:
仔細分析下面的語句的結果。
int a = 8;
int * aPtr;
aPtr = &a;
printf ("%p\n", & * aPtr);
printf ("%p\n", * & aPtr);
提示,一層層分析,可以看做 &(*aPtr)
答案在最下面。
二、指針的傳引用調用
1.C語言中所有的函數都是傳值調用
為什么,難道指針不是傳引用調用嗎?
不是,C語言只是把指針的值拷貝一份,傳如函數內部。
2.那么傳遞數組呢?
void printArray (int *nPtr);
和
void printArray (int array[]);
的效果都是一樣的,都是傳一個地址進去。
另外,要注意:
數組名本身就是地址。
3.指針的傳引用調用我們也可稱之為模擬傳引用調用,因為我們傳的是一個地址,
函數調用時,函數的參數會拷貝這個地址,然后通過復引用來操作變量。
int cubeByReference (int * nPtr)//計算立方
{
*nptr = *nptr * *nptr * *nptr;
}
注意這里,
(1)*(復引用運算符)比*(乘法運算符)優先級要高。
所以可以不適用括號,但是推薦你使用下面的語句,這樣程序更加清晰。
(2)nPtr是占用堆棧的,函數cubeByReference會給nPtr這個指針變量分配空間,
然后把傳入的指針變量的值賦給它。
int cubeByReference (int * nPtr)//計算立方
{
(*nptr) = (*nptr) * (*nptr) * (*nptr);
}
4.傳值為什么不改變傳入變量的值
因為它是在堆棧中生成一個新的變量,然后把存放的值拷貝過來,最后函數結束的時候把該變量從堆棧中釋
放掉,所以并不會改變傳入變量的值。
就像你用一張新的紙把一張紙上的東西復制一遍,然后在新的紙上寫寫畫畫,然后丟掉,并不會影響到原來
的紙上的內容。
5.傳指針(也就是傳引用為什么會改變)
因為指針給出了原來變量的地址,使得*(復引用指針)可以通過這個地址找到這個變量并對它進行修改。
三、指針的const限定
(1)指向非常量數據的非常量指針
int a;
int b;
int *aPtr;
aPtr = &a;//OK
aPtr = &b;//OK
*aptr = 3;//OK
(2)指向常量數據的非常量指針(不能修改指向變量中的數據)
注意:const 修飾int
int a;
int b;
const int *aPtr;
aPtr = &a;//OK
aPtr = &b;//OK
*aptr = 3;//ERROR 不能修改指向的變量中的數據
(3)指向非常量數據的常量指針(不能東指西指)
注意: const 修飾指針變量 aptr;
數組名是一個很好的例子。(參見字符串數組中的說明。)
int a;
int b;
const int *aPtr = &a;
aPtr = &b;//ERROR 不能再指向另外一個變量
*aptr = 3;//OK
(4)指向常量數據的常量指針(不能修改指向變量中的數據,不能東指西指)
const int * const aPtr;
int a;
int b;
const int * const aPtr = &a;
aPtr = &b;//ERROR 不能再指向另外一個變量
*aptr = 3;//ERROR 不能修改指向的變量中的數據
答案:
1.實際上*aPtr相當于a, &*aPtr就取得a的地址
2.&aPtr取得aPtr的直至,而*&aPtr就取得aPtr存放的值,也就是a的地址
3.&*會相互抵消,實際上&*aPtr == aPtr == *&aPtr