C中结构内的字符串数组,无需分配

Posted

技术标签:

【中文标题】C中结构内的字符串数组,无需分配【英文标题】:array of strings within a struct in C without allocating 【发布时间】:2021-08-31 08:00:38 【问题描述】:

我想用一个字符串数组初始化一个结构而不进行动态分配。可能吗? 我曾想过这样的事情,但它不起作用:

struct st_request 
int GRID;
char NAME[15];
char (*PARAM)[15];
;
typedef struct st_request request;

request myrequest = 
 .GRID=1,
 .NAME="GLOB",
 .PARAM="RR1","RR3"

一个想法?感谢您的解决方案。

【问题讨论】:

PARAM 不是数组。它是一个指针。 试试[]而不是[15] @Ole 实现什么,得到一个编译器错误? 【参考方案1】:

有几种可能的变体,这里有两个:

struct s

    char params1[32][64]; // 32 strings each with maximum length of 64 characters

///////////////////////////////////////////////////

    char buffer[1024]; // byte buffer for individual strings
    char* params2[32]; // 32 pointers you can let point
                       // to arbitrary positions into buffer
;

如果您不总是使用所有参数,您可能需要将 size_t numparams; 添加到上述两种解决方案中。

复制时,第一个变体很好,第二个变体你必须重新调整指针:

dest.params2[n] = dest.buffer + (source.params2[n] - source.buffer);

使用第二种变体,不要忘记为终止空指针留出空间。带有数据的结构可能如下所示:

buffer     == "hello world\0hola mundo\0salut monde\0\0\0 ...";
// first parameter  c a n  be implicit: buffer
params2[0] == buffer + 12;
params2[1] == buffer + 23;
numParams  == 3; // including the implicit parameter

或者,第一个参数可能总是指向缓冲区的开始,然后您可以一致地访问所有参数,而无需像 p = n == 0 ? buffer : params[n-1] 这样的任何特殊处理。

初始化可能如下所示:

struct s g_s =

        .params1 =
        
                "hello world",
                "hola mundo",
                "salut monde",
        ,

        .buffer = "hello world\0hola mundo\0salut monde",
        .params2 =
        
                g_s.buffer + 12,
                g_s.buffer + 23,
        ,

        .numParams = 3,

;

不幸的是,您需要自己计算第二个变体的偏移量(您可能会编写一个帮助程序 script 为您执行此操作...)。

【讨论】:

感谢您的回答。 不知道能不能用 sizeof(g_s.params2) / sizeof(g_s.params2[0] 得到数组长度? @user2030243 当然可以,就像任何数组一样——当然,只要它还没有衰减为指针(例如,sizeof(g_s.params1)/sizeof(*g_s.params1) 用于另一个数组或sizeof(*g_s.params1)/sizeof(**g_s.params1) 用于子-数组)。但是,如果您想以这种方式替换 numParams 成员,那么您就不走运了除非所有这些参数都总是在使用中(sizeof-trick 为您提供总数可用容量,numParams 实际使用的插槽数)。【参考方案2】:

线

char (*PARAM)[15];

声明一个指针PARAM,它指向一个char[15]类型的数组,即指向一个有15个元素的数组,其中每个元素的类型为char

你可能想写

char *PARAM[15];

它声明了一个包含 15 个指针的数组,其中每个指针的类型为 char*。与前面提到的指向整个数组的指针相比,这 15 个指针只指向一个字符。

在 C 中,处理字符串时,通常使用指向以空字符结尾的字符序列的第一个字符的指针。指向整个数组的指针通常只用在多维数组的上下文中,因为在多维数组中计算偏移量需要被引用对象的大小信息。

注意,变量名不能大写。这通常是为常量保留的。

另外,您的代码的最后一行缺少;

【讨论】:

char *PARAM[15] 确实与 OP 提供的初始化程序兼容,但我不太确定这是他们真正想要的。我认为 OP 的 NAME*PARAMS 都以长度 15 声明可能很重要——也就是说,尽管他们写了“字符串数组”,但他们实际上的意思是“char 数组的数组”。但是,如果不是,那么如果他们打算按所示使用它,那么声明 const char *PARAM[15] 会更好。 char * PARAM[15] 可以工作(也可以使用 const)。谢谢。 不知能否用 sizeof(myRequest.PARAM) / sizeof(myRequest.PARAM[0] 得到数组长度? @user2030243: 我不认为sizeof(myRequest.PARAM) 是你想要的,因为这会给你数组PARAM 的大小,即15 个指针的大小,即120 字节,假设每个指针有 8 个字节(64 位)。我也不认为sizeof(myRequest.PARAM[0]) 是您想要的,因为它总是会给您单个指针的大小(8 个字节)。如果你想要字符串的实际长度,你必须使用strlen。如果您想要指向的数组的实际大小,即可以存储的最大字符数,那么您必须通过其他方式记住这一点。 好的,我想我必须将初始化期间存储的字符串数量存储在其他地方(即两个:RR1 和 RR3)【参考方案3】:

您可以尝试以下方法:

#define PARAM_SIZE 20;

struct st_request 
int GRID;
char NAME[15];
char PARAM[15*PARAM_SIZE];
;

request myrequest = 
 .GRID=1,
 .NAME="GLOB"


strcpy (&myrequest.PARAM[0*PARAM_SIZE], "RR1");
strcpy (&myrequest.PARAM[1*PARAM_SIZE], "RR3");

【讨论】:

以上是关于C中结构内的字符串数组,无需分配的主要内容,如果未能解决你的问题,请参考以下文章

数据结构与算法之数组

在字符串和结构数组中查找动态内存分配错误

malloc动态分配字符串数组“ 一个月内的提醒”

C语言结构体数组排序

在C中初始化字符串数组

c语言数组在内存中是怎么分配的?