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

如何在C中确定数组的大小?,c,arrays,memory,C,Arrays,Memory,如何在C中确定数组的大小 也就是说,数组可以容纳的元素数?执行摘要: int a[17]; size_t n = sizeof(a)/sizeof(a[0]); #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + must_be_array(arr)) #define ARRAY_SSIZE(arr) ((ptrdiff_t)ARRAY_SIZE(arr)) #define ARRAY_BYTES(arr)

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


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

执行摘要:

int a[17];
size_t n = sizeof(a)/sizeof(a[0]);
#define ARRAY_SIZE(arr)     (sizeof(arr) / sizeof((arr)[0]) + must_be_array(arr))

#define ARRAY_SSIZE(arr)    ((ptrdiff_t)ARRAY_SIZE(arr))

#define ARRAY_BYTES(arr)    (sizeof(arr) + must_be_array(arr))

#define ARRAY_SBYTES(arr)   ((ssize_t)ARRAY_BYTES(arr))

完整答案:

int a[17];
size_t n = sizeof(a)/sizeof(a[0]);
#define ARRAY_SIZE(arr)     (sizeof(arr) / sizeof((arr)[0]) + must_be_array(arr))

#define ARRAY_SSIZE(arr)    ((ptrdiff_t)ARRAY_SIZE(arr))

#define ARRAY_BYTES(arr)    (sizeof(arr) + must_be_array(arr))

#define ARRAY_SBYTES(arr)   ((ssize_t)ARRAY_BYTES(arr))
要确定数组的字节大小,可以使用
sizeof
接线员:

int a[17];
size_t n = sizeof(a);
在我的计算机上,整数是4字节长,所以n是68

要确定数组中的元素数,我们可以将 数组的总大小乘以数组元素的大小。 您可以使用以下类型执行此操作:

int a[17];
size_t n = sizeof(a) / sizeof(int);
size_t n = sizeof myArray / sizeof *myArray;
int foo = 4711;
send(&foo, sizeof (int));
send(&foo, sizeof foo);
并得到正确的答案(68/4=17),但如果
a
更改如果忘记更改,您将有一个严重的错误
sizeof(int)

因此,首选除数是
sizeof(a[0])
或等效的
sizeof(*a)
,数组第一个元素的大小

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
在处理已衰减为指针的数组值时没有帮助:即使它指向数组的开头,但对于编译器来说,它与指向该数组的单个元素的指针相同。指针不会“记住”用于初始化它的数组的任何其他内容

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

assert(sizeof(a) / sizeof(a[0]) == 10);
assert(sizeof(p) == sizeof(int*));
assert(sizeof(*p) == sizeof(int));
sizeof
“技巧”是我所知道的最好的方法,在括号的使用上有一个小的但(对我来说,这是一个主要的恼怒)重要的改变

正如维基百科的条目所表明的,C的
sizeof
不是一个函数;它是一个操作符。因此,除非参数是类型名,否则它不需要在参数周围加括号。这很容易记住,因为它使参数看起来像一个强制转换表达式,它也使用括号

因此:如果您有以下情况:

int myArray[10];
int array[10];
int sizeOfArray = sizeof(array)/sizeof(int);
您可以通过以下代码找到元素的数量:

int a[17];
size_t n = sizeof(a) / sizeof(int);
size_t n = sizeof myArray / sizeof *myArray;
int foo = 4711;
send(&foo, sizeof (int));
send(&foo, sizeof foo);
对我来说,这比带括号的选项容易得多。我也喜欢在除法的右边部分使用星号,因为它比索引更简洁

当然,这也都是编译时,所以不必担心分割会影响程序的性能。因此,尽可能使用此表单

最好在实际对象上使用
sizeof
,而不是在类型上,因为这样就不必担心出错和声明错误的类型

例如,假设您有一个函数,它以字节流的形式输出一些数据,例如通过网络输出。让我们调用函数
send()
,并将指向要发送的对象的指针和对象中的字节数作为参数。因此,原型变成:

void send(const void *object, size_t size);
然后你需要发送一个整数,你可以这样编码:

int a[17];
size_t n = sizeof(a) / sizeof(int);
size_t n = sizeof myArray / sizeof *myArray;
int foo = 4711;
send(&foo, sizeof (int));
send(&foo, sizeof foo);
现在,通过在两个位置指定
foo
的类型,您介绍了一种巧妙的射中自己脚的方法。如果一个改变了,而另一个没有改变,代码就会中断。因此,请始终这样做:

int a[17];
size_t n = sizeof(a) / sizeof(int);
size_t n = sizeof myArray / sizeof *myArray;
int foo = 4711;
send(&foo, sizeof (int));
send(&foo, sizeof foo);

现在你得到了保护。当然,您复制了变量的名称,但是如果您更改它,编译器很可能会检测到它的中断。

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

#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进行计算:

<>请注意,此代码在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++,请使用“s”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();
//矢量是一个模板,表示它是整数的矢量
向量数;
//push_back()在向量的末尾(或后面)放置一个新值
对于(int i=0;i<10;i++)
数字。推回(i);
//确定数组的大小

coutsizeof
方法是处理未作为参数接收的数组的正确方法。作为参数发送到函数的数组被视为指针,因此
sizeof
将返回指针的大小,而不是数组的大小

