迭代通过null终止的数组

时间:2014-07-03 11:51:48

标签: c pointers

我想迭代通过null终止的结构数组。 虽然循环工作正常,但当我尝试访问任何结构字段时,我得到“段错误”作为响应。我做错了什么?

PS我知道可以确定数组大小并使用简单的“for”构造。我只想弄清楚问题的根源。

PSS好的,如果数组初始化错误 - 如何正确执行?

#include <stdio.h> 
#include <stdlib.h> 

typedef struct demo
{
    int a;
    int b;
    int c;
} demo;

demo * fieldDefinitions[] =
{
  { 1 , 1,  1 },
  { 2 , 2,  2 },
  { 3 , 3,  3 },
  NULL
};

int main()
{
    demo ** ptr = fieldDefinitions;
    printf( "Array: %d \n", &fieldDefinitions );

    while ( *ptr != NULL )
    {
        printf( "ptr: %d \n", ptr );
        printf( "ptr: %d \n", (**ptr).a ); // <--- problem here
        ptr++;
    }

    return 0;
} 

3 个答案:

答案 0 :(得分:6)

正如其他人已经指出的那样:听取你的编译器,一个符合标准的实现必须抱怨:

demo * fieldDefinitions[] =
{
    { 1 , 1,  1 }, // <-- note that this is not a pointer to a demo.
    { 2 , 2,  2 },
    { 3 , 3,  3 },
    NULL
};

另外,使用p作为指针的printf格式说明符,而不是d(用于整数类型)。

您需要指向demo个对象,因此需要以某种方式创建这些对象,以便我们可以获取其地址。 C99添加了一个名为复合文字的功能(看起来有点类似于演员,但是,它们是不同的)创建未命名的对象:

#include <stdio.h> 
#include <stdlib.h> 

typedef struct demo
{
    int a;
    int b;
    int c;
} demo;

demo * fieldDefinitions[] =
{
    &(demo){ 1 , 1,  1 },
    &(demo){ 2 , 2,  2 },
    &(demo){ 3 , 3,  3 },
    NULL
};

int main()
{
    demo ** ptr = fieldDefinitions;
    printf( "Array: %p \n", (void *)&fieldDefinitions );

    for ( ; *ptr != NULL; ptr++ )
    {
        printf( "ptr: %p\n", (void *)ptr); // I'm not sure, what you really wanted ...
        printf( "*ptr: %p\n", (void *)*ptr ); // ... but I think you meant this
        printf( "ptr: %d\n", (*ptr)->a ); // or (**ptr).a, whatever you prefer
    }

    return 0;
}

通过复合文字创建的对象的生命周期是封闭块或静态的生命周期(如果在初始化程序中用于具有静态存储持续时间的标识符)(如本例所示)。

HTH

答案 1 :(得分:2)

demo * fieldDefinitions[ 4 ] =
{
  { 1 , 1,  1 },
  { 2 , 2,  2 },
  { 3 , 3,  3 },
  NULL
};

你不能这样做,因为你做不到:

int *arr[] = {1, 2, 3, NULL};

向你发出警告:

initialization makes pointer from integer without a cast

如果你想使用指针运算,你可以这样做:

#include <stdio.h> 
#include <stdlib.h> 

typedef struct demo
{
    int a;
    int b;
    int c;
} demo;

demo fieldDefinitions[] = {
    { 1 , 1,  1 },
    { 2 , 2,  2 },
    { 3 , 3,  3 },
};

int main(void)
{
    demo *ptr = fieldDefinitions;
    demo *end = &fieldDefinitions[sizeof(fieldDefinitions) / sizeof(fieldDefinitions[0]) - 1];

    do {
        printf( "ptr: %p \n", (void *)ptr);
        printf( "ptr: %d \n", ptr->a);
    } while (ptr++ < end);

    return 0;
} 

答案 2 :(得分:0)

demo * fieldDefinitions[] =
{
  { 1 , 1,  1 },
  { 2 , 2,  2 },
  { 3 , 3,  3 },
  NULL
};

您声称​​ fieldDefinitions 将是一个演示对象指针数组,而是您自己提供对象。这是初始化结构数组的方式(最后除了NULL)。如果您的阵列是静态的,那么我建议创建具有已知大小的demo阵列,例如

unsigned const int fieldDefinitions_size = 3;
demo fieldDefinitions_arr[fieldDefinitions_size] = {
    {1,1,1},
    {2,2,2},
    {3,3,3}
};

使用 fieldDefinitions_size 进行迭代。

或者如果你坚持使用演示指针数组,那么你可以为每个 demo 对象单独分配内存,并为 fieldDefinitions 数组分配地址。 This线程将非常有用。