C 如何计算数组的元素数

C 如何计算数组的元素数,c,arrays,counting,C,Arrays,Counting,我在测试代码时遇到了一个问题。我定义了一个宏来获取数组的元素数,如下所示: #定义数组大小(arr)sizeof(arr)/sizeof(arr[0]) 此宏可以很好地计算初始值设定项与存储容量匹配的数组的元素数(例如,int-buf[]={1,2,3};),但对于声明为:int-buf[20]={1,2,3}的数组,效果不是很好 现在我知道像这样计算数组元素是很容易的,但是大量的元素呢?你怎么算?你知道,数数可能是个杀手 考虑以下代码: #include <stdio.h> #in

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

#定义数组大小(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);
}
#包括
#包括
#定义数组大小(arr)sizeof(arr)/sizeof(arr[0])
void g_strcat(void*_Dst、size_t dstSize、size_t字节、const void*_Src、size_t srcSize);
内部主(空)
{
int-dst[20]={1,2,3};
int src[]={4,5,6};
size_t dstSize=3;//dstSize=ARRAY_size(dst)不起作用
大小=数组大小(src);
g_strcat(dst、dstSize、sizeof(int)、src、srcSize);
大小n,newSize=dstSize+srcSize;
对于(n=0;n
您的宏工作正常。声明:

int dst[20] = { 1,2,3 };
在堆栈内存中创建以下内容:

|1|2|3|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
即使仅使用前三个值初始化,数组大小仍为20

关于评论中的问题:我将如何连接到数组?数组必须足够大以容纳另一个字符串:

如果使用字符串(而不是数字数组),则使用字符串函数
int len=strlen(字符串)
可用于在连接之前测试字符串变量的现有用法

sizeof
宏不同,
strlen
是一个在字符数组中查找第一个空字符的函数:

char string[20] = {"yes"};
在内存中创建以下内容:

|y|e|s|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
strlen
string
的地址开始计数字符,直到遇到第一个空字符。(或0):

然后可以使用strncat(string、newStr、count)
将指定数量的字符count连接到已知容量的字符串,从而避免缓冲区溢出


请记住,例如,size==20的字符串变量仅限于包含长度==19的字符串。必须为空字符保留第20个位置。

如果我们可以假设最后一个初始化的元素不是零(因为这与隐式初始化为零没有区别):

如果您想以不同的方式计算这两种情况,那么您就完全不走运了(除非您使用Clang或GCC-XML或其他方式解析代码):


以上两种方法都将给出
3
,对此无能为力。

如果只部分初始化一个基本数据类型列表(即
int
s的数组),其余元素将初始化为
0

C99标准6.7.8.21

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

在您的例子中,您试图确定初始值设定项列表的大小。我真的想不出一个有效的理由需要这样做,但您可以简单地检查元素何时开始一致地等于零。当然,如果您故意将元素设置为零,则此操作将失败

您编写的宏将正常工作(即:返回数组中的元素数),但如果在接受指向数组的指针作为参数的函数中使用该宏,则该宏将失败

尽管如此,您无法在任何有意义的意义上确定初始值设定项列表的大小,除非您这样做,将初始值设定项列表定义为宏:


代码清单

通过将一次性阵列放入新的块作用域,可以最大限度地减少内存浪费,即:


#包括
#定义列表{1,2,3}
内部主(空)
{
int i[20]=列表;
int initListSize=0;
{
int t[]=列表;
initListSize=sizeof(t)/sizeof(int);
}
printf(“t中的元素:%d\n”,initListSize);
返回0;
}


这会将临时阵列的存储寿命限制在大括号之间的狭窄范围内。同样,我可以看到这可能是一个有用的实验,但我看不到这会进入生产代码。

如果要确定数组的初始值设定项数量,请声明一个数组来保存初始值设定项元素,并在其上应用宏
array\u SIZE()
。然后使用
memcpy()
将初始值设定项复制到
dst[20]
数组

现在您可以轻松获得元素的数量

#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], src[] = { 4,5,6 };
    int initializer_list[] = { 1,2,3 };

    size_t init_size = ARRAY_SIZE(initializer_list);
    memcpy(dst, initializer_list, init_size * sizeof(int));

    size_t dstSize = init_size;
    size_t srcSize = ARRAY_SIZE(src);

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

    size_t n;
    for (n = 0; n < dstSize; 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);
}
#包括
#包括
#定义数组大小(arr)sizeof(arr)/sizeof(arr[0])
void g_strcat(void*_Dst、size_t dstSize、size_t字节、const void*_Src、size_t srcSize);
内部主(空)
{
int-dst[20],src[]={4,5,6};
int初始值设定项_list[]={1,2,3};
size\t init\u size=数组大小(初始值设定项列表);
memcpy(dst、初始值设定项列表、初始值大小*sizeof(int));
大小=初始大小;
大小=数组大小(src);
g_strcat(dst、dstSize、sizeof(int)、src、srcSize);
dstSize+=srcSize;
尺寸;
对于(n=0;nsize_t trailing_zero_bytes(const void* data, size_t size) {
    for (; size > 0; size--) {
        if (((const char*)data)[size - 1] != 0) {
            break;
        }
    }
    return size;
}

#define ARRAY_SIZE(arr) \
    ((sizeof(arr) - trailing_zero_bytes(arr, sizeof(arr)) + sizeof(arr[0]) + 1) / sizeof(arr[0]))
int s1[5] = { 4,5,6 }; // 2 zeros implied
int s2[5] = { 4,5,6,0 }; // 1 zero implied
#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;
}
elements in i: 20
elements in t: 3
#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;
}
#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], src[] = { 4,5,6 };
    int initializer_list[] = { 1,2,3 };

    size_t init_size = ARRAY_SIZE(initializer_list);
    memcpy(dst, initializer_list, init_size * sizeof(int));

    size_t dstSize = init_size;
    size_t srcSize = ARRAY_SIZE(src);

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

    size_t n;
    for (n = 0; n < dstSize; 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);
}