简体   繁体   中英

char* truncated when assigned as struct member

I have a structure with the following 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. It'ld be too easy that you actually don't have zeroes after that, so that printf() doesn't work. 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

When assigning dereferenced char pointer to array, only first char is read

command is a pointer to char .

It is initialized with a string constant, which means that it is a pointer to the first character of that string, ie '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' .

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".

C90 says, in section 6.5.7 "Initialization"

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' .

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' .

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_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....

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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