在C语言中,如何以及为什么要使用“sizeof(a)/sizeof(a[0])”来计算数组中的元素数量。

4

我是一个编程的初学者,不知道sizeof(a)和sizeof(a[0])的确切含义以计算数组中元素的数量。这个函数为什么要用?它在哪里使用?将它们相除的目的是什么。

5个回答

12
根据C标准(6.5.3.4 sizeof和alignof运算符),

2. sizeof 运算符返回其操作数的大小(以字节为单位),其可以是表达式或带括号的类型名称。大小由操作数的类型确定。结果是一个整数。如果操作数的类型是变长数组类型,则会评估该操作数;否则,操作数不会被评估,结果是一个整数常量。

因此,如果有一个数组,例如:
int a[N];

其中N是某个整数值,那么表达式

sizeof( a )

返回数组所占用的字节数。由于数组有N个元素,每个元素占用sizeof(int)字节,则

sizeof( a ) == N * sizeof( int )

或者说是同样的意思

sizeof( a ) == N * sizeof( a[0] )

因此,您可以按照以下方式计算N

N = sizeof( a ) / sizeof( a[0] )

如果您不知道数组的确切大小,例如因为其大小取决于初始化程序的数量,则这将非常有用。

例如

int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
const size_t N = sizeof( a ) / sizeof( *a );

请注意,初学者有时会犯错。

假设你有一个声明数组为参数的函数。

例如:

void f( int a[10] );

并且该函数可以这样调用

int a[10];

f( a );

初学者通常在函数主体中写下以下表达式

void f( int a[10] )
{
    size_t n = sizeof( a ) / sizeof( a[0] );
    //...
}

然而这是错误的代码。问题在于以数组形式声明的参数会被调整为指向数组元素类型的指针。因此,函数声明实际上看起来像:

void f( int *a );

并且在表达式中的函数内部

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

参数a是指针。也就是说,它等同于

    size_t n = sizeof( int * ) / sizeof( int );

根据使用的系统,指针占用4或8个字节。因此,如果sizeof(int)等于4,则会获得2或1。

您将无法获得用作参数的数组中元素的数量。

指针不会保留有关它们是指向单个对象还是某个数组的第一个对象的信息。

在这种情况下,您应该声明带有第二个参数的函数,该参数指定数组中的元素数量。例如:

void f( int *a, size_t n );

需要明确的是,如果数组被定义为int a[N],那么你已经知道元素的数量N。这只是一个例子。它被用于当你有int a[] = {1,2,3,4};并且元素的数量没有直接定义的情况下。 - Weather Vane
不要在原始指针上使用此操作,即 int *a... sizeof(a)/sizeof(a[0]),它将给出与元素数量不相关的结果。 - Jean-Baptiste Yunès

1

sizeof(a)和sizeof(a[0])的含义

sizeof(a)是操作数(在本例中是一个名为a的数组)的大小(以字节为单位)。

sizeof(a[0])是操作数的大小(以字节为单位),在本例中是数组的单个元素。

...计算数组中元素的数量。

将数组的大小除以一个元素的大小。sizeof(a)/sizeof(a[0])

为什么?

为了更方便地维护代码。考虑使用

some_type a[N];
... code that visually separates the declaration and the below loop
for (i=0; i<N; i++) 
  foo(a[i])

对抗
some_type a[N];
... lots of code
for (i=0; i<sizeof(a)/sizeof(a[0]); i++) 
  foo(a[i])

第一种方法,在将some_type a[N];更新为some_type a[N+1];后,我们需要搜索代码以更新循环和其他可能需要调整的地方。

第二种方法,在将some_type a[N];更新为some_type a[N+1];后,我们就完成了。


0

除了之前所说的,我认为 sizeof(myarray) 能够正常工作并返回类型乘以元素数量的事实可能非常依赖于编译器。有些编译器允许你这样做,而另一些则不行。如果你不小心,这是 C 编程中的一个陷阱。尝试编译和运行这个程序,亲自体验一下吧。

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


void Z1 ( int *z )
{
   printf(" size of z1 = %d\n", sizeof( z ) );
}

void Z2 ( int z[] )
{
   printf(" size of z2 = %d\n", sizeof( z ) );
}

void Z3 ( int z[10] )
{
   printf(" size of z3    = %d\n", sizeof( z ) );
   printf(" size of z3[5] = %d\n", sizeof ( z[5] ) );
}

int main ( int argc, char *argv[] )
{
   char a1;
   short int a2;
   int a3;
   long int a4;
   float a5;
   double a6;

   int myarray[10];


   for ( a3 = 0; a3 < 10; a3++ )
   {
      myarray[a3] = a3;
   }

   printf("\n");
   printf(" size of char      = %d\n", sizeof( a1 ) );
   printf(" size of short int = %d\n", sizeof( a2 ) );
   printf(" size of int       = %d\n", sizeof( a3 ) );
   printf(" size of long int  = %d\n", sizeof( a4 ) );
   printf(" size of float     = %d\n", sizeof( a5 ) );
   printf(" size of double    = %d\n", sizeof( a6 ) );

   printf(" size of myarray      = %d\n", sizeof( myarray ) );
   printf(" size of myarray[5]   = %d\n", sizeof( myarray[5] ) );

   printf("\n");

   Z1( myarray );
   Z2( myarray );
   Z3( myarray );
}

使用gcc版本4.3.4在Linux x86-64上编译,我得到的输出结果是:

 size of char      = 1
 size of short int = 2
 size of int       = 4
 size of long int  = 8
 size of float     = 4
 size of double    = 8
 size of myarray      = 40
 size of myarray[5]   = 4

 size of z1 = 8
 size of z2 = 8
 size of z3    = 8
 size of z3[5] = 4

0

sizeof 函数返回变量的字节数。因此,sizeof(a),其中 a 是一个数组,将返回数组的大小,即数组中元素的数量乘以一个元素的大小。

sizeof(a[0]) 将给出数组中一个元素的大小(我们只选择了第一个元素)。

所以 - sizeof(a) / sizeof(a[0]) = 数组长度 * 数组中一个元素的大小 / 数组中一个元素的大小 = 数组长度。


0
我会尝试用简单的话解释:
看一下,如果我们知道一个元素的大小是4,数组的总大小为20,那么数组中有多少个元素。
4 * X = 20
X = 20/4
Here also, we are doing same thing 
number of elements in array =
 
sizeof(Array) / sizeof 1 element of Array(sizeof(A[0]))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接