Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 在结构中存储多维数组_C_String_Pointers_Multidimensional Array_Struct - Fatal编程技术网

C 在结构中存储多维数组

C 在结构中存储多维数组,c,string,pointers,multidimensional-array,struct,C,String,Pointers,Multidimensional Array,Struct,我有一个二维数组,其中第一个维度的长度可变,但第二个维度是固定的。现在,在函数调用中,我可以执行类似于char foo[][3]的操作,但是结构中的相应定义是什么 因此,在示例代码中,我希望它将每个字符串打印成一行,但正如预期的那样,它将存储的指针视为一维数组 #include <stdlib.h> #include <stdio.h> struct payload_s { size_t length; char *text; }; typedef s

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

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

#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]);
}
当函数实际定义为
payload*create\u payload(char text[][3],size\u t length)
时,我可以消除此警告,但几行之后出现警告,行为没有改变:

strut.c: In function ‘create_payload’:
strut.c:16:13: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
     p->text = text;
             ^
手动按每个值的长度递增指针的唯一解决方案是什么?

使用:

char (*text)[3];
而不是:

char *
因为这里需要的是指向2D数组的指针,而不是指向单个
char
的指针。阅读更多信息

当然,建议对维度使用define或类似的东西,而不是像我的示例中那样硬编码的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]);
}

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

此行:

static char some_text[4][3] = {"Ab\0", "Cd\0", "Ef\0", "Gh\0"};
正在尝试使用每个条目中4个字节的值初始化每个条目中3个字节的数组

注意:“AB\0”是4个字节,因为声明一个字符数组总是在数组的末尾附加一个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]);
}

您正在使用不兼容的指针,这些指针不能相互隐式转换

字符数组
某些文本
声明相似

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

您有一个概念上的问题:您不能将四个
char
数组(
{“Ab\0”、“Cd\0”、“Ef\0”、“Gh\0”};
此处)仅存储在一个
char
指针(
char*text;
此处)下,至少不能以正常的方式存储。编译器警告是对这个问题的提示。这基本上就是我要问的:我还可以如何将它们存储在结构中?OT:
“Ab\0”
在内部表示为
{'a'、'b'、'\0'、'\0'}
,因此您可能不想显式地放置
'\0'
。将成员
char*text
更改为
char(*)[3]
以及:使其成为
char(*text)[3]
。调用任何堆内存分配函数:(malloc、calloc、realloc)时,始终检查(!=NULL)返回值以确保操作成功。我几乎得到了它,但括号放错了(使用了
*(text[3])
)。感谢您的评论,虽然这段代码只是为了摘录我的问题。我知道@xZise,这就是我最后一句话的原因!我必须自己查找,这就是为什么我在写这个答案之前把我检查过的答案链接到你的原因!:)顺便提一下,这个问题问得很好,让人耳目一新!
0: Ab
1: Cd
2: Ef
3: Gh
static char some_text[4][3] = {"Ab\0", "Cd\0", "Ef\0", "Gh\0"};
#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