当前位置:  开发笔记 > 运维 > 正文

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

如何解决《如何在C中确定数组的大小?》经验,为你挑选了13个好方法。

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

也就是说,阵列可以容纳的元素数量是多少?



1> Mark Harriso..:

执行摘要:

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);


**重要**:不要在这里停止阅读,阅读下一个答案!这仅适用于_stack_上的数组,例如,如果您使用malloc()或访问函数参数,则运气不佳.见下文.
@Markus它适用于任何具有数组类型的变量; 这不一定是"在堆栈上".例如`static int a [20];`.但是你的评论对于那些可能没有意识到数组和指针之间差异的读者是有用的.
所有编译器应该是这种情况,因为sizeof的结果被定义为编译时常量.
生成的代码将是相同的,因为编译器在编译时知道*int_arr的类型(因此sizeof(*int_arr)的值).它将是一个常量,编译器可以相应地进行优化.
对于C或C++中的Windows API编程,在`WinNT.h`中定义了`ARRAYSIZE` makro(由其他头文件引入).因此WinAPI用户不需要定义自己的makro.
我们应该删除这个作为正确的答案.阅读@Markus评论.我浪费了几个小时,因为这个答案在malloc案例中不起作用.

2> Elideb..:

sizeof方法是正确的方式当且仅当你面对的不是收到的参数数组.作为参数发送到函数的数组被视为指针,因此sizeof将返回指针的大小,而不是数组的大小.

因此,在内部函数中,此方法不起作用.相反,始终传递一个额外的参数,size_t size指示数组中的元素数量.

测试:

#include 
#include 

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


@Bbvarghe那是因为64位系统中的指针是8个字节(sizeof(intArray)),但是int仍然(通常)是4个字节长(sizeof(intArray [0])).
@Pacerier:没有正确的代码 - 通常的解决方案是将长度与数组一起作为单独的参数传递.
如果仅传递指向第一个数组元素的指针,为什么是`参数的长度:2`?
等等,所以没有办法直接从指针访问数组并看到它的大小?这里是C新手.
@Michael Trouw:如果让你感觉更好,你可以使用运算符语法:`(sizeof array/sizeof*array)`.
@Nickolai这里的主要困惑是`sizeof`不是函数,而是C/C++中的运算符.如果从创建数组的同一范围调用,`sizeof`知道它的大小.但是,将数组作为参数传递时,该大小信息将丢失.该函数仅接收对内存中数组位置的引用,因此它被视为指针,用于所有目的.所以`sizeof`,当从函数内部调用时,只看到一个指针,并返回指针的大小.这些规则不适用于`sizeof`,因为它实际上不是一个函数,而且保留了范围.
@Elideb谢谢你.我发布评论后,我想我在其他地方看过类似的内容.最终帮助我理解的是,当在声明数组的同一范围内调用sizeof时,它将其参数视为int [7]类型的参数(使用答案中的示例),但在另一个范围内调用时它将其参数视为int*类型的参数.基本上你说的一样,只是用我自己的话:)
@MichaelTrouw,但正如在您自己的示例中chqrlie所演示的那样,它们也不是C中必需的。但是,是的,我离题,将C与您的HLL进行比较很愚蠢,它们的目标和意图截然不同。同样,不幸的是,如果您使用任何语言进行专业开发,都将使您的寿命缩短1-10年,因此您只能实现收支平衡:(

3> Magnus Hoff..:

值得注意的是,sizeof在处理已经衰减到指针的数组值时没有帮助:即使它指向数组的开头,对于编译器它也与指向该数组的单个元素的指针相同.指针不会"记住"用于初始化它的数组的任何其他内容.

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

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


这是一个很好的回应.我想评论所有上述断言都被评估为TRUE.

4> unwind..:

"技巧"的大小是我所知道的最好的方式,其中一个很小但是(对我来说,这是一个主要的烦恼)括号使用的重要变化.

正如维基百科条目所表明的那样,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> Arjun Sreedh..:
int size = (&arr)[1] - arr;

请查看此链接以获取解释


小挑剔:指针减法的结果是'ptrdiff_t`类型.(通常在64位系统上,这将是比`int`更大的类型).即使你在这段代码中将`int`改为`ptrdiff_t`,如果`arr`占用超过一半的地址空间,它仍然有一个错误.

6> Mohd Shibli..:

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

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

代码最初在这里找到: C程序查找数组中的元素数



7> Abhitesh kha..:

如果您知道数组的数据类型,则可以使用以下内容:

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(数组名称)都是指针.


“ int noofele = sizeof(arr)/ sizeof(int);”仅比编码“ int noofele = 9;”好一半。如果数组大小改变,使用`sizeof(arr)`可以保持灵活性。然而,如果更改arr []的类型,则需要更新sizeof(int)。最好使用`sizeof(arr)/ sizeof(arr [0])`,即使类型众所周知。不清楚为什么将`int`用作`noofele`而不是`size_t`,即由sizeof()返回的类型。

8> 小智..:

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最终将作为指针类型并使整个宏无效(就像你试图在带有指针参数的函数中使用宏一样).

在一天结束时,在这个特定的例子中,错误并不重要(所以我只是浪费每个人的时间; huzzah!),因为你没有带有'array'类型的表达式.但我认为关于预处理器评估小数的真正意义重大.


有没有理由不使用`(sizeof(x)/ sizeof(*x))`

9> Andreas Spin..:

对于多维数组,它有点复杂.通常人们定义显式宏常量,即

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

无限的,无限的.



10> Yogeesh H T..:

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


奇怪的是,代码使用的是“ size_t size_of_element”而使用了“ int”,而“ int n = sizeof(a)/ sizeof(a [0]);” `,而不是`size_t n = sizeof(a)/ sizeof(a [0]);`

11> Ted Percival..:
sizeof(array) / sizeof(array[0])



12> Ohad..:

"你已经介绍了一种在脚下射击自己的微妙方式"

C'原生'数组不存储它们的大小.因此,建议将数组的长度保存在单独的变量/ const中,并在每次传递数组时传递它,即:

#define MY_ARRAY_LENGTH   15
int myArray[MY_ARRAY_LENGTH];

你应该总是避免使用原生数组(除非你不能,在这种情况下,请注意你的脚).如果您正在编写C++,请使用STL的'vector'容器."与阵列相比,它们提供了几乎相同的性能",它们更有用!

// vector is a template, the  means it is a vector of ints
vector 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/



13> Andy Nugent..:
#define SIZE_OF_ARRAY(_array) (sizeof(_array) / sizeof(_array[0]))


请注意,这仅适用于实际数组,而不适用于指向数组的指针.
推荐阅读
低调pasta_730
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有