简体   繁体   English

分配为结构成员时,char *被截断

[英]char* truncated when assigned as struct member

I have a structure with the following typedef. 我有一个具有以下typedef的结构。

typedef struct {
    short cmdLength;
    char cmdRequest[126];
} cmdRequest_t;

Then I have the following code in a main program. 然后我在主程序中有以下代码。

char *command = "d tcpip\0";
printf("command: %s\n", command);
size_t cmdLen = strlen(command);
printf("size: %zu\n", cmdLen);
cmdRequest_t cmdRequest = {(short) cmdLen, *command};
printf("size: %hi\n", cmdRequest.cmdLength);
printf("command: %s\n", cmdRequest.cmdRequest);

However, my output is as follows. 但是,我的输出如下。

command: d tcpip
size: 7
size: 7
command: d

The size is still correct, but for some reason the command is truncated to one letter. 大小仍然正确,但是由于某种原因该命令被截断为一个字母。 Any idea why this is the case? 知道为什么会这样吗?

What happens is that... 发生的是...

cmdRequest_t cmdRequest = {(short)cmdLen, *command};

This will initialize the member cmdRequest of cmdRequest as the dereferencing of command , or in other words, you'll end up with the first character in the string. 这将初始化成员cmdRequestcmdRequest 作为反引用command ,或者换句话说,你会在字符串中的第一个字符结束。 It'ld be too easy that you actually don't have zeroes after that, so that printf() doesn't work. 在那之后实际上没有零太容易了,以至于printf()不起作用。 You may perfectly have had output like this if you changed a few unrelated things... 如果您更改了一些不相关的内容,那么您可能会完美地拥有这样的输出...

command: d%$232!>~11cCV224
mysh: program received SIGSEGV, Segmentation fault

Do this instead... 改为这样做...

#include <string.h> 

cmdRequest_t cmdRequest;
cmdRequest.cmdLength = (short)cmdLen;
strncpy(cmdRequest.cmdRequest, command, sizeof(cmdRequest.cmdRequest) - 1);

Use strcpy instead of plain assignment 使用strcpy而不是普通分配

When assigning dereferenced char pointer to array, only first char is read 将取消引用的char指针分配给数组时,仅读取第一个char

command is a pointer to char . command是指向char的指针。

It is initialized with a string constant, which means that it is a pointer to the first character of that string, ie 'd' . 它使用字符串常量初始化,这意味着它是指向该字符串的第一个字符(即'd' )的指针。

If you dereference a pointer to char , you get, as a result, the single char to which it points, so *command evaluates to 'd' . 如果取消引用指向char的指针,结果将得到它指向的单个char ,因此*command值为'd'

You're initializing a structure, which is an "aggregate type" in C, and the second member of that structure is an array, which is also an "aggregate type". 您正在初始化一个结构,该结构在C语言中是“聚合类型”,而该结构的第二个成员是一个数组,它也是一个“聚合类型”。

C90 says, in section 6.5.7 "Initialization" C90在第6.5.7节“初始化”中说

Otherwise, the initializer for an object that has aggregate type shall be a brace-enclosed list of initializers for the members of the aggregate, written in increasing subscript or member order; 否则,具有聚合类型的对象的初始值设定项应是用大括号括起来的聚合成员的初始值设定项列表,并以递增的下标或成员顺序编写; and the initializer for an object that has union type shall be a brace-enclosed initializer for the first member of the union. 具有联合类型的对象的初始化程序应为联合的第一个成员的括号括起来的初始化程序。

If the aggregate contains members that are aggregates or unions, or if the first member of a union is an aggregate or union, the rules apply recursively to the subaggregates or contained unions. 如果聚合包含的成员是聚合或联合,或者联合的第一个成员是聚合或联合,则规则将递归应用于子聚合或包含的联合。 If the initializer of a subaggregate or contained union begins with a left brace, the initializers enclosed by that brace and its matching right brace initialize the members of the subaggregate or the first member of the contained union. 如果子集合或包含的并集的初始化程序以左括号开头,则该括号括起来的初始化程序及其匹配的右括号将初始化子集合的成员或所包含的并集的第一个成员。 Otherwise, only enough initializers from the list are taken to account for the members of the subaggregate or the first member of the contained union; 否则,仅使用列表中足够的初始化程序来考虑子集合的成员或所包含的并集的第一个成员; any remaining initializers are left to initialize the next member of the aggregate of which the current subaggregate or contained union is a part. 剩下的所有初始化程序都将初始化当前子聚合或所包含的并集所属的聚合的下一个成员。

Your initializer for the structure is enclosed in braces, so the initializers in that initializer initialize the structure members cmdLength and cmdRequest , in order, so it initializes cmdLength to cmdlen and initializes cmdRequest to 'd' . 结构的初始化程序包含在大括号中,因此该初始化程序中的初始化程序按顺序初始化结构成员cmdLengthcmdRequest ,以便将cmdLength初始化为cmdlen并将cmdRequest初始化为'd'

cmdRequest is an aggregate, but its initializer is not in braces, so "only enough initializers from the list are taken to account for the members of the subaggregate", so cmdRequest[0] is initialized to 'd' . cmdRequest是一个聚合,但其初始化程序不在大括号中,因此“仅使用列表中足够的初始化程序来考虑子cmdRequest[0]的成员”,因此cmdRequest[0]初始化为'd'

If you want to initialize cmdRequest to the array whose first member is pointed to by command , you'll have to do it with strcpy: 如果你想要初始化cmdRequest到其第一件被指向数组command ,你必须与strcpy的做到这一点:

cmdRequest_t cmdRequest;
cmdRequest.cmdLen = (short) cmdLen;
strcpy(cmdRequest.cmdRequest, command);

Sorry about that, but that's what you get when using a language in which strings aren't real data types.... 抱歉,但这就是使用字符串不是真实数据类型的语言时得到的。

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

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