天天看點

如何确定C語言中數組的大小?

如何确定C語言中數組的大小?

也就是說,數組可以容納多少個元素?

#1樓

如果您要處理未作為參數接收的數組,則

sizeof

方法是正确的方法。 作為參數發送給函數的數組被視為指針,是以

sizeof

将傳回指針的大小,而不是數組的大小。

是以,内部函數無法使用此方法。 相反,請始終傳遞一個附加參數

size_t size

訓示數組中元素的數量。

測試:

#include <stdio.h>
#include <stdlib.h>

void printSizeOf(int intArray[]);
void printLength(int intArray[]);

int main(int argc, char* argv[])
{
    int array[] = { 0, 1, 2, 3, 4, 5, 6 };

    printf("sizeof of array: %d\n", (int) sizeof(array));
    printSizeOf(array);

    printf("Length of array: %d\n", (int)( sizeof(array) / sizeof(array[0]) ));
    printLength(array);
}

void printSizeOf(int intArray[])
{
    printf("sizeof of parameter: %d\n", (int) sizeof(intArray));
}

void printLength(int intArray[])
{
    printf("Length of parameter: %d\n", (int)( sizeof(intArray) / sizeof(intArray[0]) ));
}
           

輸出(在64位Linux作業系統中):

sizeof of array: 28
sizeof of parameter: 8
Length of array: 7
Length of parameter: 2
           

輸出(在32位Windows作業系統中):

sizeof of array: 28
sizeof of parameter: 4
Length of array: 7
Length of parameter: 1
           

#2樓

您可以使用

&

運算符。 這是源代碼:

#include<stdio.h>
#include<stdlib.h>
int main(){

    int a[10];

    int *p; 

    printf("%p\n", (void *)a); 
    printf("%p\n", (void *)(&a+1));
    printf("---- diff----\n");
    printf("%zu\n", sizeof(a[0]));
    printf("The size of array a is %zu\n", ((char *)(&a+1)-(char *)a)/(sizeof(a[0])));


    return 0;
};
           

這是示例輸出

1549216672
1549216712
---- diff----
4
The size of array a is 10
           

#3樓

如果您真的想通過數組來傳遞資料,那麼我建議您實作一個結構,以存儲指向您想要的數組類型的指針和一個表示數組大小的整數。 然後,您可以将其傳遞給函數。 隻需将數組變量值(指向第一個元素的指針)配置設定給該指針。 然後,您可以轉到

Array.arr[i]

以擷取第i個元素,并使用

Array.size

來擷取數組中的元素數。

我為您提供了一些代碼。 它不是很有用,但您可以使用更多功能進行擴充。 不過,老實說,如果您要這些,就應該停止使用C,并使用内置這些功能的另一種語言。

/* Absolutely no one should use this...
   By the time you're done implementing it you'll wish you just passed around
   an array and size to your functions */
/* This is a static implementation. You can get a dynamic implementation and 
   cut out the array in main by using the stdlib memory allocation methods,
   but it will work much slower since it will store your array on the heap */

#include <stdio.h>
#include <string.h>
/*
#include "MyTypeArray.h"
*/
/* MyTypeArray.h 
#ifndef MYTYPE_ARRAY
#define MYTYPE_ARRAY
*/
typedef struct MyType
{
   int age;
   char name[20];
} MyType;
typedef struct MyTypeArray
{
   int size;
   MyType *arr;
} MyTypeArray;

MyType new_MyType(int age, char *name);
MyTypeArray newMyTypeArray(int size, MyType *first);
/*
#endif
End MyTypeArray.h */

/* MyTypeArray.c */
MyType new_MyType(int age, char *name)
{
   MyType d;
   d.age = age;
   strcpy(d.name, name);
   return d;
}

MyTypeArray new_MyTypeArray(int size, MyType *first)
{
   MyTypeArray d;
   d.size = size;
   d.arr = first;
   return d;
}
/* End MyTypeArray.c */


void print_MyType_names(MyTypeArray d)
{
   int i;
   for (i = 0; i < d.size; i++)
   {
      printf("Name: %s, Age: %d\n", d.arr[i].name, d.arr[i].age);
   }
}

int main()
{
   /* First create an array on the stack to store our elements in.
      Note we could create an empty array with a size instead and
      set the elements later. */
   MyType arr[] = {new_MyType(10, "Sam"), new_MyType(3, "Baxter")};
   /* Now create a "MyTypeArray" which will use the array we just
      created internally. Really it will just store the value of the pointer
      "arr". Here we are manually setting the size. You can use the sizeof
      trick here instead if you're sure it will work with your compiler. */
   MyTypeArray array = new_MyTypeArray(2, arr);
   /* MyTypeArray array = new_MyTypeArray(sizeof(arr)/sizeof(arr[0]), arr); */
   print_MyType_names(array);
   return 0;
}
           

