如何在编译时获取初始化列表中的元素总数?

时间:2015-09-24 22:04:31

标签: c arrays struct

假设我已定义具有一个数组的结构。我在主程序中初始化了数组。但是现在我怎样才能找到数组中初始化的元素数量。我也创建了struct对象的数组。

#include <stdio.h>
#define noOfArray 10
struct Arrays
{
   int data[100];
   int size;
   int discardArray; //1 for true and 0 for false
};

void main( )
{    
   int size=0,i,j;

   struct Arrays arrayObject[10]={
        {{1,2,3,4}},
        {{1,3,5,6,3,4}},
        {{1,6,7,8,9,10,11,43,4}}
   };

size = sizeof arrayObject[0].data / sizeof arrayObject[0].data[0];
}

这个大小给了我100但我需要arrayObject [0] .data中存在的元素总数。

使用

尝试了事件
int arr[] = {1,2,3,4};
struct Arrays arrayObject[10] = {
    {arr,sizeof arr/sizeof arr[0]},
    {{1,3,5,6,3,4}},
    {{1,6,7,8,9,10,11,43,4}}
};

但是这不会编译:接近sizeof start它表示无效的初始化。

我真正想要的是存储n数组的任何方法,其中第一个数组可以与其他数组进行比较。数组中预设的元素具有不同的大小。

3 个答案:

答案 0 :(得分:2)

您的编译时错误是您尝试使用arr作为初始化arrayObject的值。但是,C仅允许在编译时已知的值用作初始值设定项。 arr是堆栈上的地址,在执行时间之前不会被人知道,因此它不能用作初始化程序。

您应该能够初始化为sizeof arr/sizeof arr[0],这将是数组中元素的数量,但您无法初始化为arr, sizeof arr/sizeof arr[0]

答案 1 :(得分:2)

您尝试做的事情的缺陷是您尝试区分初始化元素与未初始化元素的方式。

int a[100] = { 1, 2 };

初始化所有100个元素。初始化列表中未提及的元素初始化为零。您无法使用sizeof(a)/sizeof(a[0])来计算已初始化的元素。

可以做类似

的事情
#define INIT_LIST { 1, 2, 111}  // 257
#define ASIZE 100

int big_array[ASIZE] = INIT_LIST;


// this works with gcc -O1 / -Og, but dummy is there in the object file at -O0
static const char dummy[] = INIT_LIST;
int initialized_count = sizeof(dummy);  // sizeof(char) is guaranteed to be 1, so no divisor is needed.

// Or even better, no dummy array in the object file even with -O0:
int initialized_count2 = sizeof((int[])INIT_LIST)/sizeof(int);
// This also avoids compiler warnings when constants in the initializer list don't fit in a char.

// in macro form: Be careful with very large initializers; this could compile slowly if you used it all over the place.
#define COUNT_INITLIST (x) (sizeof((long[])x)/sizeof(long))


// Even with optimization on, this will also compile away to just returning a constant
int initialized_in_big_array() {
    // without optimization: dummy2 is there in the object file
    // but still not copied to the stack, because of const
    const char dummy2[] = INIT_LIST;
    return sizeof(dummy2);
}

即使在-Og这样的低优化级别,结果也是如此,编译器完全避免发出未使用的数组。因此不需要内联函数。 Jens Gustedt关于转换初始化列表的建议,所以从来没有一个数组,是最好的。

答案 2 :(得分:1)

一种解决方案是将sentinel value放在数组的末尾。例如,如果数组中通常不允许使用负值,则可以使用值-1标记数组的结尾。

struct Arrays arrayObject[10]={
    {{1,2,3,4,-1}},
    {{1,3,5,6,3,4,-1}},
    {{1,6,7,8,9,10,11,43,4,-1}}
};

这允许您使用简单的for循环来计算数组中有效条目的数量。