因此,在函数内部,此方法不起作用。相反,始终传递一个附加参数
size\t size
,指示数组中的元素数

int a[17];
size_t n = sizeof(a) / sizeof(a[0]);
测试:

输出(在32位windows操作系统中):


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

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

如果你真的想这样做来传递你的数组,我建议实现一个结构来存储一个指向你想要的数组类型的指针和一个表示数组大小的整数。然后你可以把它传递给你的函数。只需将数组变量值(指向第一个元素的指针)分配给该指针。然后您可以转到
Array.arr[i]
获取第i个元素,并使用
Array.size
获取数组中的元素数

int a[17];
size_t n = sizeof(a) / sizeof(a[0]);
我为您提供了一些代码。它不是很有用,但是你可以用更多的特性来扩展它。不过,老实说,如果这些是你想要的,你应该停止使用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;
}
/*绝对没有人应该使用此。。。
当你完成了它的实现时,你会希望你只是随便说说而已
函数的数组和大小*/
/*这是一个静态实现。您可以获得动态实现和
使用stdlib内存分配方法在main中剪切阵列,
但它的工作速度会慢得多,因为它会将您的阵列存储在
int array[10];
int sizeOfArray = sizeof(array)/sizeof(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;
}
#define ARRAY_SIZE(arr)     (sizeof(arr) / sizeof((arr)[0]) + must_be_array(arr))

#define ARRAY_SSIZE(arr)    ((ptrdiff_t)ARRAY_SIZE(arr))

#define ARRAY_BYTES(arr)    (sizeof(arr) + must_be_array(arr))

#define ARRAY_SBYTES(arr)   ((ssize_t)ARRAY_BYTES(arr))
#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)  __VA_OPT__(,)  __VA_ARGS__);\
                        char ISO_C_forbids_a_struct_with_no_members__;  \
                }                                                       \
        )                                                               \
)
#define must_be_array(arr)  must_be(is_array(arr), "Not a `[]` !")
void foo(ptrdiff_t nmemb, int arr[static nmemb])
{
        qsort(arr, nmemb, sizeof(arr[0]), cmp);
}
#define ARRAY_SIZE(arr)     (sizeof(arr) / sizeof((arr)[0]))
#define ARRAY_SSIZE(arr)    ((ptrdiff_t)ARRAY_SIZE(arr))
void foo(ptrdiff_t nmemb)
{
        char buf[nmemb];

        fgets(buf, ARRAY_SIZE(buf), stdin);
}

void bar(ptrdiff_t nmemb)
{
        int arr[nmemb];

        for (ptrdiff_t i = 0; i < ARRAY_SSIZE(arr); i++)
                arr[i] = i;
}
void foo(ptrdiff_t nmemb, char buf[nmemb])
{

        fgets(buf, nmemb, stdin);
}

void bar(ptrdiff_t nmemb, int arr[nmemb])
{

        for (ptrdiff_t i = 0; i < nmemb; i++)
                arr[i] = i;
}
#define ARRAY_BYTES(arr)        (sizeof((arr)[0]) * ARRAY_SIZE(arr))
#define ARRAY_SBYTES(arr)   ((ssize_t)ARRAY_BYTES(arr))
void foo(ptrdiff_t nmemb)
{
        int arr[nmemb];

        memset(arr, 0, ARRAY_BYTES(arr));
}
void foo(ptrdiff_t nmemb, int arr[nmemb])
{

        memset(arr, 0, sizeof(arr[0]) * nmemb);
}
#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), "Not a `[]` !")

#define ARRAY_SIZE(arr)         (                                       \
{                                                                       \
        Static_assert_array(arr);                                       \
        sizeof(arr) / sizeof((arr)[0]);                                 \
}                                                                       \
)
#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), "Not a `[]` !")

#define ARRAY_SIZE(arr)         (                                       \
{                                                                       \
        Static_assert_array(arr);                                       \
        __arraycount((arr));                                            \
}                                                                       \
)

#define ARRAY_SSIZE(arr)        ((ptrdiff_t)ARRAY_SIZE(arr))
#define ARRAY_BYTES(arr)        (sizeof((arr)[0]) * ARRAY_SIZE(arr))
#define ARRAY_SBYTES(arr)       ((ssize_t)ARRAY_BYTES(arr))
#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)  __VA_OPT__(,)  __VA_ARGS__);\
                        char ISO_C_forbids_a_struct_with_no_members__;  \
                }                                                       \
        )                                                               \
)
#define must_be_array(arr)      must_be(is_array(arr), "Not a `[]` !")

#define ARRAY_SIZE(arr)         (__arraycount((arr)) + must_be_array(arr))
#define ARRAY_SSIZE(arr)        ((ptrdiff_t)ARRAY_SIZE(arr))
#define ARRAY_BYTES(arr)        (sizeof(arr) + must_be_array(arr))
#define ARRAY_SBYTES(arr)       ((ssize_t)ARRAY_BYTES(arr))
size_t size = sizeof(a) / sizeof(*a);
sizeof(a) / sizeof (a[0])
sizeof(a)
char a[10];
size_t length = sizeof(a);