指針概念
指針是一個變量粗井,該變量的數(shù)值是地址枝哄,或者說愈犹,指針是一個數(shù)據(jù)對象键科。
類似于,int 類型變量的數(shù)值是整數(shù)漩怎。
與指針相關的運算符
間接運算符:*
ptr 指向 bath勋颖,ptr = &bath
。
獲取 bath 中存放的數(shù)值勋锤,val = * ptr
饭玲。
上面兩句語句等價于 val = bath
。
地址運算符:&
后跟一個變量名時怪得,&
給出該變量的地址咱枉。
指針聲明
int * pi;
int
表明被指向的變量的類型是整型卑硫,*
表示該變量是一個指針徒恋。pi
所指向的值(*pi)
是 int
類型,pi
的
類型是“指向 int 的指針”欢伏。
*
和指針名之間的空格是可選的入挣。
指針的輸出格式是 %p
。
使用指針在函數(shù)間通信
結合 PHP 中函數(shù)的引用賦值來理解硝拧。
變量的值在函數(shù)中改變還是全局改變径筏。
指針和數(shù)組
概念
在 C 中,對一個指針加 1 的結果是對該指針增加 1 個存儲單元(storage unit)障陶。對數(shù)組而言滋恬,地址會增加到下一個元素的地址,而
不是下一個字節(jié)抱究。歸納如下:
指針的數(shù)值就是它所指向的對象的地址恢氯。對于包含多個字節(jié)的數(shù)據(jù)類型,對象的地址通常是指其首字節(jié)的地址鼓寺。
在指針前運用運算符
*
可以得到該指針所指向的對象的數(shù)值勋拟。對指針加1,等價于對指針的值加上它所指向的對象的字節(jié)大小妈候。
函數(shù)敢靡、數(shù)組和指針
聲明數(shù)組參量
下面的四種原型都是等價的
int sum(int *ar, int n);
int sum(int *, int);
int sum(int ar[], int n);
int sum(int [], int);
定義函數(shù)時,下面兩種形式等價
int sum(int * ar, int n)
{
}
int sum(int ar[], int n)
{
}
聲明形式參量時苦银,int *ar
和 int ar[]
都表示 ar
是指向 int
的指針啸胧。
sizeof
求變量赶站、指針、數(shù)組大小纺念。
使用指針參數(shù)
使用數(shù)組形參的函數(shù)需要知道數(shù)組的起點和終點亲怠。告知終點有兩種方法,一種是直接使用整數(shù)參量指明數(shù)組元素的個數(shù)柠辞,一種是用指針
指明數(shù)組的結束地址团秽。比如,
int sum(int * start, int * end);
若數(shù)組的元素個數(shù)是 SIZE
叭首,那么习勤,* end
的值是 &start + SIZE
(表示數(shù)組的最后一個元素后面的下一個元素)。
一元運算符 *
和 ++
具有相等的優(yōu)先級別焙格,但它在結合時是從右向左進行的图毕。
指針操作
指針基本操作
- 賦值(assignment)。
通常使用數(shù)組名或地址運算符&
進行地址賦值眷唉。地址應該和指針類型兼容予颤。
求職(value-finding)或取值(dereferencing)。
取指針地址冬阳。
將一個整數(shù)加給指針蛤虐。
增加指針的值。
從指針中減去一個整數(shù)肝陪。
減小指針的值驳庭。
求差值(Differencing)。指向同一個數(shù)組內(nèi)兩個元素的指針使用此運算氯窍。
比較饲常。兩個指針具有相同的類型。
對未初始化的指針取值
不能對未初始化的指針取值狼讨。例如
int * pt; // 未初始化的指針
*pt = 5;
合法的代碼
int i = 5;
int * pt = &i;
或者
double * ptd;
ptd = (double)malloc(30 * sizeof(double));
指針和多維數(shù)組
例程
#include <stdio.h>
int main(void)
{
int zippo[4][2] = {{2, 4}, {6, 8}, {1, 3}, {5, 7}};
printf(" zippo = %p, zippo + 1 = %p\n",
zippo, zippo + 1);
printf("zippo[0] = %p, zippo[0] + 1 = %p\n",
zippo[0], zippo[0] + 1);
printf(" *zippo = %p, *zippo + 1 = %p\n",
*zippo, *zippo + 1);
printf("zippo[0][0] = %d\n", zippo[0][0]);
printf(" *zippo[0] = %d\n", *zippo[0]);
printf(" **zippo = %d\n", **zippo);
printf(" zippo[2][1] = %d\n", zippo[2][1]);
printf("*(*(zippo+2) + 1) = %d\n", *(*(zippo+2) + 1));
return 0;
}
代碼見 E:\code\c\c_primer_plus_c\10_15_zippo1.c
贝淤。
這段代碼中的疑點:*zippo[0]
、**zippo
政供。
聲明指向二維數(shù)組的指針變量
正確的代碼
int (* pz)[2]; // 聲明一個指向二維數(shù)組pz[n][2]的指針
錯誤的代碼
int * pax[2]; // 創(chuàng)建一個兩個指針的數(shù)組
指針兼容
int n = 5;
double x;
int * pi = &n;
double * pd = &x;
x = n; // 隱藏的類型轉換
pd = pi; // 編譯時錯誤
假如有如下聲明:
int * pt;
int (*pa)[3];
int ar1[2][3];
int ar2[3][2];
int **p2; // 指向指針的指針
那么播聪,有如下結論:
pt = &ar1[0][0]; // 都指向int
pt = ar1[0]; // 都指向int
pt = ar1; // 非法
pa = ar1; // 都指向int[3]
pa = ar2; // 非法
p2 = &pt; // 都指向 int *
*p2 = ar2[0]; // 都指向int。不理解
p2 = ar2; // 非法鲫骗。不理解
保護數(shù)組內(nèi)容
對形參使用 const
如果不打算在函數(shù)中修改數(shù)組犬耻,在函數(shù)原型和函數(shù)定義中對參數(shù)使用 const
可以達到目的。例程如下:
int sum(const int ar[], int n);
int sum(const int ar[], int n)
{
int i;
int total = 0;
for(i = 0; i < n; i++)
total += ar[i];
return total;
}
使用了 const
执泰,在函數(shù)中試圖修改使用了 const
的參數(shù)時枕磁,編譯時會發(fā)現(xiàn)此錯誤。
有關 const 的其他內(nèi)容
使用 const 創(chuàng)建符號常量术吝。
const double PI = 3.14159;
指向常量的指針不能用于修改數(shù)值计济,但可以指向其他地址茸苇。
double rates[5] = {88.99, 100.12, 59.45, 183.11, 340.5};
const double * pd = rates; // pd指向數(shù)組開始處
* pd = 29.89; // 不允許
pd[2] = 222.22; // 不允許
rates[0] = 99.99; // 允許,因為 rates 不是常量
pd++; // 讓pd指向rates[1]沦寂,允許
將常量或非常量數(shù)據(jù)的地址賦給指向常量的指針是合法的学密。
double rates[5] = {88.99, 100.2, 59.45, 183.11, 340.5};
const double locked[4] = {0.08, 0.075, 0.0725, 0.07};
const double * pc = rates; // 合法
pc = locked; // 合法
pc = &rates[3]; // 合法
只有非常量數(shù)據(jù)的地址才可以賦給普通的指針。
double rates[5] = {88.99, 100.2, 59.45, 183.11, 340.5};
const double locked[4] = {0.08, 0.075, 0.0725, 0.07};
double * pnc = rates; // 合法
pnc = locked; // 非法
pnc = &rates[3]; // 合法
使用 const 保證指針不會指向別處传藏。
double rates[5] = {88.99, 100.2, 59.45, 183.11, 340.5};
double * const pc = rates; // 指針指向數(shù)組的開始處
pc = &rates[2]; // 不允許
*pc = 92.99; // 可以
使用 const 禁止修改所指向的數(shù)據(jù)腻暮。
double rates[5] = {88.99, 100.2, 59.45, 183.11, 340.5};
const double * const pc = rates; // 指針指向數(shù)組的開始處
pc = &rates[2]; // 不允許
*pc = 92.99; // 不允許
參考資料
《C Primer Plus(第五版)中文版》
- 指針簡介: P236-9.7
- 指針和數(shù)組: P254-10.3
- 函數(shù)、數(shù)組和指針: P256-10.4
- 指針操作: P260-10.5
- 指針和多維數(shù)組: P267-10.7
- 保護數(shù)組內(nèi)容: P263-10.6