#4樓

sizeof技巧是我所知道的最好方法,在括号的使用上有一個很小但(對我來說,這是一個主要的挑戰)。

維基百科條目清楚地表明,C的

sizeof

不是函數。 它是一個運算符 。 是以,除非參數是類型名稱,否則不需要在參數周圍加上括号。 這很容易記住,因為它使參數看起來像強制轉換表達式,該表達式也使用括号。

是以:如果您具有以下條件:

int myArray[10];
           

您可以使用以下代碼找到元素數量:

size_t n = sizeof myArray / sizeof *myArray;
           

對我來說,這比帶括号的替代方法容易讀得多。 我也贊成在該部門的右側使用星号,因為它比索引更簡潔。

當然,這也都是編譯時,是以無需擔心劃分會影響程式的性能。 是以,請盡可能使用此表格。

最好是在有一個實際對象時在一個對象上使用sizeof,而不是在一個類型上,因為這樣一來,您就不必擔心會出錯并指出錯誤的類型。

例如,假設您有一個函數,例如通過網絡将某些資料作為位元組流輸出。 讓我們調用函數

send()

,并使其以指向要發送的對象的指針以及對象中的位元組數作為參數。 是以,原型變為:

void send(const void *object, size_t size);
           

然後,您需要發送一個整數,是以您将其編碼如下:

int foo = 4711;
send(&foo, sizeof (int));
           

現在,您通過在兩個位置指定

foo

的類型,引入了一種微妙的腳步射擊方法。 如果一個更改但另一個沒有更改,則代碼将中斷。 是以,請始終這樣做:

send(&foo, sizeof foo);
           

現在,您已受到保護。 當然,您可以重複變量的名稱,但是如果更改它,則很有可能以編譯器可以檢測的方式破壞該變量。

#5樓

int size = (&arr)[1] - arr;
           

檢視此連結以擷取解釋

#6樓

如果知道數組的資料類型,則可以使用類似以下内容的方法:

int arr[] = {23, 12, 423, 43, 21, 43, 65, 76, 22};

int noofele = sizeof(arr)/sizeof(int);
           

或者,如果您不知道數組的資料類型,則可以使用類似以下内容的方法:

noofele = sizeof(arr)/sizeof(arr[0]);
           

注意:隻有在運作時未定義數組(例如malloc)并且未在函數中傳遞數組時,此功能才有效。 在這兩種情況下,

arr

(數組名稱)都是一個指針。

#7樓

每個人都使用的宏

ARRAYELEMENTCOUNT(x)

評估不正确 。 實際上,這隻是一個敏感的問題,因為您不能擁有導緻“數組”類型的表達式。

/* Compile as: CL /P "macro.c" */
# define ARRAYELEMENTCOUNT(x) (sizeof (x) / sizeof (x[0]))

ARRAYELEMENTCOUNT(p + 1);
           

實際評估為:

(sizeof (p + 1) / sizeof (p + 1[0]));
           

鑒于

/* Compile as: CL /P "macro.c" */
# define ARRAYELEMENTCOUNT(x) (sizeof (x) / sizeof (x)[0])

ARRAYELEMENTCOUNT(p + 1);
           

正确評估為:

(sizeof (p + 1) / sizeof (p + 1)[0]);
           

确實,這與數組的大小沒有太大關系。 我剛剛注意到了很多錯誤,因為他們沒有真正觀察C預處理器的工作方式。 您總是包裝宏參數,而不涉及表達式。

這是對的; 我的例子很糟糕。 但這實際上正是應該發生的情況。 如前所述,

p + 1

最終将成為指針類型,并使整個宏無效(就像您試圖在具有指針參數的函數中使用該宏一樣)。

歸根結底,在這種特定情況下,錯誤并不重要(是以,我隻是在浪費每個人的時間;煩死了!),因為您沒有帶有“數組”類型的表達式。 但實際上,我認為關于預處理程式評估的要點很微妙。

#8樓

C中的數組大小:

int a[10];
size_t size_of_array = sizeof(a);      // Size of array a
int n = sizeof (a) / sizeof (a[0]);    // Number of elements in array a
size_t size_of_element = sizeof(a[0]); // Size of each element in array a                                          
                                       // Size of each element = size of type
           

#9樓

最好的方法是例如在以下結構中儲存此資訊:

typedef struct {
     int *array;
     int elements;
} list_s;
           

實作所有必要的功能,例如建立,銷毀,檢查相等性以及您需要的所有其他功能。 作為參數傳遞更容易。

#10樓

執行摘要:

int a[17];
size_t n = sizeof(a)/sizeof(a[0]);
           

完整答案:

要确定以位元組為機關的數組大小,可以使用

sizeof

運算符:

int a[17];
size_t n = sizeof(a);
           

