日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言再学习 -- 数组和指针

發(fā)布時間:2025/3/15 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言再学习 -- 数组和指针 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、數(shù)組

1、數(shù)組介紹

數(shù)組(array)由一系列類型相同的元素構成。例如:

int arr[10];

float candy[25];

char code[12];

以上數(shù)組聲明中包括數(shù)組元素的數(shù)目和元素的類型。數(shù)組元素按順序存儲于內(nèi)存中,通過使用整數(shù)索引(或偏移量)來訪問。在C中,首元素的索引值為0,因此包含n個元素的數(shù)組的末元素的索引為n-1。


2、數(shù)組初始化

A、可以使用花括號括起來的一系列數(shù)值來初始化數(shù)組。數(shù)組之間用逗號隔開,在數(shù)值和逗號之間可以使用空格符。例如:

int arr[5] = {1, 2, 3, 4, 5};

B、當數(shù)值數(shù)目少于數(shù)組元素數(shù)目時,多余的數(shù)組元素被初始化為0。也就是說,如果不初始化數(shù)組,數(shù)組元素和未初始化的普通變量一樣,其中存儲的是無用的數(shù)值,但是如果部分初始化數(shù)組,未初始化的元素則被設置為0。例如:

int arr[10] = {1, 2, 3, 4, 5}; 默認后五位未初始化元素為0。

C、如果初始化列表中項目的個數(shù)大于數(shù)組大小,編譯器會毫不留情地認為這是一個錯誤。你可以省略括號中的數(shù)字,從而讓編譯器自動匹配數(shù)組大小和初始化列表中的項目數(shù)目。例如:

int arr[] = {1, 2, 3, 4, 5};

需要注意:

當使用空的方括號對數(shù)組進行初始化時,編譯器會根據(jù)列表中的數(shù)值數(shù)目來確定數(shù)組大小。

可通過sizeof計算數(shù)組元素數(shù)目,例如:

int arr[] = {1, 2, 3, 4, 5};?

數(shù)組元素數(shù)目 = sizeof (arr) / sizeof (int);

D、字符串數(shù)組初始化,例如:

char code[] = "hello world";

char code[] = {'h' ,'e' ,'l' ,'l' ,'o' ,' ' ,'w' ,'o' ,'r' ,'l' ,'d' ,'\0'};

注意標志結(jié)束的空字符,如果沒有它,得到的就只是一個字符數(shù)組而不是一個字符串。指定數(shù)組大小時,一定要確保數(shù)組元素比字符串長度至少多1 (多出來的1個元素用于容納空字符),未被使用的元素均被自動初始化為0。這里的0是char形式的空字符,而不是數(shù)字字符0。

E、采用宏定義#define指令創(chuàng)建一個指定數(shù)組大小的明顯常量 (SIZE),可以在定義數(shù)組和設置循環(huán)限制時使用這個常量,以后更改數(shù)組大小的時候方便處理,例如:

#define SIZE 5

int arr[SIZE];

for (int n = 0; n < SIZE; n++) {....};

F、指定初始化項目(C99)

例如:int arr[6] = {[5] = 2}; ?//把arr[5]初始化為2 ??

等于:int arr[6] = {0, 0, 0, 0, 0, 2};

說明:對于通常的初始化,在初始化一個或多個元素后,未經(jīng)初始化的元素都將被設置為0.

再如:int day[12] = {31, 28, [4] = 31, 30, 31, [1] = 29};

等于:int day[12] = {31, 29, 0, 0, 31, 30, 31, 0, 0, 0, 0, 0};

說明:

第一,如果在一個指定初始化項目后跟有不止一個值,,例如在序列 [4] = 31, 30, 31中這樣,則這些數(shù)值將用來后續(xù)的數(shù)組元素初始化。

第二,如果多次對一個元素進行初始化,則最后的一次有效。錄入在序列中前面days[1]初始化為28,而后面的指定初始化 [1] = 29覆蓋了前面的數(shù)值,于是day[1]的數(shù)值最終為29.

3、數(shù)組賦值

聲明完數(shù)組后,可以借助數(shù)組的索引(即下標)對數(shù)組成員進行賦值。C不支持把數(shù)組作為一個整體來進行賦值的,也不支持用花括號括起來的列表形式進行賦值 (初始化的時候除外)??墒褂醚h(huán)對元素逐個賦值。

