如何确定 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]), ,数组的零元素的大小。

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

其他提示

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

值得一提的是 sizeof 在处理已衰减为指针的数组值时没有帮助:尽管它指向数组的开头,但对于编译器来说,它与指向该数组的单个元素的指针相同。指针不会“记住”有关用于初始化它的数组的任何其他信息。

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 不是一个函数;这是一个 操作员. 。因此,它不需要在其参数周围使用括号,除非该参数是类型名称。这很容易记住,因为它使参数看起来像也使用括号的强制转换表达式。

所以:如果您有以下情况:

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

现在你受到保护了。当然,您复制了变量的名称,但是如果您更改它,则很可能会破坏编译器可以检测到的方式。

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

查看 这个链接 用于解释

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

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

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

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

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 (数组名)是一个指针。

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

归根结底,在这个 特别的 例如,错误并不重要(所以我只是在浪费大家的时间;好极了!),因为你没有“数组”类型的表达式。但我认为关于预处理器评估微妙之处确实很重要。

为了 多维数组 这有点复杂。人们通常定义显式的宏常量,即

#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",        " " },
};

但这些常量也可以在编译时评估 大小:

#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 中数组的大小:

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

“你引入了一种搬起石头砸自己脚的微妙方式”

C“原生”数组不存储其大小。因此建议将数组的长度保存在单独的变量/const中,并在传递数组时传递它,即:

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

@马格努斯:该标准将 sizeof 定义为生成对象中的字节数,并且 sizeof (char) 始终为 1。一个字节中的位数是特定于实现的。

编辑:ANSI C++ 标准第 5.3.3 节 Sizeof:

sizeof 运算符生成其操作数的对象表示形式中的字节数。[...] sizeof (char)、sizeof (signed char) 和 sizeof (unsigned char) 均为 1;sizeof 应用于任何其他基本类型的结果是实现定义的。

1.6节C++内存模型:

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

@斯基兹:我很确定我是对的,尽管我现在可以给你的最好的“来源”是维基百科,来自关于 sizeof 的文章:

维基百科是错的,斯基兹是对的。根据定义,sizeof(char) 为 1。

我是说, 仔细阅读维基百科条目 看到它是错误的。“多个字符”。 sizeof(char) 永远不可能成为任何东西 其他 比“1”。如果是 2,则意味着 sizeof(char) 是 char 大小的两倍!

如果您确实想这样做来传递数组,我建议实现一个结构来存储指向您想要的数组类型的指针和表示数组大小的整数。然后你可以将其传递给你的函数。只需将数组变量值(指向第一个元素的指针)分配给该指针即可。然后你就可以走了 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;
}

最好的方法是保存此信息,例如,在结构中:

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

实现所有必要的功能,例如创建、销毁、检查相等性以及您需要的所有其他功能。作为参数传递更容易。

功能 sizeof 返回数组在内存中使用的字节数。如果你想计算数组中元素的数量,你应该将该数字除以 sizeof 数组的变量类型。比方说 int array[10];, ,如果您的计算机中的变量类型整数是32位(或4字节),为了获取数组的大小,您应该执行以下操作:

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

您可以使用 & 操作员。这是源代码:

#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
int a[10];
int size = (*(&a+1)-a) ;

欲了解更多详情,请参阅这里并且 这里.

例子

#include <stdio.h>

int main() {
    int size;
    scanf("%d", &size);
    int array[size];
    printf("%d\n", (int) (sizeof(array) / sizeof(int)));
    printf("%d\n", (int) (sizeof(array) / sizeof(array[0])));
    return 0;
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top