自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

聊聊C語言中使用頻率較高的指針與數(shù)組

開發(fā) 前端
指針和數(shù)組在C語言中使用頻率是很高的,在極個別情況下,數(shù)組和指針是“通用的”,比如數(shù)組名表示這個數(shù)組第一個數(shù)據(jù)的指針。

定義

指針:C語言中某種數(shù)據(jù)類型的數(shù)據(jù)存儲的內(nèi)存地址,例如:指向各種整型的指針或者指向某個結(jié)構(gòu)體的指針。

數(shù)組:若干個相同C語言數(shù)據(jù)類型的元素在連續(xù)內(nèi)存中儲存的一種形態(tài)。

數(shù)組在編譯時就已經(jīng)被確定下來,而指針直到運行時才能被真正的確定到底指向何方。所以數(shù)組的這些身份(內(nèi)存)一旦確定下來就不能輕易的改變了,它們(內(nèi)存)會伴隨數(shù)組一生。

而指針則有很多的選擇,在其一生他可以選擇不同的生活方式,比如一個字符指針可以指向單個字符同時也可代表多個字符等。

指針和數(shù)組在C語言中使用頻率是很高的,在極個別情況下,數(shù)組和指針是“通用的”,比如數(shù)組名表示這個數(shù)組第一個數(shù)據(jù)的指針。

如下代碼:

#include <stdio.h>
char array[4] = {1, 2, 3, 4};
int main(void)
{
char * p;
int i = 0;
p = array;
for (; i < 4; i++)
{
printf("*array = %d\n", *p++);
}
return (0);
}

這里我們將數(shù)組名array作為數(shù)組第一個數(shù)據(jù)的指針賦值給p。但是不能寫成*array++。準確來說數(shù)組名可以作為右值,不能作為左值(左值和右值的概念這里不再展開講解)。

數(shù)組名的值其實是一個指針常量,這樣我想你就明白了數(shù)組名為什么不能做為左值了。如果想用指針p訪問array的下面2的數(shù)據(jù),以下寫法是合法的。


char data;
/*第一種寫法*/
p = array;
data = p[2];
/*第二種寫法*/
p = array;
data = *(p+2);
/*第三種寫法*/
p = array +

指針與二維數(shù)組

先說一下二維數(shù)組,二維數(shù)組在概念上是二維的,有行和列,但在內(nèi)存中所有的數(shù)組元素都是連續(xù)排列的,它們之間沒有“縫隙”。以下面的二維數(shù)組 a 為例:

int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} };

從概念上理解,a 的分布像一個矩陣:

  • 0 1 2 3。
  • 4 5 6 7。
  • 8 9 10 11。

但是內(nèi)存是連續(xù)的,沒有這樣的“矩陣內(nèi)存”,所以二維數(shù)組a分布是連續(xù)的一塊內(nèi)存。

C語言允許把一個二維數(shù)組分解成多個一維數(shù)組來處理。對于數(shù)組 a,它可以分解成三個一維數(shù)組,即 a[0]、a[1]、a[2]。每一個一維數(shù)組又包含了 4 個元素,例如 a[0] 包含 a[0][0]、a[0][1]、a[0][2]、a[0][3]。那么定義如下指針如何理解呢?

int (*p)[4];

括號中的*表明 p 是一個指針,它指向一個數(shù)組,數(shù)組的類型為int [4],這正是 a 所包含的每個一維數(shù)組的類型。那么和下面定義有什么區(qū)別呢?

int *p[4];

這里就要先說明*和[]的優(yōu)先級了,[]的優(yōu)先級是高于*的,所以int *p[4];等同于int *(p[4]);。所以它是一個指針數(shù)組。這里很繞,總接下:

int (*p)[4];是數(shù)組指針,它指向二維數(shù)組中每個一維數(shù)組的類型,它指向的是一個數(shù)組。

int *p[4];是指針數(shù)組,它是一個數(shù)組,數(shù)組中每個數(shù)是指向int型的指針。

指針數(shù)組與數(shù)組指針

對于指針數(shù)組,說的已經(jīng)很明確了,不再詳細講解,下面說一下數(shù)組指針。舉例看一下:

#include <stdio.h>
int main()
{
int a[3][4] = {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}};
int(*p)[4];
p = a;
printf("%d\n", sizeof(*(p + 1)));
return (0);
}

對于數(shù)組指針p如下:

那么printf("%d\n", sizeof(*(p + 1)));的結(jié)果就是16。如果想打印a[1][0]的值,代碼如下:

printf("%d\n", *(*(p + 1)));

如果想打印a[1][1]的值,代碼如下:

printf("%d\n", *(*(p + 1)+1));

這個代價自行體會,p是數(shù)組指針,它指向的是一個數(shù)組,所以對獲取它指向的值,也就是*p,是指向一個數(shù)組還是一個值,指向a[0]。獲取獲取a[0][0],就需要寫成**p。

對指針進行加法(減法)運算時,它前進(后退)的步長與它指向的數(shù)據(jù)類型有關(guān),p 指向的數(shù)據(jù)類型是int [4],那么p+1就前進 4×4 = 16 個字節(jié),p-1就后退 16 個字節(jié),這正好是數(shù)組 a 所包含的每個一維數(shù)組的長度。也就是說,p+1會使得指針指向二維數(shù)組的下一行,p-1會使得指針指向數(shù)組的上一行。

最后再次捋一下數(shù)組指針和指針數(shù)組。