#include <stdio.h> #define SIZE 5 int main (void) {int n;int arr[SIZE] = {1, 2, 3, 4, 5}; /"數(shù)組初始化"/int code[SIZE]; code = arr; /"不允許"/code[SIZE] = arr[SIZE]; /"不正確"/code[SIZE] = {1, 2, 3, 4, 5}; /"不起作用"/for (n = 0; n < SIZE; n++) /"循環(huán)對元素逐個賦值"/arr[n] = 2*n;return 0; }

4、數(shù)組邊界

使用數(shù)組的時候,需要注意數(shù)組索引不能超過數(shù)組的邊界,例如:

int arr[5];

那么在使用數(shù)組索引的時候,要確保它的范圍在0和4之間,因為編譯器不會檢測出這種錯誤,例如:

arr[5] = 3; //沒有這個數(shù)組元素

arr[6] = 4; //沒有這個數(shù)組元素

在標準C中并不檢查是否使用正確的下標,不檢查邊界能夠讓C程序的運行速度更快。當程序運行時,這些語句把數(shù)據(jù)放在可能由其他數(shù)據(jù)使用的位置上,因而可能破壞程序的結(jié)果甚至使程序崩潰。

5、指定數(shù)組大小

直到C99標準出現(xiàn)之前,聲明數(shù)組時在方括號內(nèi)只能使用整數(shù)常量表達式。整數(shù)常量表達式是由整數(shù)常量組成的表達式。sizeof表達式被認為是一個整數(shù)常量,而(和C++不同)一個const值卻不是整數(shù)常量。并且該表達式的值必須大于0.

#define SIZE 5 int n = 5; float a1[5]; //可以 float a2[5*2 + 1]; //可以 float a3[sizeof (int) +1]; //可以 float a4[-4]; //不可以,數(shù)組大小必須大于0 float a5[0]; //不可以,數(shù)組大小必須大于0 float a6[2.5]; //不可以,數(shù)組大小必須大于0 float a7[(int)2.5]; //可以,把float類型指派為int類型 float a8[n]; //C99之前不允許 float a9[SIZE]; //可以

6、數(shù)組函數(shù)

使用數(shù)組名作為實際參數(shù)時,主要的一點是要知道并不是把整個數(shù)組傳遞給函數(shù),而是傳遞它的地址;因此相應的形式參量是一個指針(數(shù)組做形參即指針)。處理數(shù)組時,函數(shù)必須知道數(shù)組的地址和元素的個數(shù)。數(shù)組地址直接傳遞給函數(shù),而數(shù)組元素的個數(shù)信息需要內(nèi)建于函數(shù)內(nèi)部或被作為獨立的參數(shù)傳遞給函數(shù)。后者更為通用,因為這種方法可以處理不同大小的數(shù)組。

下列4中原型都是等價的:

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) {...}

7、多維數(shù)組

A、int arr[5][12]; //5個有12個整數(shù)組成的宿主的數(shù)組,我們稱之為二維數(shù)組。

int arr[行][列];

arr[0]是數(shù)組,那么它的首元素是arr[0][0],第二個元素為arr[0][1],依此類推其他元素。它包含5行,每行12列。

注意:使用for嵌套循環(huán)結(jié)構處理二維數(shù)組時,“行”為外循環(huán),“列”為內(nèi)循環(huán),長循環(huán)為內(nèi)部循環(huán),短循環(huán)為外部循環(huán),那么“行”應該小于“列”。

B、初始化二維數(shù)組

例如:arr[2][3]={{1,2,3},{4,5,6}};

初始化使用了2個數(shù)值列表,每個數(shù)值列表都用花括號括起來。如果第一個列表有2個數(shù)值,則第一行只有前2個元素得到賦值,最后1個元素被默認初始化為0.如果列表中的數(shù)值多余3個,則報告錯誤;而且這些數(shù)值不會影響到下一行的賦值。

初始化的時候也可以省略內(nèi)部的花括號,只保留最外面的一對花括號,例如:

arr[2][3]={1,2,3,4,5,6};

C、二維數(shù)組作形參

在傳統(tǒng)的C向函數(shù)傳遞多維數(shù)組的方法是把數(shù)組名(也就是地址)傳遞給相應類型的指針變量。指針聲明需要指定各維的大小(注意第一個方括號是空的,不需要明確指出大小);第一個參量的維數(shù)大小通常作為第二個參數(shù)來傳遞,例如:

