我如何确定我的数组在C中的大小?

我如何确定我的数组在C中的大小?

也就是说,数组可以容纳的元素的数量?

执行摘要:

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

要以字节为单位确定数组的大小,可以使用sizeof运算符:

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

在我的电脑上,整数是4个字节,所以n是68。

为了确定数组中元素的数量,我们可以将数组的总大小除以数组元素的大小。 你可以用types来做到这一点,就像这样:

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

并得到正确的答案(68/4 = 17),但是如果你改变了types,如果你忘记修改sizeof(int)话,你会有一个讨厌的bug。

因此,首选的除数是sizeof(a[0]) ,即数组中的zeroeth元素的大小。

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

另一个好处是,你现在可以很容易地在macros中参数化数组名,并得到:

 #define NELEMS(x) (sizeof(x) / sizeof((x)[0])) int a[17]; int n = NELEMS(a); 

如果您正在处理未作为参数接收的数组,则sizeof方法是正确的。 作为参数发送到函数的数组被视为一个指针,所以sizeof将返回指针的大小,而不是数组的大小。

因此,内部函数这个方法不起作用。 相反,总是传递一个额外的参数size_t size指出数组中元素的数量。

testing:

 #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 

值得注意的是sizeof在处理一个已经衰减到一个指针的数组值的时候并没有帮助:即使它指向一个数组的开始,对于编译器来说,它和指向单个元素的指针是一样的arrays。 指针不会“记住”用于初始化数组的任何其他内容。

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

“窍门”的大小是我所知道的最好的方式,对于括号的使用来说,一个小的(对我来说,这是一个主要的宠物)是重要的改变。

正如维基百科条目所表明的那样,C的sizeof不是一个函数; 这是一个运营商 。 因此,除非参数是types名称,否则它不需要围绕其参数的括号。 这很容易记住,因为它使参数看起来像一个expression式,也使用括号。

所以:如果你有以下几点:

 int myArray[10]; 

你可以find像这样的代码元素的数量:

 size_t n = sizeof myArray / sizeof *myArray; 

对我来说,读取比括号中的select更容易。 我也赞成在分区的右边使用星号,因为它比索引更简洁。

当然,这也是编译时间,所以不必担心影响程序性能的分工。 所以尽可能使用这种forms。

当你有一个实际的对象时,最好使用sizeof,而不是一个types,因为那样你就不用担心出错和声明错误的types。

例如,假设你有一个函数,把一些数据输出为字节stream,例如通过networking。 让我们调用函数send() ,并将它作为参数指向要发送的对象的指针,以及对象中的字节数。 所以,原型变成:

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

然后你需要发送一个整数,所以你这样编码:

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

现在,通过在两个地方指定foo的types,您已经引入了一种微妙的方式在脚下射击自己。 如果一个改变,但另一个不改变,代码就会中断。 因此,总是这样做:

 send(&foo, sizeof foo); 

现在你被保护了。 当然,你可以复制variables的名字,但是如果你改变的话,那么很可能会被编译器检测到。

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

看看这个链接的解释

如果你知道数组的数据types,你可以使用类似于:

 int arr[] = {23, 12, 423, 43, 21, 43, 65, 76, 22}; int noofele = sizeof(arr)/sizeof(int); 

或者,如果您不知道数组的数据types,则可以使用如下所示的内容:

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

注意:只有在运行时未定义数组(如malloc)并且数组不在函数中传递的情况下,此函数才起作用。 在这两种情况下, arr (数组名称)都是一个指针。

对于multidimensional array来说,这有点复杂。 通常人们定义明确的macros常量,即

 #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]) 

等等,无穷无尽。

