Инициализировать массив 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;
}

И, конечно, вы можете создать программу или скрипт для генерации определений. (и включите их в свою основную программу, возможно, в глобальном масштабе)

Другие вопросы по тегам