如何计算数组的元素数量

mac*_*e_1 0 c arrays counting

我在测试代码时遇到了一个问题.我定义了一个宏来获取数组元素的数量,如下所示:

#define ARRAY_SIZE(arr) sizeof(arr) / sizeof(arr[0])

此宏可用于计算初始化程序与存储容量匹配的数组的元素数(例如int buf[] = {1,2,3};),但对于声明为:的数组不是很有效:int buf[20] = {1,2,3};

现在我知道像这样计算数组元素非常简单,但是大量的元素呢?你怎么算他们?你知道,计数可能是一个杀手!

请考虑以下代码:

#include <stdio.h>
#include <string.h>

#define ARRAY_SIZE(arr) sizeof(arr) / sizeof(arr[0])

void g_strcat(void *_Dst, size_t dstSize, size_t bytes, const void *_Src, size_t srcSize);

int main(void)
{
    int dst[20] = { 1,2,3 };
    int src[] = { 4,5,6 };

    size_t dstSize = 3; // dstSize = ARRAY_SIZE(dst) doesn't work
    size_t srcSize = ARRAY_SIZE(src);

    g_strcat(dst, dstSize, sizeof(int), src, srcSize);

    size_t n, newSize = dstSize + srcSize;
    for (n = 0; n < newSize; n++) {
        printf("%d ", dst[n]);
    }
    putchar('\n');
    return 0;
}

void g_strcat(void *_Dst, size_t dstSize, size_t bytes, const void *_Src, size_t srcSize)
{
    memcpy((char *)_Dst + (dstSize * bytes), _Src, srcSize * bytes);
}
Run Code Online (Sandbox Code Playgroud)

Clo*_*oud 5

如果仅部分初始化原始数据类型列表(即:ints 数组),则其余元素将初始化为0.

C99标准6.7.8.21

如果括号括起的列表中的初始值设定项少于聚合的元素或成员,或者用于初始化已知大小的数组的字符串文字中的字符数少于数组中的元素,则聚合的其余部分应为隐式初始化与具有静态存储持续时间的对象相同.

在您的情况下,您正在尝试确定初始化列表的大小.无法真正想到需要这样做的正当理由,但您可以简单地检查元素何时始终等于零.当然,如果您故意将元素设置为零,则会失败.

您编写的宏将正常工作(即:返回数组中元素的数量),但如果您在接受指向数组的指针作为参数的函数中使用它,它将失败,因为指针衰减会导致sizeof行为与人们的期望不同.

总而言之,您无法确定任何有意义的初始化列表的大小,除非您执行类似的操作,将初始化列表定义为宏:


代码清单


#include <stdio.h>
#define LIST    {1,2,3}

int main(void)
{
    int i[20] = LIST;
    int t[] = LIST;

    printf("elements in i: %d\n", sizeof(i)/sizeof(int));
    printf("elements in t: %d\n", sizeof(t)/sizeof(int));

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

样本输出


elements in i: 20
elements in t: 3
Run Code Online (Sandbox Code Playgroud)

您可以通过将丢弃数组放入新的块范围来最小化浪费的内存,即:


#include <stdio.h>
#define LIST    {1,2,3}

int main(void)
{
    int i[20] = LIST;
    int initListSize = 0;

    {
        int t[] = LIST;
        initListSize = sizeof(t) / sizeof(int);
    }

    printf("elements in t: %d\n", initListSize);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这会将临时阵列的存储寿命限制在大括号之间的狭窄范围内.同样,我可以看到这可能作为一个实验很有用,但是无法看到它在生产代码中找到它的方式.