void display (int arr[][12], int rows);等價于

void display (int (* arr)[4], int rows);

請注意下面的聲明是不正確的:

void display (int arr[][], int rows); //錯誤的聲明

編譯器會把數(shù)組符號轉(zhuǎn)換成指針符號,如果是空括號,這樣轉(zhuǎn)換的時候會不知道ar所指向?qū)ο蟮臄?shù)據(jù)大小,編譯器將不能正確處理。

也可以如下這樣在另一對括號填寫大小,但編譯器將忽略:

void display (int arr[8][12], int rows);

一般聲明N維數(shù)組的指針時,除了最左邊的方括號可以留空外,其他都需要填寫數(shù)據(jù),這是因為首方括號表示這是一個指針,而其他方括號描述的是所指向?qū)ο蟮臄?shù)據(jù)類型,例如:

void display (int arr[][5][8][9], int rows); 等價于

void display (int (*arr)[5][8][9], int rows);

8、變長數(shù)組(VLA)

int n = 4,m = 5;

int arr[n][m];//一個變長數(shù)組?

變長數(shù)組有一些限制:

變長數(shù)組必須是自動存儲類的,這意味著它們必須在函數(shù)內(nèi)部或作為函數(shù)參量聲明,而且聲明時不可以進行初始化。變長數(shù)組中的“變”并不表示在創(chuàng)建數(shù)組后,可以修改其大小。變長數(shù)組的大小在創(chuàng)建后就是保持不變的?!白儭钡囊馑际钦f起維大小可以用變量來指定。

聲明一個二維變長數(shù)組參數(shù)的函數(shù):

int sum (int row, int cols, int arr[row][cols]);

請注意錢兩個參量(row和cols)用作數(shù)組參量arr的維數(shù)。因為arr的聲明中使用了row和cols,所以在參量列表中,它們兩個的聲明需要早于arr。因此,下面的原型是錯誤的:

int sum (int arr[row][cols], int row, int cols); //順序不正確

也可以省略函數(shù)原型中的名稱,但是如果省略名稱,則需要使用星號來代替省略的維數(shù):

int sum (int, int, int arr[*][*]); ?//省略了維數(shù)參量的名稱

二、指針

1、指針介紹

一般來講,指針是一個其數(shù)值為地址的變量指針變量的數(shù)值表示的是地址,例如:

int n = 5;

int *ptr = &n; ??

*ptr = 5; ? ? ? ?

這時ptr的值是n的地址,*ptr是存儲在地址&n中的數(shù)值。

一元運算符&:

假設p是一個變量的名字,那么&p就是該變量的地址,%p是輸出地址的占位符,通常以十六進制形式顯示值,例如:

printf ("%d, %p\n", p, &p);

說明:如果你的編譯器不支持%p,可以使用%u或%lu作為代替。

間接運算符*:

當后面跟一個指針名或地址時,* 給出存儲區(qū)在被指向地址中的數(shù)值.

在 32 位系統(tǒng)下,不管什么樣的指針類型,其大小都為 4byte??梢詼y試一下 sizeof( void *)。


2、指針聲明

int *pi;/*pi是指向一個整數(shù)變量的指針*/

char *pc;/*pc是指向一個字符變量的指針*/

float *pf;/*pf是指向一個浮點數(shù)變量的指針*/

指針聲明,需要說明指針所指向的變量的類型,星號(*)表明該變量為一指針。星號(*)和指針之間的空格式可選的,通常程序員在聲明中使用空格,而在指向變量時將其省略。

切記:當創(chuàng)建一個指針時,系統(tǒng)只會分配了用來存儲指針本身的內(nèi)存空間,并不會分配用來存儲數(shù)據(jù)的內(nèi)存空間。因此在使用指針之前,必須給它賦予一個已分配的內(nèi)存地址。

可以將一個已存在的變量地址賦給指針,或者使用函數(shù)malloc()來首先分配內(nèi)存,例如:

int arr[5];

int *ptr = arr; ? ? 或者

int *ptr = (*int)malloc (5*sizeof (int));

擴展部分:

int* b, c, d;