在我的計算機上,整數是4個位元組長,是以n是68。

為了确定數組中元素的數量,我們可以将數組的總大小除以數組元素的大小。 您可以使用以下類型來執行此操作:

int a[17];
size_t n = sizeof(a) / sizeof(int);
           

并得到正确的答案(68/4 = 17),但如果類型

a

改你将有一個讨厭的錯誤,如果你忘了改變

sizeof(int)

為好。

是以,首選除數是

sizeof(a[0])

,即數組的第零個元素的大小。

int a[17];
size_t n = sizeof(a) / sizeof(a[0]);
           

另一個優點是,您現在可以輕松地在宏中參數化數組名稱并獲得:

#define NELEMS(x)  (sizeof(x) / sizeof((x)[0]))

int a[17];
size_t n = NELEMS(a);
           

#11樓

sizeof(array) / sizeof(array[0])
           

#12樓

值得注意的是,

sizeof

在處理已衰減為指針的數組值時無濟于事:即使它指向數組的開頭,但對于編譯器,它與指向該數組中單個元素的指針相同數組。 指針不會“記住”用于初始化數組的其他任何資訊。

int a[10];
int* p = a;

assert(sizeof(a) / sizeof(a[0]) == 10);
assert(sizeof(p) == sizeof(int*));
assert(sizeof(*p) == sizeof(int));
           

#13樓

#define SIZE_OF_ARRAY(_array) (sizeof(_array) / sizeof(_array[0]))
           

#14樓

您可以使用sizeof運算符,但不适用于函數,因為它将擷取指針的引用,您可以執行以下操作找到數組的長度:

len = sizeof(arr)/sizeof(arr[0])
           

最初在這裡找到的代碼: C程式查找數組中元素的數量

#15樓

int a[10];
int size = (*(&a+1)-a) ;
           

有關更多詳細資訊,請參見此處和此處 。

#16樓

函數

sizeof

傳回數組在記憶體中使用的位元組數。 如果要計算數組中元素的數量,則應将該數字除以數組的

sizeof

變量類型。 假設

int array[10];

,如果您計算機中的變量類型整數為32位(或4位元組),為了擷取數組的大小,您應該執行以下操作:

int array[10];
int sizeOfArray = sizeof(array)/sizeof(int);
           

#17樓

最簡單的答案:

#include <stdio.h>

int main(void) {

    int a[] = {2,3,4,5,4,5,6,78,9,91,435,4,5,76,7,34};//for Example only
    int size;

    size = sizeof(a)/sizeof(a[0]);//Method

    printf ("size = %d",size);
    return 0;
}
           

#18樓

我建議不要使用

sizeof

(即使可以使用它)來擷取數組的兩個不同大小中的任何一個,無論是元素數還是位元組數,這是我在這裡顯示的最後兩種情況。 對于這兩種大小,可以使用下面顯示的宏使其更安全。 原因是使代碼的意圖明顯地展現給維護者,乍一看,

sizeof(ptr)

sizeof(arr)

有所不同(這種寫法并不明顯),是以對于每個閱讀代碼的人來說,錯誤都是顯而易見的。

有關此主題的重要錯誤: https : //lkml.org/lkml/2015/9/3/428

我不同意Linus提供的解決方案,即永遠不要将數組表示法用作函數的參數。

我喜歡将數組表示法用作将指針用作數組的文檔。 但是,這意味着需要采用一種萬無一失的解決方案,以便不可能編寫錯誤的代碼。

在數組中,我們可能需要知道三種大小:

  • 數組元素的大小
  • 數組中的元素數
  • 數組在記憶體中使用的位元組大小

數組元素的大小

第一個非常簡單,我們處理數組還是指針都沒有關系,因為它是通過相同的方式完成的。

用法示例:

void foo(ptrdiff_t nmemb, int arr[static nmemb])
{
        qsort(arr, nmemb, sizeof(arr[0]), cmp);
}
           

qsort()

需要此值作為其第三個參數。

對于其他兩個大小(這是問題的主題),我們要確定正在處理數組,如果沒有處理,則中斷編譯,因為如果處理指針,則會得到錯誤的值。 當編譯中斷時,我們将能夠輕松地看到,我們并沒有在處理數組,而是在使用指針,并且我們隻需要使用存儲變量大小的變量或宏編寫代碼即可。指針後面的數組。

數組中的元素數

這是最常見的一個,許多答案為您提供了典型的宏ARRAY_SIZE:

#define ARRAY_SIZE(arr)     (sizeof(arr) / sizeof((arr)[0]))
           

鑒于ARRAY_SIZE的結果通常與

ptrdiff_t

類型的帶符号變量一起使用,最好定義此宏的帶符号變量:

#define ARRAY_SSIZE(arr)    ((ptrdiff_t)ARRAY_SIZE(arr))
           

