在struct中存储多维数组

时间:2016-11-16 17:13:38

标签: c string pointers multidimensional-array struct

我有一个二维数组,其中第一个维度具有可变长度但第二个维度是固定的。现在在函数调用中,我可以执行char foo[][3]之类的操作,但struct中的相应定义是什么?

因此在示例代码中我希望它能够在一行中打印每个字符串,但正如预期的那样,它将存储的指针视为一维数组。

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

struct payload_s {
    size_t length;
    char *text;
};

typedef struct payload_s payload;

static char some_text[4][3] = {"Ab", "Cd", "Ef", "Gh"};

payload* create_payload(char *text, size_t length)
{
    payload *p = malloc(sizeof *p);
    p->text = text;
    p->length = length;
    return p;
}

int main()
{
    payload *p = create_payload(some_text, 4);
    for (size_t i = 0; i < p->length; ++i)
        printf("%zu: %s\n", i, &p->text[i]);
}

由于警告,我主要注意到了这一点:

strut.c: In function ‘main’:
strut.c:23:33: warning: passing argument 1 of ‘create_payload’ from incompatible pointer type [-Wincompatible-pointer-types]
     payload *p = create_payload(some_text, 4);
                                 ^~~~~~~~~
strut.c:13:10: note: expected ‘char *’ but argument is of type ‘char (*)[3]’
 payload* create_payload(char *text, size_t length)
          ^~~~~~~~~~~~~~

当函数实际定义为payload* create_payload(char text[][3], size_t length)时,我可以摆脱这个警告,但之后会有几行警告并且行为没有改变:

strut.c: In function ‘create_payload’:
strut.c:16:13: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
     p->text = text;
             ^

是唯一的手动递增指针的方法是每个值的长度吗?

3 个答案:

答案 0 :(得分:1)

使用:

char (*text)[3];

而不是:

char *

因为你想要的是指向你的2D数组的指针,而不是指向单char的指针。阅读C pointer to two dimensional array中的更多内容。

当然,建议使用定义或类似的维度,而不是硬编码3,就像我的例子一样。

最小。例如:

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

#define M 3

struct payload_s {
    size_t length;
    char (*text)[M]; // change the member!
};

typedef struct payload_s payload;

// not need for null terminators in the strings,
// it will be placed automatically
static char some_text[4][M] = {"Ab", "Cd", "Ef", "Gh"};

// change the prototype as well
payload* create_payload(char (*text)[M], size_t length)
{
    payload *p = malloc(sizeof *p);
    p->text = text;
    p->length = length;
    return p;
}

int main()
{
    payload *p = create_payload(some_text, 4);
    for (size_t i = 0; i < p->length; ++i)
        // no need to print the address now
        // also 'zu' should be used for 'size_t'
        printf("%zu: %s\n", i, p->text[i]);
}

输出:

Georgioss-MacBook-Pro:~ gsamaras$ gcc -Wall main.c 
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out 
0: Ab
1: Cd
2: Ef
3: Gh

PS - 检查malloc()返回的内容,看看内存是否实际分配(当然是真实代码,而不是最小分数)。

答案 1 :(得分:1)

这一行:

static char some_text[4][3] = {"Ab\0", "Cd\0", "Ef\0", "Gh\0"};

尝试在每个条目中初始化一个3个字节的数组,每个条目中的值为4个字节。

注意:&#34; AB \ 0&#34;是4个字节,因为声明一个char数组总是将一个NUL字节附加到数组的末尾。

推荐:

static char some_text[4][3] = {"Ab", "Cd", "Ef", "Gh"};

printf()的调用包含几个错误,编译器应该告诉你这些错误。

字段:char *text;实际上指向2D数组,因此应该相应地声明。

需要对malloc()的调用执行错误检查。

这是代码的一个版本,将应用所有(合理的)更正。

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

struct payload_s 
{
    size_t length;
    char **text;
};


static char *some_text[] = {"Ab", "Cd", "Ef", "Gh"};

struct payload_s* create_payload(char **text, size_t length)
{
    payload *p = malloc(sizeof (struct payload_s));
    if( !p )
    {
        perror( "malloc for instance of payload failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, malloc successful

    p->text = text;
    p->length = length;
    return p;
}

int main( void )
{
    //payload *p = create_payload(some_text, 4);
    payload *p = create_payload(some_text, sizeof(some_text) / sizeof( *some_text ) );
    for (size_t i = 0; i < p->length; ++i)
        printf("%lu: %s\n", i, p->text[i]);
}

上述代码的结果是:

0: Ab
1: Cd
2: Ef
3: Gh

答案 2 :(得分:0)

您使用的是不兼容的指针,这些指针无法相互隐式转换。

字符数组some_text声明为

static char some_text[4][3] = {"Ab\0", "Cd\0", "Ef\0", "Gh\0"};

当它在表达式中用作例如用作参数时,它被隐式转换为指向其第一个元素的指针,并且具有类型char ( * )[3]。它与char *类型的指针不同。

看起来你需要一个具有灵活数组的结构。

这是一个演示程序,展示了如何使用这种结构。

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

#define N   3

struct payload_s 
{
    size_t length;
    char text[][N];
};

struct payload_s * create_payload( char( *text )[N], size_t length )
{
    struct payload_s *p = malloc( sizeof( struct payload_s ) + 
                                  length * sizeof( char[N] ) );

    p->length = length;

    for ( size_t i = 0; i < length; i++ ) strcpy( p->text[i], text[i] );

    return p;
}

void free_payload( struct payload_s *p )
{
    free( p );
}

int main(void) 
{
    char some_text[4][N] = {"Ab", "Cd", "Ef", "Gh"};
    char another_text[5][N] = {"Bb", "Dd", "Ff", "Hh", "Jj"};

    struct payload_s *p1 = create_payload( some_text, 
        sizeof( some_text ) / sizeof( *some_text ) );

    struct payload_s *p2 = create_payload( another_text, 
        sizeof( another_text ) / sizeof( *another_text ) );

    for ( size_t i = 0; i < p1->length; i++ )
    {
        printf( "%s ", p1->text[i] );
    }
    printf( "\n" );

    for ( size_t i = 0; i < p2->length; i++ )
    {
        printf( "%s ", p2->text[i] );
    }
    printf( "\n" );

    free_payload( p2 );
    free_payload( p1 );

    return 0;
}

它的输出是

Ab Cd Ef Gh 
Bb Dd Ff Hh Jj