人們很自然地以為這條語句把所有三個變量聲明為指向整型的指針,但事實上并非如此。我們被它的形式愚弄了。星號實際上是表達式 *b 的一部分,只對這個標識符有用。b 是一個指針,但其余兩個變量只是普通的整型。要聲明三個指針,正確的語句如下:

int *b, *c, *d;


3、指針和數(shù)組

A、數(shù)組標記實際上是一種變相的使用指針的形式,比如,數(shù)組名同時也是該數(shù)組首元素的地址。

int arr[5];

arr = &arr[0]; //數(shù)組名是該數(shù)組首元素的地址。

int *p = arr; ? ?//將數(shù)組首元素地址,賦值給指針

兩者都是常量,因為在程序的運行過程中它們保持不變??梢詫⑺鼈冑x值給指針變量的值,然后進行修改。

B、用指針標識數(shù)組的每一個元素,可以得到每一個元素的數(shù)值,對指針加1,等久對指針的值加上它指向的對象的字節(jié)大小,例如:

int n[10];

n + 2 = &n[2]; ? ??/*相同的地址*/

*(n + 2) = n[2]; ? ?/*相同的值*/

注意區(qū)分 *(n + 2)和*n + 2。間接運算符(*)的優(yōu)先級高于+,因此后者等價于 *(n) + 2

*(n + 2) ? ?/*n的第3個元素的值*/

*n +2 ? ? ? /*第1個元素的值和2相加*/

4、函數(shù)、數(shù)組和指針

int sum (int *arr, int n); ??

int sum (int arr[], int n);

這里第一個參數(shù)把數(shù)組地址和數(shù)組類型的信息傳遞給函數(shù),第二個參數(shù)把數(shù)組中的鋨元素個數(shù)傳遞給函數(shù)。此外,關于函數(shù)參量還需要注意,在函數(shù)原型或函數(shù)定義的場合中(并且也只有在這兩種場合),可以用int *arr代替int arr[]。

無論在任何情況下,形式int* arr都表示arr是指向int的指針。形式int arr[]也可以表示arr是指向int的指針,但只是在聲明形式參量時才可以這樣使用。使用第二種形式說明了arr不僅指向一個int數(shù)值,而且它指向的這個int是一個數(shù)組中的元素。

5、指針操作

A、賦值,可以把一個地址賦給指針。通常使用數(shù)組名或地址運算符&來進行地址賦值。注意地址應該和指針類型兼容。

B、求值或取值,運算符*可取出指針指向地址中存儲的數(shù)值。

C、取指針地址,指針變量同其他變量一樣具有地址和數(shù)值,使用運算符&可以得到存儲指針本身的地址。

D、將一個整數(shù)加給指針,可以使用+運算符來把一個整數(shù)加給一個指針,或者把一個指針加給一個正數(shù)。如果相加的結(jié)果超出了初始指針指向的數(shù)組的范圍,那么這個結(jié)果不確定。

E、增加指針的值,可以通過一般的加法或增量運算符來增加一個指針的值。

F、從指針中減去一個整數(shù),可以使用-運算符來從指針中減去一個整數(shù)。

G、減小指針的值,指針做減量運算。

H、求差值,可以求出兩個指針間的差值。

I、比較,可以使用關系運算符來比較兩個指針的值,前提是兩個指針具有相同的類型。

#include <stdio.h> int main (void) {int arr[5] = {100, 200, 300, 400, 500};int *ptr1, *ptr2, *ptr3;ptr1 = arr;ptr2 = &arr[2];printf ("ptr1 = %p, *ptr1 = %d, &ptr1 = %p\n", ptr1, *ptr1, &ptr1);ptr3 = ptr1 +4;printf ("ptr1 +4 = %p, *(ptr1 + 3) = %d\n", ptr1 + 4, *(ptr1 + 3));ptr1++;printf ("ptr1 = %p, *ptr1 = %d, &ptr1 = %p\n", ptr1, *ptr1, &ptr1);ptr2--;printf ("ptr2 = %p, *ptr2 = %d, &ptr2 = %p\n", ptr2, *ptr2, &ptr2);--ptr1;++ptr2;printf ("ptr1 = %p, ptr2 = %p\n", ptr1, ptr2);printf ("ptr2 = %p, ptr1 = %p, ptr2 - ptr1 = %d\n", ptr2, ptr1, ptr2 - ptr1);printf ("ptr3 = %p, ptr3 - 2 = %p\n", ptr3, ptr3 - 2);return 0; } 輸出結(jié)果: ptr1 = 0xbf89c5f0, *ptr1 = 100, &ptr1 = 0xbf89c604 ptr1 +4 = 0xbf89c600, *(ptr1 + 3) = 400 ptr1 = 0xbf89c5f4, *ptr1 = 200, &ptr1 = 0xbf89c604 ptr2 = 0xbf89c5f4, *ptr2 = 200, &ptr2 = 0xbf89c608 ptr1 = 0xbf89c5f0, ptr2 = 0xbf89c5f8 ptr2 = 0xbf89c5f8, ptr1 = 0xbf89c5f0, ptr2 - ptr1 = 2 ptr3 = 0xbf89c600, ptr3 - 2 = 0xbf89c5f8