成員數超過

PTRDIFF_MAX

數組将為此宏的簽名版本提供無效值,但是從讀取C17 :: 6.5.6.9來看,類似的數組已經開始發揮作用。 在這些情況下,僅應使用

ARRAY_SIZE

size_t

當您将此宏應用于指針時,最新版本的編譯器(例如GCC 8)會向您發出警告,是以它是安全的(還有其他方法可確定對較舊的編譯器安全)。

它通過将整個數組的位元組大小除以每個元素的大小來工作。

用法示例:

void foo(ptrdiff_t nmemb)
{
        char buf[nmemb];

        fgets(buf, ARRAY_SIZE(buf), stdin);
}

void bar(ptrdiff_t nmemb)
{
        int arr[nmemb];

        for (ptrdiff_t i = 0; i < ARRAY_SSIZE(arr); i++)
                arr[i] = i;
}
           

如果此函數未使用數組,而是将其用作參數,則先前的代碼将無法編譯,是以将不可能有錯誤(假設使用的是最新的編譯器版本,或使用了其他技巧) ,我們需要将宏調用替換為以下值:

void foo(ptrdiff_t nmemb, char buf[nmemb])
{

        fgets(buf, nmemb, stdin);
}

void bar(ptrdiff_t nmemb, int arr[nmemb])
{

        for (ptrdiff_t i = 0; i < nmemb; i++)
                arr[i] = i;
}
           

數組在記憶體中使用的位元組大小

通常将

ARRAY_SIZE

用作前一種情況的解決方案,但這種情況很少被安全地編寫,可能是因為它不太常見。

擷取此值的常用方法是使用

sizeof(arr)

。 問題:與上一個相同; 如果您有一個指針而不是一個數組,您的程式将失敗。

該問題的解決方案涉及使用與以前相同的宏,我們知道這是安全的(如果将其應用于指針,它将破壞編譯):

#define ARRAY_BYTES(arr)        (sizeof((arr)[0]) * ARRAY_SIZE(arr))
           

它的工作原理非常簡單:它消除了

ARRAY_SIZE

所做的除法

ARRAY_SIZE

,是以,在進行數學取消後,您最終隻得到一個

sizeof(arr)

,但又增加了

ARRAY_SIZE

構造的安全性。

用法示例:

void foo(ptrdiff_t nmemb)
{
        int arr[nmemb];

        memset(arr, 0, ARRAY_BYTES(arr));
}
           

memset()

需要此值作為其第三個參數。

和以前一樣,如果将數組作為參數(指針)接收,則它将無法編譯,是以我們必須将宏調用替換為值:

void foo(ptrdiff_t nmemb, int arr[nmemb])
{

        memset(arr, 0, sizeof(arr[0]) * nmemb);
}
           

#19樓

對于多元數組,這有點複雜。 人們通常會定義顯式宏常量,即

#define g_rgDialogRows   2
#define g_rgDialogCols   7

static char const* g_rgDialog[g_rgDialogRows][g_rgDialogCols] =
{
    { " ",  " ",    " ",    " 494", " 210", " Generic Sample Dialog", " " },
    { " 1", " 330", " 174", " 88",  " ",    " OK",        " " },
};
           

但是這些常量也可以在編譯時使用sizeof求值:

#define rows_of_array(name)       \
    (sizeof(name   ) / sizeof(name[0][0]) / columns_of_array(name))
#define columns_of_array(name)    \
    (sizeof(name[0]) / sizeof(name[0][0]))

static char* g_rgDialog[][7] = { /* ... */ };

assert(   rows_of_array(g_rgDialog) == 2);
assert(columns_of_array(g_rgDialog) == 7);
           

請注意,此代碼可在C和C ++中使用。 對于二維以上的數組,請使用

sizeof(name[0][0][0])
sizeof(name[0][0][0][0])
           

等等,是無限的。

#20樓

“您介紹了一種微妙的腳下射擊方法”

C個“本機”數組不存儲其大小。 是以,建議将數組的長度儲存在單獨的變量/常量中,并在每次傳遞數組時将其傳遞,即:

#define MY_ARRAY_LENGTH   15
int myArray[MY_ARRAY_LENGTH];
           

您應該始終避免使用本機數組(除非您不能這樣做,否則請多加注意)。 如果您正在編寫C ++,請使用STL的“向量”容器。 “與數組相比,它們提供了幾乎相同的性能”,它們的作用要大得多!

// vector is a template, the <int> means it is a vector of ints
vector<int> numbers;  

// push_back() puts a new value at the end (or back) of the vector
for (int i = 0; i < 10; i++)
    numbers.push_back(i);

// Determine the size of the array
cout << numbers.size();
           

請參閱: http : //www.cplusplus.com/reference/stl/vector/