提问人:Mark Harrison 提问时间:9/1/2008 最后编辑:Daniel WalkerMark Harrison 更新时间:9/2/2023 访问量:3212892
如何在 C 中确定数组的大小?
How do I determine the size of my array in C?
答:
摘要:
int a[17];
size_t n = sizeof(a)/sizeof(a[0]);
完整答案:
若要确定数组的大小(以字节为单位),可以使用运算符:sizeof
int a[17];
size_t n = sizeof(a);
在我的计算机上,int 的长度为 4 个字节,因此 n 为 68。
为了确定数组中元素的数量,我们可以除以 数组的总大小乘以数组元素的大小。 您可以使用以下类型执行此操作,如下所示:
int a[17];
size_t n = sizeof(a) / sizeof(int);
并获得正确的答案(68 / 4 = 17),但是如果更改了类型,如果您忘记更改,您将遇到一个令人讨厌的错误
以及。a
sizeof(int)
所以优选的除数是或等价的,数组第一个元素的大小。sizeof(a[0])
sizeof(*a)
int a[17];
size_t n = sizeof(a) / sizeof(a[0]);
另一个优点是您现在可以轻松进行参数化 宏中的数组名称和 get:
#define NELEMS(x) (sizeof(x) / sizeof((x)[0]))
int a[17];
size_t n = NELEMS(a);
评论
ARRAYSIZE
WinNT.h
static int a[20];
sizeof(array) / sizeof(array[0])
评论
array
sizeof(array) / sizeof(array[0])
array
char
unsigned char
signed char
sizeof(array)
值得注意的是,在处理已衰减为指针的数组值时,这无济于事:即使它指向数组的开头,但对于编译器来说,它与指向该数组的单个元素的指针相同。指针不会“记住”用于初始化它的数组的任何其他内容。sizeof
int a[10];
int* p = a;
assert(sizeof(a) / sizeof(a[0]) == 10);
assert(sizeof(p) == sizeof(int*));
assert(sizeof(*p) == sizeof(int));
评论
char
“诀窍”是我所知道的最好的方法,括号的使用有一个小但(对我来说,这是一个主要的烦恼)重要的变化。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);
现在您受到了保护。当然,你复制了变量的名称,但如果你改变它,它很有可能以编译器可以检测到的方式中断。
评论
sizeof(int)
sizeof(foo)
int x = 1+1;
int x = (1+1);
sizeof
可能是一个运算符,但根据 Linus Torvalds 的说法,它应该被视为一个函数。我同意。在这里阅读他的理性:lkml.org/lkml/2012/7/11/103
sizeof myArray / sizeof *myArray;
sizeof(myArray / sizeof *myArray);
对于多维数组,它有点复杂。通常,人们会定义显式的宏常数,即
#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])
等等,无穷无尽。
“你引入了一种微妙的搬起石头砸自己的脚的方式”
C 的“原生”数组不存储它们的大小。因此,建议将数组的长度保存在单独的变量/常量中,并在传递数组时传递它,即:
#define MY_ARRAY_LENGTH 15
int myArray[MY_ARRAY_LENGTH];
如果你正在编写 C++,你应该始终避免使用原生数组(除非你不能,在这种情况下,注意你的脚)。如果您正在编写 C++,请使用 STL 的“vector”容器。“与阵列相比,它们提供几乎相同的性能”,而且它们更有用!
// 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/
评论
std::array<int,10>
是普通阵列的直接替代品。仅当您实际希望其大小为运行时变量时才使用。 不会将大小存储在内存中的任何位置,但它会将大小关联为类型的一部分,从而为您提供所有效率,而不会带来维护风险。std::vector
std::array
如果您处理未作为参数接收的数组,则该方法是正确的方法。作为参数发送到函数的数组被视为指针,因此将返回指针的大小,而不是数组的大小。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
评论
length of parameter:2
(sizeof array / sizeof *array)
您可以使用运算符。源代码如下:&
#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
评论
ptrdiff_t
sizeof()
size_t
((char *)(&a+1)-(char *)a)/(sizeof(a[0]))
size_t
z
printf("The size of array a is %zu\n", sizeof a/sizeof a[0]);
(char *)(&a+1)-(char *)a
不是一个常量,可以在运行时计算,即使使用固定大小的 . 在本例中,是编译时完成的常量。a[10]
sizeof(a)/sizeof(a[0])
如果你真的想这样做来传递你的数组,我建议实现一个结构来存储一个指向你想要的类型的指针,一个数组和一个表示数组大小的整数。然后,你可以把它传递给你的函数。只需将数组变量值(指向第一个元素的指针)分配给该指针即可。然后你可以去获取第 i 个元素并用于获取数组中的元素数量。Array.arr[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;
}
评论
strcpy(d.name, name);
strcpy
int size = (&arr)[1] - arr;
查看此链接以获取说明
评论
ptrdiff_t
int
int
ptrdiff_t
arr
/3G
foo buf1[80]; foo buf2[sizeof buf1/sizeof buf1[0]]; foo buf3[(&buf1)[1] - buf1];
buf3[]
(&buf1)[1] - buf1
如果您知道数组的数据类型,则可以使用如下方法:
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);
只比编码好一半。使用时,如果阵列大小发生变化,则保持灵活性。然而,如果类型发生变化,则需要更新。即使类型众所周知,也最好使用。不清楚为什么使用 for vs. ,返回的类型。int noofele = 9;
sizeof(arr)
sizeof(int)
arr[]
sizeof(arr)/sizeof(arr[0])
int
noofele
size_t
sizeof()
每个人都在使用的宏计算不正确。实际上,这只是一个敏感问题,因为你不能有导致“数组”类型的表达式。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
归根结底,在这种特殊情况下,错误并不重要(所以我只是在浪费每个人的时间;呵呵!),因为你没有带有“数组”类型的表达式。但实际上,我认为关于预处理器评估微妙之处的一点很重要。
评论
(sizeof (x) / sizeof (*x))
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]);
char a[INT_MAX + 1u];
int n
int n = sizeof (a) / sizeof (a[0]);
size_t n = sizeof (a) / sizeof (a[0]);
最好的方法是将此信息保存在结构中,例如,在结构中:
typedef struct {
int *array;
int elements;
} list_s;
实现所有必要的功能,例如创建、销毁、检查相等以及您需要的所有其他功能。它更容易作为参数传递。
评论
int elements
size_t elements
#define SIZE_OF_ARRAY(_array) (sizeof(_array) / sizeof(_array[0]))
评论
您可以使用 sizeof 运算符,但它不适用于函数,因为它将接受指针的引用。 您可以执行以下操作来查找数组的长度:
len = sizeof(arr)/sizeof(arr[0])
代码最初在这里找到:
评论
注意:正如 M.M 在评论中指出的那样,这可能会给你未定义的行为。
int a[10];
int size = (*(&a+1)-a);
有关更多详细信息,请参阅此处和此处。
评论
*
*(&a+1) - a;
(&a)[1] - a;
*(&a+1)
(&a)[1]
x[y]
*(x + (y))
该函数返回内存中数组使用的字节数。如果要计算数组中的元素数,则应将该数除以数组的变量类型。假设,如果计算机中的变量类型整数是 32 位(或 4 个字节),为了获得数组的大小,您应该执行以下操作:sizeof
sizeof
int array[10];
int array[10];
size_t sizeOfArray = sizeof(array)/sizeof(int);
评论
size_t sizeOfArray
int
最简单的答案:
#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;
}
评论
我建议永远不要使用 sizeof
(即使可以使用)来获取数组的两种不同大小中的任何一种,无论是元素数还是字节数,这是我在这里展示的最后两种情况。对于这两种大小中的每一种,下面显示的宏都可用于使其更安全。原因是为了让维护者清楚地看到代码的意图,并且乍一看 sizeof(ptr
) 与 sizeof(arr)
的区别(以这种方式编写并不明显),因此对于阅读代码的每个人来说,错误都是显而易见的。
TL;博士:
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + must_be_array(arr))
#define ARRAY_BYTES(arr) (sizeof(arr) + must_be_array(arr))
must_be_array(arr)
(定义见下文)需要 IS 因为 -Wsizeof-pointer-div
有问题(截至 2020 年 4 月):
#define is_same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
#define is_array(arr) (!is_same_type((arr), &(arr)[0]))
#define must_be(e) \
( \
0 * (int)sizeof( \
struct { \
static_assert(e); \
char ISO_C_forbids_a_struct_with_no_members__; \
} \
) \
)
#define must_be_array(arr) must_be(is_array(arr))
关于这个主题有一些重要的错误:https://lkml.org/lkml/2015/9/3/428
我不同意 Linus 提供的解决方案,即永远不要对函数的参数使用数组表示法。
我喜欢数组表示法作为指针用作数组的文档。但这意味着需要应用万无一失的解决方案,以便不可能编写有缺陷的代码。
从一个数组中,我们有三种大小,我们可能想知道:
- 数组元素的大小
- 数组中的元素数
- 数组在内存中使用的大小(以字节为单位)
数组元素的大小
第一个非常简单,无论我们处理的是数组还是指针都无关紧要,因为它是以相同的方式完成的。
使用示例:
void foo(size_t nmemb, int arr[nmemb])
{
qsort(arr, nmemb, sizeof(arr[0]), cmp);
}
qsort()
需要此值作为其第三个参数。
对于其他两个大小,也就是问题的主题,我们希望确保我们正在处理一个数组,如果没有,则中断编译,因为如果我们处理指针,我们将得到错误的值。当编译被破坏时,我们将能够很容易地看到我们不是在处理数组,而是在处理指针,我们只需要用变量或宏编写代码,将数组的大小存储在指针后面。
数组中的元素数
这个是最常见的,许多答案都为您提供了典型的宏:ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
最新版本的编译器(如 GCC 8)会在您将此宏应用于指针时发出警告,因此它是安全的(还有其他方法可以使其在较旧的编译器中安全)。
它的工作原理是将整个数组的大小(以字节为单位)除以每个元素的大小。
使用示例:
void foo(size_t nmemb)
{
char buf[nmemb];
fgets(buf, ARRAY_SIZE(buf), stdin);
}
void bar(size_t nmemb)
{
int arr[nmemb];
for (size_t i = 0; i < ARRAY_SIZE(arr); i++)
arr[i] = i;
}
如果这些函数不使用数组,而是将它们作为参数,则以前的代码将无法编译,因此不可能有错误(假设使用了最新的编译器版本,或者使用了其他技巧),我们需要用以下值替换宏调用:
void foo(size_t nmemb, char buf[nmemb])
{
fgets(buf, nmemb, stdin);
}
void bar(size_t nmemb, int arr[nmemb])
{
for (size_t i = nmemb - 1; i < nmemb; i--)
arr[i] = i;
}
数组在内存中使用的大小(以字节为单位)
ARRAY_SIZE
通常用作前一个案例的解决方案,但这种情况很少被安全地编写,可能是因为它不太常见。
获取此值的常用方法是使用 .问题:与上一个相同;如果你有一个指针而不是一个数组,你的程序就会发疯。sizeof(arr)
该问题的解决方案涉及使用与以前相同的宏,我们知道这是安全的(如果它应用于指针,它会破坏编译):
#define ARRAY_BYTES(arr) (sizeof((arr)[0]) * ARRAY_SIZE(arr))
它的工作原理非常简单:它取消了除法,因此在数学取消后,您最终只得到一个,但增加了结构的安全性。ARRAY_SIZE
sizeof(arr)
ARRAY_SIZE
使用示例:
void foo(size_t nmemb)
{
int arr[nmemb];
memset(arr, 0, ARRAY_BYTES(arr));
}
memset()
需要此值作为其第三个参数。
和以前一样,如果数组作为参数(指针)接收,则它不会编译,我们将不得不用以下值替换宏调用:
void foo(size_t nmemb, int arr[nmemb])
{
memset(arr, 0, sizeof(arr[0]) * nmemb);
}
更新(2020 年 4 月 23 日):-Wsizeof-pointer-div
有问题:
今天我发现 GCC 中的新警告仅在宏在不是系统标头的标头中定义时才有效。如果您在系统中安装的标头(通常是或)()中定义宏,编译器将不会发出警告(我尝试了 GCC 9.3.0)。/usr/local/include/
/usr/include/
#include <foo.h>
因此,我们拥有并希望确保它的安全。我们将需要 C2X 和一些 GCC 扩展:表达式中的语句和声明,__builtin_types_compatible_p:#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
static_assert()
#include <assert.h>
#define is_same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
#define is_array(arr) (!is_same_type((arr), &(arr)[0]))
#define Static_assert_array(arr) static_assert(is_array(arr))
#define ARRAY_SIZE(arr) \
({ \
Static_assert_array(arr); \
sizeof(arr) / sizeof((arr)[0]); \
})
现在是完全安全的,因此它的所有衍生物都是安全的。ARRAY_SIZE()
更新:libbsd 提供:__arraycount()
Libbsd 在 <sys/cdefs.h>
中提供了宏,这是不安全的,因为它缺少一对括号,但我们可以自己添加这些括号,因此我们甚至不需要在标头中编写除法(为什么要复制已经存在的代码?该宏是在系统标头中定义的,因此如果我们使用它,我们将被迫使用上面的宏。__arraycount()
#inlcude <assert.h>
#include <stddef.h>
#include <sys/cdefs.h>
#include <sys/types.h>
#define is_same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
#define is_array(arr) (!is_same_type((arr), &(arr)[0]))
#define Static_assert_array(arr) static_assert(is_array(arr))
#define ARRAY_SIZE(arr) \
({ \
Static_assert_array(arr); \
__arraycount((arr)); \
})
#define ARRAY_BYTES(arr) (sizeof((arr)[0]) * ARRAY_SIZE(arr))
有些系统在 <sys/param.h>
中提供,有些系统同时提供两者。你应该检查你的系统,并使用你拥有的系统,也许使用一些预处理器条件来实现可移植性并支持两者。nitems()
更新:允许在文件范围内使用宏:
不幸的是,gcc扩展名不能在文件范围内使用。
为了能够在文件范围内使用宏,静态断言必须
里面。然后,将其乘以不影响
结果。强制转换可能适合模拟函数
返回(在这种情况下,它不是必需的,但随后它
可重用于其他用途)。({})
sizeof(struct {})
0
(int)
(int)0
此外,可以简化定义。ARRAY_BYTES()
#include <assert.h>
#include <stddef.h>
#include <sys/cdefs.h>
#include <sys/types.h>
#define is_same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
#define is_array(arr) (!is_same_type((arr), &(arr)[0]))
#define must_be(e) \
( \
0 * (int)sizeof( \
struct { \
static_assert(e); \
char ISO_C_forbids_a_struct_with_no_members__; \
} \
) \
)
#define must_be_array(arr) must_be(is_array(arr))
#define ARRAY_SIZE(arr) (__arraycount((arr)) + must_be_array(arr))
#define ARRAY_BYTES(arr) (sizeof(arr) + must_be_array(arr))
笔记:
此代码使用以下扩展,这些扩展是完全必要的,并且它们的存在对于实现安全性是绝对必要的。如果你的编译器没有它们,或者一些类似的编译器,那么你就无法达到这个安全级别。
我还使用了以下 C2X 功能。但是,使用旧标准可以克服它的缺失,可以使用一些肮脏的技巧来克服(例如:C 代码中的“:-!!”是什么?(在 C11 中,您也有 ,但它需要一条消息)。static_assert()
评论
sizeof
sizeof
一个更优雅的解决方案将是
size_t size = sizeof(a) / sizeof(*a);
评论
除了已经提供的答案之外,我还想指出一个特殊情况,即使用
sizeof(a) / sizeof (a[0])
If 是 的数组,或者不需要使用两次,因为具有这些类型之一操作数的表达式总是会导致 。a
char
unsigned char
signed char
sizeof
sizeof
1
引自 C18,6.5.3.4/4:
"当
sizeof
应用于类型为 char、unsigned
char 或signed char
(或其限定版本)的操作数时,结果为1
。
因此,将等价于 if 是 类型的数组,或 。通过 1 的划分是多余的。sizeof(a) / sizeof (a[0])
NUMBER OF ARRAY ELEMENTS / 1
a
char
unsigned char
signed char
在这种情况下,您可以简单地缩写并执行:
sizeof(a)
例如:
char a[10];
size_t length = sizeof(a);
如果你想要一个证据,这里是一个指向 GodBolt 的链接。
尽管如此,如果类型发生重大变化,该部门仍会保持安全(尽管这些情况很少见)。
评论
/ sizeof (a[0])
char
unsigned char
signed char
对于预定义数组:
int a[] = {1, 2, 3, 4, 5, 6};
计算数组中的元素数:
element _count = sizeof(a) / sizeof(a[0]);
评论
若要了解在代码中显式声明并由其变量引用的固定数组的大小,可以使用 sizeof,例如:
int a[10];
int len = sizeof(a)/sizeof(int);
但这通常是无用的,因为你已经知道答案了。
但是,如果你有一个指针,你不能使用 sizeof,这是一个原则问题。
但。。。由于数组是作为线性内存呈现给用户的,因此如果您知道最后一个元素地址并且知道类型的大小,则可以计算大小,然后您可以计算它有多少个元素。例如:
#include <stdio.h>
int main(){
int a[10];
printf("%d\n", sizeof(a)/sizeof(int));
int *first = a;
int *last = &(a[9]);
printf("%d\n", (last-first) + 1);
}
输出:
10
10
此外,如果无法利用编译时间,则可以:
#include <stdio.h>
int main(){
int a[10];
printf("%d\n", sizeof(a)/sizeof(int));
void *first = a;
void *last = &(a[9]);
printf("%d\n", (last-first)/sizeof(int) + 1);
}
评论
void*
#ifndef __cplusplus
/* C version */
# define ARRAY_LEN_UNSAFE(X) (sizeof(X)/sizeof(*(X)))
# define ARRAY_LEN(X) (ARRAY_LEN_UNSAFE(X) + 0 * sizeof((typeof(*(X))(*[1])[ARRAY_LEN_UNSAFE(X)]){0} - (typeof(X)**)0))
#else
/* C++ version */
template <unsigned int N> class __array_len_aux { public: template <typename T, unsigned int M> static const char (&match_only_array(T(&)[M]))[M]; };
template <> class __array_len_aux<0> { public: template <typename T> static const char (&match_only_array(T(&)))[0]; };
# define ARRAY_LEN(X) sizeof(__array_len_aux<sizeof(X)>::match_only_array(X))
#endif
/* below are verifying codes */
#include <assert.h>
void * a0[0];
void * a1[9];
void * aa0[0];
void * aa1[5][10];
void *p;
struct tt {
char x[10];
char *p;
} t;
static_assert(ARRAY_LEN(a0) == 0, "verify [0]");
static_assert(ARRAY_LEN(aa0) == 0, "verify [0][N]");
static_assert(ARRAY_LEN(a1) == 9, "verify [N]");
static_assert(ARRAY_LEN(aa1) == 5, "verify [N][M]");
static_assert(ARRAY_LEN(aa1[0]) == 10, "verify inner array of [N][M]");
static_assert(ARRAY_LEN(t.x) == 10, "verify array in struct");
//static_assert(ARRAY_LEN(p) == 0, "should parse error");
//static_assert(ARRAY_LEN(t.p) == 0, "should parse error");
以下版本仅依赖于 。和版本具有相同的行为,只接受数组(包括 0 长度或多维数组),但拒绝任何指针类型。C
ARRAY_LEN
typeof()
C++
C
评论
int foo[5];
sizeof(array)/sizeof(array[0])