大家正在使用的macrosARRAYELEMENTCOUNT(x)评估不正确 。 这实际上只是一个敏感的问题,因为你不能有expression式导致'数组'types。

 /* 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预处理器如何工作。 您总是包装macros参数,而不是可能涉及的expression式。


这是对的; 我的例子是一个糟糕的例子。 但是这实际上是应该发生的。 正如我前面提到的那样, p + 1将最终成为指针types,并使整个macros无效(就像如果您试图在带有指针参数的函数中使用macros一样)。

在这一天结束的时候,在这个特定的例子中,错误并不重要(所以我只是在浪费大家的时间;因为你没有一个“数组”types的expression式。 但是我认为关于预处理器评估的关键点真的很重要。

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

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 
 #define SIZE_OF_ARRAY(_array) (sizeof(_array) / sizeof(_array[0])) 

您可以使用sizeof运算符,但它不会用于函数,因为它会采取指针的引用,您可以执行以下操作来查找数组的长度

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

上述代码C程序的引用来查找数组中元素的数量

“你已经引入了一种微妙的方式在脚下射击自己”

C本地数组不存储它们的大小。 因此,build议将数组的长度保存在一个单独的variables/ const中,并在传递数组时传递它,即:

 #define MY_ARRAY_LENGTH 15 int myArray[MY_ARRAY_LENGTH]; 

你应该总是避免本地数组(除非你不能,在这种情况下,请记住你的脚)。 如果您正在编写C ++,请使用STL的“向量”容器。 “与arrays相比,它们提供的性能几乎相同”,而且它们更有用!

 // 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/

@ Magnus:标准将sizeof定义为产生对象中的字节数,sizeof(char)永远是1。 一个字节中的位数是特定于实现的。

编辑:ANSI C ++标准部分5.3.3 Sizeof:

sizeof运算符产生其操作数的对象表示中的字节数。 sizeof(char),sizeof(signed char)和sizeof(unsigned char)是1; 适用于任何其他基本types的sizeof的结果是实现定义的。

1.6节C ++内存模型:

C ++内存模型中的基本存储单元是字节。 一个字节至less足够大以包含基本执行字符集的任何成员,并且由一个连续的位序列组成,其数目是由实现定义的。

@Skizz:我很确定我是对的,虽然目前我能给你的最好的“资源”是维基百科,从sizeof上的文章来看:

维基百科是错误的,Skizz是正确的。 根据定义,sizeof(char)是1。

我的意思是, 只要仔细阅读维基百科的条目 ,看看是错的。 “字符的倍数”。 sizeof(char)永远不能是“1”以外的任何东西。 如果是2,那就意味着sizeof(char)sizeof(char)两倍!

如果你真的想这样做来传递你的数组,我build议实现一个结构来存储一个指向你想要的数组types的指针和一个表示数组大小的整数。 然后你可以把它传递给你的函数。 只要将数组variables值(指向第一个元素的指针)赋给那个指针即可。 然后你可以去Array.arr[i]获得第i个元素,并使用Array.size来获取数组中的元素数量。

我为你包含了一些代码。 这不是很有用,但你可以扩展更多的function。 说实话,如果这些是你想要的东西,你应该停止使用C,并使用内置这些function的另一种语言。

 /* 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; } 

最好的方法是将这些信息保存在一个结构中:

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

实现所有必要的function,如创build,销毁,检查平等,和其他所有你需要的。 作为parameter passing更容易。

您可以使用&运算符。 这里是源代码:

 #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 

sizeof()不应该用于获取所有情况下的元素数量。 数组大小(或长度)的单独参数,即。 size_t应该被传递给一个函数。

 #include<stdio.h> void fun(int arr[], size_t arr_size) { int i; for (i = 0; i < arr_size; i++) { arr[i] = i; } } int main() { int i; int arr[4] = {0, 0 ,0, 0}; fun(arr, 4); for(i = 0; i < sizeof(arr)/sizeof(arr[0]); i++) printf(" %d ", arr[i]); getchar(); return 0; } 

由于这个程序无法获得大小…这就是为什么以上使用..

  #include<stdio.h> void fun(int arr[]) { int i; //sizeof should not be used here to get number of element of array int arr_size = sizeof(arr)/sizeof(arr[0]); //incorrect use of sizeof for (i = 0; i < arr_size; i++) { arr[i] = i; /*executed only once */ } } int main() { int i; int arr[4] = {0, 0 ,0, 0}; fun(arr); for(i = 0; i < sizeof(arr)/sizeof(arr[0]); i++) //sizeof is fine here printf(" %d " ,arr[i]); getchar(); return 0; } 

使用:

 int a=[10] = {1, 2, 3, 4, 5}; int n = sizeof(a); printf("%d", n); 

输出:

 5 

原因:计算数组中保存的元素的数量,而不是分配给它的空闲空间的数量。