简体   繁体   English

将多维数组存储在struct中

[英]Store multidimensional array in struct

I have a two dimensional array where the first dimension has a variable length but the second dimension is fixed. 我有一个二维数组,其中第一维的长度可变,但是第二维是固定的。 Now in a function call I could do something like char foo[][3] but what is the corresponding definition in a struct ? 现在,在函数调用中,我可以执行类似char foo[][3]但是struct的相应定义是什么?

So in the example code I expected it to print each string in a line, but as expected it treats the stored pointer as a single dimensional array. 因此,在示例代码中,我希望它能将一行中的每个字符串都打印出来,但是正如预期的那样,它将存储的指针视为一维数组。

#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]);
}

I mainly noticed this because of a warning: 我主要是因为警告而注意到这一点:

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)
          ^~~~~~~~~~~~~~

I can get rid of this warning when the function is actually defined as payload* create_payload(char text[][3], size_t length) , but then there is a warning a few lines later and the behavior didn't change: 当函数实际上定义为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;
             ^

Is the only solution to manually increment the pointer by the length of each value? 手动将指针增加每个值的长度是唯一的解决方案吗?

Use: 采用:

char (*text)[3];

instead of: 代替:

char *

since what you want here is a pointer to your 2D array, not a pointer to single char . 因为您想要的是指向2D数组的指针,而不是单个char的指针。 Read more in C pointer to two dimensional array . C指向二维数组的指针中阅读更多内容。

Of course, it is suggested to use a define, or something similar for your dimension, instead of the hardcoded 3, like in my example. 当然,建议像我的示例一样,使用定义或类似的尺寸来代替维3。


Min. 闵。 Example: 例:

#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]);
}

Output: 输出:

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

PS - Check what malloc() returns, to see if the memory was actually allocated (of course on real code, not in min. egs). PS-检查malloc()返回什么,以查看是否实际分配了内存(当然是在实际代码上,而不是在最小例中)。

this line: 这行:

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

is trying to initialize an array of 3 bytes in each entry with values that are 4 bytes in each entry. 正在尝试初始化每个条目中3个字节的数组,并在每个条目中使用4个字节的值。

note: "AB\\0" is 4 bytes because declaring a char array Always appends a NUL byte to the end of the array. 注意:“ AB \\ 0”为4个字节,因为声明一个char数组始终将NUL字节附加到该数组的末尾。

Suggest: 建议:

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

The call to printf() contains several errors, which your compiler should have told you about. printf()的调用包含一些错误,您的编译器应已将这些错误告知您。

The field: char *text; 字段: char *text; is actually pointing to a 2D array, so should be declared accordingly. 实际上指向2D数组,因此应相应声明。

Need to perform error checking on the call to malloc() . 需要对malloc()的调用执行错误检查。

here is a version of the code, will all (reasonable) corrections applied. 这是代码的一个版本,将应用所有(合理的)更正。

#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]);
}

The result of the above code is: 上面的代码的结果是:

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

You are using incompatible pointers that can not be converted implicitly to each other. 您正在使用不能相互隐式转换的不兼容指针。

Character array some_text declared like 字符数组some_text声明为

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

when it is used in expression as for example used as an argument it is implicitly converted to pointer to its first element and has type char ( * )[3] . 当在表达式中使用它(例如用作参数)时,它隐式转换为指向其第一个元素的指针,并且类型为char ( * )[3] It si not the same as pointer of type char * . 它与char *类型的指针不同。

It looks like you need a structure with a flexible array. 看起来您需要具有灵活数组的结构。

Here is a demonstrative program that shows how such a structure can be used. 这是一个演示程序,显示了如何使用这种结构。

#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;
}

Its output is 它的输出是

Ab Cd Ef Gh 
Bb Dd Ff Hh Jj 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM