C語言指針――指針和數組
來源:程序員人生 發布時間:2014-10-12 20:00:12 閱讀次數:3328次
先看一個常用的例子:
#include <stdio.h>
int main(void)
{
int a[3] = {1,2,3};
int *p = a;
printf("%d ", p[0]);
return 0;
}
這段代碼編譯和運行都沒有任何問題,程序會打印出1這個值,但是為什么可以這樣用呢?p明明是一個int類型的指針,這里怎么可以使用p[0]這種數組的操作呢?而且我們使用sizeof去測試a和p得到的一個是a數組的大小,一個是p指針的大小,這兩個類型是不一樣的。其實這個是C語言內部的原因,一個指針變量在使用類似p[]這樣的運算的時候,編譯器內部相當于對p做了一次類型提升,將p其提升為該類型的數組,注意這里僅僅會提升一次哦!看下面的例子:
#include <stdio.h>
int main(void)
{
int a[3][3] = {1,2,3,4,5,6,7,8,9};
int *p = (int *)a;
printf("%d ", p[0]);
return 0;
}
首先需要注意的是,(int *)這個是必不可少的,因為int型二維數組的首地址是不能直接賦值給int *變量的。其次這段代碼也是可以正常輸出1的,這個程序的理解跟上一個類似。再看下面一個代碼:
#include <stdio.h>
int main(void)
{
int a[3][3] = {1,2,3,4,5,6,7,8,9};
int *p = (int *)a;
printf("%d ", p[0][0]);
return 0;
}
這段代碼編譯或者運行的時候會出錯嗎?答案是編譯的時候會報錯,因為p是一個int類型的指針,使用[]這種運算的時候編譯器會將其提升一次,僅僅是一次,所以p最多會被提升到一維數組的程度,然而這里的p[0][0]這樣的操作顯然是針對二維數組的,編譯器不允許這樣的用法。再看下面的例子:
#include <stdio.h>
int main(void)
{
int a[3][3] = {1,2,3,4,5,6,7,8,9};
int (*p)[3] = a;
printf("%d ", p[0][0]);
return 0;
}
注意這個例子,編譯和運行都不會出錯,因為p是一個數組指針,a直接賦值給p也不會出錯,這里也說明,數組在給該類型的指針賦值的時候,編譯器默認最多降一級,也就是說一維數組給指針直接賦值編譯器允許,二維數組給該類型的數組指針賦值編譯器允許,但是跨過兩級就不行了,就像上一個例子。同時從這里也可以看出,p[0][0]這樣的操作是允許的,p被提升為二維數組,p也是被提升了一級。這段代碼會打印出1。再看下面的例子:
#include <stdio.h>
int main(void)
{
int a[3][3] = {1,2,3,4,5,6,7,8,9};
int (*p)[3] = a;
printf("%d ", p[1]-p[0]);
return 0;
}
這段代碼的編譯和運行都沒有出錯,打印的值是多少呢?首先來分析一下這個程序,p[1]中的p表示的是一個數組指針,然而使用p[]這種操作,p會被提升一級成為一個二維數組的形式,那么p[1]就相當于a[1],p[0]就相當于a[0],那么a[1]-a[0]的值是多少呢?a[1]是二維數組a中第二個[3]一維數組的首地址,而a[0]是a中第一個[3]一維數組的首地址,所以兩個首地址之間相差sizeof(int)*3,然而由于這里是指針(地址)的運算,所以這里的值應該是(sizeof(int)*3)/sizeof(int),所以最終的輸出結果為3。再看下面的代碼:
#include <stdio.h>
int main(void)
{
int a[3][3] = {1,2,3,4,5,6,7,8,9};
int (*p)[3] = a;
printf("%d ", *p[0]);
return 0;
}
這段代碼會輸出什么呢?答案是輸出1。首先需要知道的是[]運算的優先級高于*運算符,然后p[0]代表的是a[0]也就是第一個一維數組的首地址,然后使用*(地址)這種寫法的時候,取的是這個地址的值,所以也就是a[0][0]的值,因為a[0]=&a[0][0]。再看下面的例子:
#include <stdio.h>
int main(void)
{
int a[3][3] = {1,2,3,4,5,6,7,8,9};
int (*p)[3] = a;
printf("%d ", *(p+1)[0]);
return 0;
}
這段代碼會輸出什么呢?答案是4。首先p是一個數組指針,所以p+1的運算對應過去編譯器理解是指到下一個一維數組的首地址,所以p+1實際上的值為p+1*sizeof(int)*3,后面的理解就跟上面的相同了。
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