#include <stdio.h>
#include <string.h>
int main()
{
typedef struct recmd_hd_t_ {
unsigned short magic; /*magic(0X8D5D)*/
unsigned int cmd_id; /*命令号*/
unsigned int data_len; /*数据长度 pdata的长度*/
int result_value; /*返回状态*/
char result_msg[128]; /*返回消息为字符串log*/
char pdata[0]; /*返回数据,柔性数组*/
}recmd_hd_t;
recmd_hd_t recmd_hd_s = { 0 };
recmd_hd_s.magic = 0X8D5D;
recmd_hd_s.cmd_id = 0X51;
recmd_hd_s.data_len = 0;
recmd_hd_s.result_value = 0;
strcpy(recmd_hd_s.result_msg, "led switch ok");
printf("51 led switch ok %s",(char*)&recmd_hd_s);
}
一段代码,牵扯出三个问题:
编译会不会报错?
不会
什么是柔性数组?
结构体的最后一个成员可以是一个大小不确定的数组,这个数组就叫做柔性数组
;
https://xie.infoq.cn/article/6f1da2c291b1fb5f361dcb87d
https://juejin.cn/post/7239715688141946936
https://developer.aliyun.com/article/1241746
recmd_hd_t recmd_hd_s = { 0 };这样初始化正确吗?
唯一没有初始化到柔性数组
加一句recmd_hd_s.pdata = {0};试试再次编译
直接报错:
main.c: In function ‘main’:
main.c:14:20: error: expected expression before ‘{’ token
recmd_hd_s.pdata = {0};
那柔性数组应该怎么初始化?
在 C 语言中,不能像这样直接使用{0}
来初始化结构体中的柔性数组成员。柔性数组必须在分配了足够的内存空间后,通过其他方式(如memset
等函数)或者逐个元素赋值来初始化其内容。
printf打印什么?
51 led switch ok ],去掉柔性数组还是会打印这句话
%s打印的是字符串,直到遇到“\0”才结束,而这个结构体不存在“\0”
那我把柔性数组初始化试试?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
typedef struct recmd_hd_t_ {
unsigned short magic; /*magic(0X8D5D)*/
unsigned int cmd_id; /*命令号*/
unsigned int data_len; /*数据长度 pdata的长度*/
int result_value; /*返回状态*/
char result_msg[128]; /*返回消息为字符串log*/
char pdata[]; /*返回数据,柔性数组*/
}recmd_hd_t;
recmd_hd_t recmd_hd_s = { 0 };
recmd_hd_t* ps = (recmd_hd_t*)malloc(sizeof(recmd_hd_t) + 6* sizeof(char));
//recmd_hd_s.pdata = {0};
recmd_hd_s.magic = 0X8D5D;
recmd_hd_s.cmd_id = 0X51;
recmd_hd_s.data_len = 0;
recmd_hd_s.result_value = 0;
strcpy(recmd_hd_s.result_msg, "led switch ok");
int i = 0;
for (i = 0; i < 5; i++)
{
ps->pdata[i] = i;
}
ps->pdata[6] = '\0';
//printf("size = %d\n",sizeof(recmd_hd_s.pdata));
printf("51 led switch ok %s",(char *)&recmd_hd_s);
free(ps);
ps = NULL;
}
还是打印51 led switch ok ]
-
printf("51 led switch ok %s",(char *)&recmd_hd_s);
这种打印方式是错误的。你不能直接将结构体的地址强制转换为char*
并期望以字符串的方式打印。结构体中除了pdata
之外的其他成员可能包含不可打印的字符,并且这种方式也不能正确地识别pdata
的结束位置。 -
虽然给
pdata[6]
赋值为'\0'
作为结束符,但这并不能保证整个结构体被正确地解释为字符串。
要正确打印结构体中的信息,可以分别打印各个成员,或者使用更合适的方式来处理和打印柔性数组的内
附:
gcc -S main.c可以生成汇编代码main.s
char test[] = {0};
不是不定长数组,它是一个定长数组,只是这个数组被初始化为只有一个元素且该元素值为 0。
char *test = {0};
不是不定长数组,并且这种初始化方式严格来说在 C 语言中是错误的,但在某些编译器中可能不会报编译错误而是给出警告。
正确的初始化方式应该是:
char *test = NULL;
或者char *test = 0;
表示将指针初始化为空指针。char *test = "some string";
表示将指针指向一个字符串常量。
原因是{0}
这种初始化方式不是指针的合法初始化语法,因为它试图用一个初始化列表来初始化一个指针,而指针应该被初始化为一个地址值(比如另一个变量的地址、动态分配的内存地址或者字符串常量的地址等)。