一些合法和非法的語句:

int arr[5];

int *ptr1, ptr2;

合法: ? ? ? ? ? ? ? ? ? ? 非法:

ptr++; ? ? ? ? ? ? ? ? ? ? arr++;

ptr2 = ptr1 + 2; ? ? ? ptr2 = ptr2 + ptr1;

ptr2 = arr + 1; ? ? ? ? ptr2 = arr * ptr1;

說明只有指針變量,才可以使用ptr++這樣的表達式。

6、const修飾指針、數(shù)組

const定義的變量具有只讀性,const修飾的只讀變量必須在定義的時候初始化。

A、修飾數(shù)組

定義或說明一個只讀數(shù)組可采用如下格式:
int const a[5]={1, 2, 3, 4, 5};或
const int a[5]={1, 2, 3, 4, 5};

B、修飾指針

這里給出一個記憶和理解的方法:
先忽略類型名(編譯器解析的時候也是忽略類型名),我們看 const 離哪個近。“近水樓先得月”,離誰近就修飾誰。

int arr[5];
const int *p = arr; //const 修飾*p,p 是指針,可變; *p 是指針指向的對象,不可變。
int const *p = arr; //const 修飾*p,p 是指針, 可變;*p 是指針指向的對象,不可變。
int *const p = arr; //const 修飾 p, p 是指針,不可變; p 指向的對象可變。
const int *const p= arr; //前一個 const 修飾*p,后一個 const 修飾 p,指針 p 和 p 指向的對象都不可變。

7、指針數(shù)組和數(shù)組指針

指針數(shù)組:首先它是一個數(shù)組,數(shù)組的元素都是指針,例如:int *ptr1[10];

數(shù)組指針:首先它是一個指針,它指向一個數(shù)組,例如:int (*ptr2)[10];

這里需要明白一個符號之間優(yōu)先級的問題,"[ ]"的優(yōu)先級比"*"要高。p1 先與“ []”結(jié)合,構成一個數(shù)組的定義,數(shù)組名為 p1, int *修飾的是數(shù)組的內(nèi)容,即數(shù)組的每個元素。那現(xiàn)在我們清楚,這是一個數(shù)組,其包含 10 個指向 int 類型數(shù)據(jù)的指針,即指針數(shù)組。

至于 p2 就更好理解了,在這里"( )"的優(yōu)先級比"[ ]"高,"*"號和 p2 構成一個指針的定義,指針變量名為 p2, int 修飾的是數(shù)組的內(nèi)容,即數(shù)組的每個元素。數(shù)組在這里并沒有名字,是個匿名數(shù)組。那現(xiàn)在我們清楚 p2 是一個指
針,它指向一個包含 10 個 int 類型數(shù)據(jù)的數(shù)組,即數(shù)組指針。


三、指針和數(shù)組的區(qū)別

指針就是指針,指針變量在 32 位系統(tǒng)下,永遠占 4 個 byte,其值為某一個內(nèi)存的地址。指針可以指向任何地方,但是不是任何地方你都能通過這個指針變量訪問到。

數(shù)組就是數(shù)組,其大小與元素的類型和個數(shù)有關。定義數(shù)組時必須指定其元素的類型和個數(shù)。數(shù)組可以存任何類型的數(shù)據(jù),但不能存函數(shù)。

他們之間沒有任何關系!只是他們經(jīng)常穿著相似的衣服來逗你玩罷了。


總結(jié)

以上是生活随笔為你收集整理的C语言再学习 -- 数组和指针的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。