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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

C语言入坑指南-数组之谜

發布時間:2023/12/20 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言入坑指南-数组之谜 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

在C語言中,數組和指針似乎總是“曖昧不清”,有時候很容易把它們混淆。本文就來理一理數組和指針之間到底有哪些異同。

數組回顧

在分析之前,我們不妨回顧一下數組的知識。數組是可以存儲一個固定大小的相同類型元素的順序集合。為了便于我們說明,假設有以下數組聲明:

int?a[5]; char?b[]?=?"hello";
  • 數組大小必須在編譯期就作為一個常數確定下來。

  • 但C99中引入了變長數組,允許數組的維度是表達式 ,但在數組分配內存時,其表達式的值可以被求出。

  • 數組下標運算實際上都是通過指針進行的,也就是說a[4]與*(a+4)是等價的,甚至你會發現和4[a]也是一樣的。

  • 數組名一般代表了指向該數組下標為0的元素的指針,并且printf("%s\n",hello)與printf("%s\n",&hello[0])等效。

數組和指針不相等

考慮下面的聲明:

int?c[4];//假設int占4字節 int?*d;

對于上面的聲明,編譯器會給c預留內存空間4*4字節,并且數組名代表著指向數組第一個元素的指針。但對于d,卻只為指針本身保留了內存空間。

c[3];????????//合法 *(c+3);??????//合法 *d;??????????//不合法,d指向了內存中不確定位置 c++;????????//不合法,一維數組名是指針常量,常量不能被修改掉 d++;????????//可通過編譯

另外,下面的兩種情況也是不一樣的:

char?c[]?=?"hello"; char?*d?=?"hello";

前者對字符數組a進行了初始化,后者將d指向了字符串常量。字符串常量存儲在只讀區,因此有下面的操作:

?c[0]?=?'H';??//合法,可修改數組內容*d?=?'H';????//不合法,字符串常量內容不可更改d[0]?=?'H'???//不合法

數組名的含義

絕大多數情況,數組名都代表著指向該數組中下標為0的元素的指針,但是有例外:

int?e[4];//假設int為4字節 sizeof(e);

上面的sizeof(e)的值并非4或8(指針占用空間),而是4*4 = 16。也就是說,當數組名被用作運算符sizeof的參數時,它的計算結果是整個數組的大小,而非第一個元素的指針大小。

int?temp[5]; char?*p?=?&temp; char?*q?=?temp;

在這里,p和q的值是一樣的,含義卻不一樣,前者是指向數組的指針,而后者是指向該數組中下標為0的元素的指針。因此p+1指向了temp的末尾,而q+1指向了temp的第2個元素。

數組長度計算

如何計算數組長度?考慮下面的代碼:

int?f[]?=?{1,2,3,4,5,6}; int?*g?=?f; size_t?len_f?=?sizeof(f)/sizeof(int)//正確計算方法 size_t?len_g?=?sizeof(g)/sizeof(int)

上面的len_f和len_g的值相等嗎?顯然并不相等。事實上,只有len_f得到了數組f的長度,而len_g的值并沒有任何實際意義。

不能作為參數的數組

所謂的數組不能作為參數,并不是指聲明的數組不能作為參數傳遞,而是指當數組名作為參數時,數組名會被轉換為指向該數組下標為0的元素的指針。

size_t?arrayLen(const?int?*arr); size_t?arrayLen(const?int?arr[]);

我們來看一個例子,說明數組作為參數的情況:

#include?<stdio.h> int?arraySum(const?int?arr[]) {unsigned?int?loop?=?0;/*循環前計算好長度,提高性能*/unsigned?int?len?=?sizeof(arr)/sizeof(int);int?sum?=?0;if(NULL?==?arr){return?0;}for(loop?=?0;?loop?<?len;?loop++){sum+=arr[loop];}return?sum;??? } int?main(void) {int?a[]?=?{1,2,3,4,5,6};int?sum?=?arraySum(a);printf("arr?sum?is?%d",sum);return?0; }

我們運行上面的程序,發現最終結果并不是我們預期的21,而是3。問題在于,a作為參數傳入到arraySum中時,它是作為指針的,那么在函數內部計算sizeof(arr)自然只是得到了指針占用的內存大小。對于64位程序,這個大小是8,那么len的值為2,最終只計算了兩個元素的和。

思考:該如何修改上面的程序才能得到正確的結果?

總結

我們來總結一下前面的核心內容:

  • 數組下標運算實際上都是通過指針進行的。

  • 數組名代表著指向該數組中下標為0的元素的指針,但有例外:sizeof(數組名)返回整個數組的大小,而非指針大小;&數組名返回一個指向數組的指針,而不是指向該數組中下標為0的元素的指針的指針。

  • 數組名作為參數時,數組名會被轉換成指向該數組下標為0的元素的指針。

  • 指針操作可能比下標操作效率高,但可維護性卻不一定有下標操作好。

  • 數組和指針不相等。

思考

下面的代碼輸出結果是什么?

#include<stdio.h> int?main(void) {int?a[5]?=?{1,2,3,4,5};int?*p?=?(int*)(&a+1);printf("%d,%d",*(a+1),*(p-1));return?0; }

掃碼或長按關注

回復「?加群?」進入技術群聊

總結

以上是生活随笔為你收集整理的C语言入坑指南-数组之谜的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。