int *p1[4];是指針數(shù)組。

int (*p2)[4];是數(shù)組指針。

“[]”的優(yōu)先級比“*”要高。

對于指針數(shù)組,p1先和“[]”結(jié)合,構(gòu)成一個數(shù)組的定義,數(shù)組名為p1,int *修飾的是數(shù)組的內(nèi)容,即數(shù)組的每個元素。那么它本質(zhì)是一個數(shù)組,這個數(shù)組里有4個指向int類型數(shù)據(jù)的指針。

對于數(shù)組指針,“()”的優(yōu)先級比“[]”高,“*”號和p2 構(gòu)成一個指針的定義,指針變量名為p2,int 修飾的是數(shù)組的內(nèi)容,即數(shù)組的每個元素。數(shù)組在這里并沒有名字,是個匿名數(shù)組。那么它本質(zhì)是一個指針,它指向一個包含4個int 類型數(shù)據(jù)的數(shù)組。

既然深入談了指針數(shù)組和數(shù)組指針,就多聊一下。

#include <stdio.h>
int main()
{
char a[5] = {'A', 'B', 'C', 'D'};
char(*p3)[5] = &a;
char(*p4)[5] = a;
return 0;
}

上面代碼是編譯編譯是報了waring的,報警如下:

注意:不同的編譯器編譯結(jié)果可能不同,我的編譯方法請參考《使用vscode編譯C語言》。p3 這個定義的“=”號兩邊的數(shù)據(jù)類型完全一致,而p4 這個定義的“=”號兩邊的數(shù)據(jù)類型就不一致了。左邊的類型是指向整個數(shù)組的指針,右邊的數(shù)據(jù)類型是指向單個字符的指針。所以才有了上面的警告。

但由于&a 和a 的值一樣,而變量作為右值時編譯器只是取變量的值,所以運行并沒有什么問題。不過編譯器仍然警告你別這么用。

再舉一個栗子:

int vector[10];
int matrix[3][10];
int *vp,*vm;
vp = vector;
vm = matrix;

上面的代碼第5行是錯誤的,因為vm是指向整型的指針,但是matrix不是指向正向的指針,他是指向整型數(shù)組的指針。下面是正確的寫法:

int matrix[3][10];
int (*vm)[10];
vm = matrix;

數(shù)組指針的應(yīng)用

上面說了那么多,可能大部分開發(fā)者用不到,數(shù)組指針在很多時候都是可以代替二維數(shù)組的,有些程序員喜歡用指針數(shù)組來代替多維數(shù)組,一個常見的用法就是處理字符串。

#include <stdio.h>
char *Names[] =
{
"Bill",
"Sam",
"Jim",
"Paul",
"Charles",
0};
void main()
{
char **nm = Names;
while (*nm != 0)
printf("%s \n", *nm++);
}

具體運行我就不講解了,運行結(jié)果如下:

注意數(shù)組中的最后一個元素被初始化為0,while循環(huán)以次來判斷是否到了數(shù)組末尾。具有零值的指針常常被用做循環(huán)數(shù)組的終止符。

這種零值的指針稱為為空指針(NULL)。采用空指針作為終止符,在增刪元素時就不必改動遍歷數(shù)組的代碼,因為此時數(shù)組仍然以空指針作為結(jié)束。

操作

寫到這里想到一個“操作”,先看下面代碼是否正確。

p[-1]=0;

初看這句代碼,覺得奇怪,甚至覺得它就是錯誤,日常C語言開發(fā)基本有見到小標是負數(shù)的,但是仔細想想沒有哪一本書說過下標能為負數(shù)的。看下面代碼:

void main()
{
int data[4] = {0, 1, 2, 3};
int *p;
p = data +2;
printf("p[-1] is %d\n",p[-1]);
printf("*(p-1) is %d\n",*(p-1));
}

運行結(jié)果如下:

不僅可以編譯通過,還能正確的輸出結(jié)果為1。這表明,C的下標引用和間接訪問表達式是一樣的。當然不鼓勵這種操作,代碼需要很強的可讀性,而不是這樣的操作,這里只是演示下標引用和簡介表達式的關(guān)系。

責任編輯:姜華 來源: 知曉編程
相關(guān)推薦

2021-07-13 06:44:04

Go語言數(shù)組

2014-08-01 15:16:05

SwiftC語言

2009-06-30 10:46:05

多級指針

2021-12-06 11:19:47

語言指針內(nèi)存

2023-10-27 11:21:20

C語言Multics語言

2022-01-06 14:25:24

C語言指針內(nèi)存

2023-10-04 00:01:00

sizeofC 語言

2023-12-21 11:46:48

C語言柔性數(shù)組開發(fā)

2011-05-25 13:22:05

PHPJSON

2011-05-13 17:25:34

C

2010-07-13 15:34:09

Perl語言

2024-05-17 08:47:33

數(shù)組切片元素

2013-06-25 09:52:32

GoGo語言Go編程

2010-07-26 16:23:23

Perl語言

2023-03-02 19:36:34

C語言

2011-05-17 13:04:20

Cconst

2016-12-05 13:35:02

C語言數(shù)組指針

2023-01-31 08:48:49

Go語言文件

2015-04-15 14:41:40

c語言數(shù)組名a&a詳細介紹

2009-06-12 15:01:48

Java數(shù)組Java教程
點贊
收藏

51CTO技術(shù)棧公眾號