Инициализировать массив C байтами и строковыми литералами
Я хотел бы инициализировать байтовый массив с некоторыми байтовыми значениями и строковым литералом за один раз. По сути массив представляет собой сериализованное представление структуры данных типа
struct foo {
uint8 param1;
uint8 stringLen;
const char * string;
uint8 param2;
};
хотя API ожидает байтовый массив, и я не могу это контролировать. API ожидает, что массив будет статически инициализирован для sizeof
оператор, чтобы сообщить фактический размер. Я знаю, что можно инициализировать массив строковыми литералами ИЛИ конкретными байтами, хотя любая попытка инициализировать массив с обоими концами заканчивается строковым литералом, который рассматривается как адрес указателя (что здесь не удивительно).
Я думал об определении своего struct
и инициализируя массив этим, но я не верю, что структуры или даже строковые литералы сериализуемы во время компиляции. Я не могу думать о таком синтаксисе и даже не уверен, возможно ли это вообще. Любой вклад приветствуется.
В крайнем случае можно инициализировать массив чем-то вроде array[] = "\x66oo"
, но это было бы лишь немного более приемлемым, чем простой array[] = {0x66, 'o', 'o'}
оба решения требуют внешнего (python?) генератора.
2 ответа
Вам придется инициализировать байтовый массив с помощью функции, подобной этой:
uint8 *initByteArray(const struct foo *foo)
{
unsigned slen = foo->string ? strlen(foo->string) : 0;
assert(slen <= 255);
uint8 *array = malloc(slen + 3);
unsigned i = 0;
array[i++] = foo->param1;
array[i++] = (uint8)slen;
if (slen) {
strncpy(&array[i], foo->string, slen);
i += slen;
}
array[i++] = foo->param2;
return array;
}
Если struct
содержит любые целые числа длиной более 1 (т.е. uint16
и т. д.) тогда вам также нужно будет учитывать их порядковый номер при кодировании.
C позволяет разбивать строковые литералы (также в инициализаторах); компилятор вставит их для вас.
Итак, вы можете сделать:
char unit1[8] = "\x40" "\x05" "Hello" "\x3e";
char unit2[9] = "\x40" "\x06" "World!" "\x3e";
char unitBoth[] = "\x40" "\x05" "Hello" "\x3e"
"\x40" "\x06" "World!" "\x3e";
unitBoth[]
массив не имеет определенного размера; это всего на один байт длиннее (нулевой байт), чем сумма двух отдельных массивов.
#include <stdio.h>
#include <string.h>
int main(void)
{
unsigned idx, len;
printf("Unit1 Size = %zu\n", sizeof unit1);
for (idx=0; idx < sizeof unit1; idx++) {
printf("%u : %02x\n" , idx , 0xff & unit1[idx] );
}
printf("\nUnit2 Size = %zu\n", sizeof unit2);
for (idx=0; idx < sizeof unit2; idx++) {
printf("%u : %02x\n" , idx , 0xff & unit2[idx] );
}
printf("\nUnitBoth Size = %zu\n", sizeof unitBoth);
for (idx=0; idx < sizeof unitBoth; idx++) {
printf("%u : %02x\n" , idx , 0xff & unitBoth[idx] );
}
return 0;
}
И, конечно, вы можете создать программу или скрипт для генерации определений. (и включите их в свою основную программу, возможно, в глобальном масштабе)