2015-09-16 3 views
1

У меня есть структура со следующим typedef.char * усечен при назначении как элемент структуры

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

Тогда у меня есть следующий код в основной программе.

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

Однако мой выход выглядит следующим образом.

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

Размер по-прежнему правильный, но по какой-либо причине команда усечена на одну букву. Любая идея, почему это так?

+0

'#define COMMAND" d tcpip ", а затем использовать' COMMAND' вместо '* command' – BLUEPIXY

+2

@BLUEPIXY: Это уродливо, и OP может получить строка динамически ... – 3442

+3

@Alex Строковые литералы не нуждаются в явном терминале NULL ('\ 0') - они соответствуют ctly null завершен, если вы этого не сделаете. –

ответ

4

Что происходит, что ...

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

Это будет инициализировать элемент cmdRequest от cmdRequest как разыменования command, или, другими словами, вы получите первый символ в строке. Было бы слишком легко, что вы на самом деле не имеют нули после этого, так что printf() не работает. Вы прекрасно, возможно, был выход, как это, если вы изменили несколько несвязанных вещей ...

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

Сделайте это вместо того, чтобы ...

#include <string.h> 

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

@ user3386109: Ах, извините ... Отредактировано! – 3442

0

Использование зЬгсра вместо простого присваивания

При назначении разыменованного указателя обугленного на массив, только первый символ читаются

0

command является указателем на char.

Инициализируется строковой константой, что означает, что это указатель на первый символ этой строки, то есть 'd'.

Если вы разыменования указателя на char, вы получите в результате, единственный char, к которой он указывает, так *command вычисляет 'd'.

Вы инициализируете структуру, которая является «совокупным типом» в C, а второй элемент этой структуры представляет собой массив, который также является «совокупным типом».

C90 говорит, в разделе 6.5.7 «Инициализация»

В противном случае инициализатор для объекта, который имеет совокупный тип должна быть скобкой огороженного списка инициализаторов для членов совокупности, написанный в увеличение индекса или порядка членов; и инициализатор для объекта, который имеет тип объединения, должен быть инициализатором, заключенным в скобки для первого члена объединения.

Если совокупность содержит элементы, которые являются агрегатами или объединениями, или если первый член союза является агрегатом или объединением, правила применяются рекурсивно к подгруппам или объединенным объединениям. Если инициализатор субагрегата или объединенного объединения начинается с левой скобки, инициализаторы, заключенные в эту скобку, и ее подходящую правую фигуру инициализируют членов субагрегата или первого члена объединенного объединения.В противном случае только достаточное количество инициализаторов из списка учитывается для членов субагрегата или первого члена объединенного союза; любые оставшиеся инициализаторы оставляются для инициализации следующего члена агрегата, частью которого является текущий субагрегат или содержащий объединение.

Ваш инициализатор структуры заключен в скобки, так инициализаторы в этом инициализаторе инициализации членов структуры cmdLength и cmdRequest, в порядке, так что инициализирует cmdLength в cmdlen и инициализирует cmdRequest к 'd'.

cmdRequest представляет собой агрегат, но его инициализатор не в фигурных скобках, поэтому «только достаточно Инициализаторов из списка принимается для учета членов subaggregate», так cmdRequest[0] инициализируются 'd'.

Если вы хотите инициализировать cmdRequest в массив, первый элемент, на который указывает command, вы должны сделать это с зЬгсру:

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

К сожалению об этом, но это то, что вы получите при использовании язык, в котором строки не являются реальными типами данных ....