1. 程式人生 > >C語言中如何求任意一個int型陣列的長度?

C語言中如何求任意一個int型陣列的長度?

問題即:int length(int ar[]);只給出陣列首地址,返回該陣列的長度
C語言中對陣列的操作不太靈活,而陣列操作又是不可或缺的

計算記憶體容量
用運算子sizeof可以計算出陣列的容量(位元組數)。示例7-3-3(a)中,sizeof(a)的值是12(注意別忘了’/0’)。指標p指向a,但是sizeof(p)的值卻是4。這是因為sizeof(p)得到的是一個指標變數的位元組數,相當於sizeof(char*),而不是p所指的記憶體容量。C++/C語言沒有辦法知道指標所指的記憶體容量,除非在申請記憶體時記住它。

注意當陣列作為函式的引數進行傳遞時,該陣列自動退化為同類型的指標。示例7-3-3(b)中,不論陣列a的容量是多少,sizeof(a)始終等於sizeof(char *)。

char a[] = "hello world";
char *p  = a;
cout<< sizeof(a) << endl;// 12位元組
cout<< sizeof(p) << endl;// 4位元組
示例7-3-3(a) 計算陣列和指標的記憶體容量

void Func(char a[100])
{
cout<< sizeof(a) << endl;// 4位元組而不是100位元組
}
示例7-3-3(b) 陣列退化為指標

只能把陣列的長度作為引數傳遞。

當然也可以這樣:
#include "stdio.h"

typedef struct array_box
{
    int array[10];
}ARRAY_BOX;

void getData(ARRAY_BOX * arrayBox_p)
{
    int count = sizeof(arrayBox_p->array) / sizeof(int);
    int i;
    for (i = 0; i < count; i++)
    {
        arrayBox_p->array[i] = i;
    }
}

main()
{
    ARRAY_BOX arrayBox;
    getData(&arrayBox);
}

做一個只有一個型別為陣列的元素的結構體,相當於把陣列用一個box包起來,佔用的記憶體空間相同,但是可以達到樓主想要得效果。

至於想要知道陣列實際使用長度,那真是沒有任何辦法了,只有自己數吧~~

1 C風格陣列在定義時可以通過sizeof計算出大小,如:

#define AR_SIZE( a ) sizeof( a ) / sizeof( a[0] )

char str[] = "Some thing for test";
int a[] = { 1, 3, 4 };
int b[20];

AR_SIZE( str );  //20
AR_SIZE( a );  //3
AR_SIZE( b );  //20

注意,sizeof是編譯器間靜態求值的。他必須知道物件的準確型別。


2 陣列作為函式引數,作用類似指標。 函式只傳遞一個4位元組的地址,而沒有其大小資訊。

樓上 JustNewBie(懶惰+驕傲+不耐心!) 做法是錯誤的。

int length(int ar[])
{
  sizeof ar; // 永遠是4(當然,在16位編譯器下是2 )
}

3 C99支援動態陣列,你可以查查資料,似乎有支援自動指定大小——但是目前支援C99的編譯器很少,我沒有試過。

不可能有辦法的。
當你定義一個數組的時候:
int a[] = {1, 2, 3};  // 實際上被編譯為 int a[3] = {1,2,3}

陣列名代表的是陣列的地址。注意 —— 你絕對沒有辦法通過陣列名動態獲得陣列的大小。當你丟失a的長度資訊的時候,你永遠不可能知道他的長度。

那麼 sizeof 是怎麼回事呢?他不是通過 a 的名字獲得 a的大小了麼? —— 大錯特錯!

關鍵字 sizeof 產生的是一個編譯期常量(注1) 他的運作方式是這樣的:

當你寫:
sizeof a
實質是:
sizeof ( a的型別 )

而a的型別是什麼呢?編譯器察看 a的定義發現, 是 int [3]
就是說,這裡 sizeof a 實質是:
sizeof ( int[3] )
完全等同於常量 12 (假定int為4位元組)。


考慮一個函式
void func( int a[] ); 
// 寫成 int a[3] 也不會有本質區別——也許你該試試寫成 int (&a) [3] ?

C++規定,陣列作為形參的時候,a代表陣列首地址。
他的底層意義是: a 退化為了一個4位元組的指標,沒有任何變量表示陣列的大小會“自動”被傳遞進來。

我們看看這個時候 sizeof a是什麼:
sizeof( 函式形參的a[] )  = sizeof( int* const ) = 4  // 當然a[]不是合法的C++型別

仍然不服氣?好——我們反問一個問題:若你是C /C++的設計者, 你怎麼在相容原有設計的基礎上讓void func( int a[] )同時傳遞地址和大小?

首先,a是一個變數,而且類似陣列。他必須是一個地址,否則你不知道如何索引元素。
他怎麼再帶上一個變量表示他的大小呢?

擴充 sizeof (a) 的能力?

sizeof a 必須產生程式碼——不管是常量還是什麼。 要讓他在執行時決定 a的值, a就必須帶上他的大小資訊。

1 你必須修改C標準,讓C支援“兩種”陣列。一種是定義處的陣列,他分配大片連續記憶體,和原來的C標準相同。

2 另一種是作為引數傳遞陣列。 你必須傳遞地址和陣列大小;這個陣列實際上是一個8位元組的結構{ 地址; 大小}(事實上可能更加複雜,考慮多緯陣列如何實現? )

3 系統必須根據兩種不同陣列分別實現其 []、* 、&等。 原有的陣列根據其首地址偏移(這是個常量)和下標定址; 而引數陣列則首先取“地址”內容(這是個變數),然後根據這個地址定址....

厄... 再考慮多維陣列——聽起來這不是一整套vector模型麼?

-----------------------------------------------
注1: 對於C99支援的 flexible array ,其 sizeof 運算是執行時求值