2

I would like to initialize a byte array with some byte values and a string literal in one go. Essentially the array is serialized representation of data structure like

struct foo {
  uint8 param1;
  uint8 stringLen;
  const char * string;
  uint8 param2;
};

though the API expects byte array and I have no control over that. The API expects the array to be statically initialized for sizeof operator to report actual size. I know it is possible to initialize an array with string literals OR specific bytes, though any attempt to initialize an array with both ends up in string literal being treated as a pointer address (what it is, no surprise here).

I was thinking about defining my own struct and initializing the array with that, but I don't believe structs or even string literals are compile-time serializable. I cannot seem to think of such syntax and am not even sure if that is possible at all. Any input appreciated.

The last resort could be initializing the array with something like array[] = "\x66oo", but that would only be marginally more maintainable than simple array[] = {0x66, 'o', 'o'}, both solutions require external (python?) generator.

7
  • 2
    You can define an initialized const array of the structure and it should be initialized at compile-time. Watch out for structure padding though, consult your compiler manual on how to pack structures without padding. Commented Mar 3, 2015 at 11:16
  • 1
    @JoachimPileborg this is a good idea,but it will not serialize the string literals,compiler still have liberty to store them anywhere. An array of characters of fixed size will do(If string literal is of fixed size). Commented Mar 3, 2015 at 11:32
  • But, IIUC, the real problem is that a standard initialiser for a C string assumes that a nul-terminator should be appended ? ( string concatenation for C strings will allow char array[] = "a" "\x05" "Hello" "b"; , but the resulting initalizer will be 9 bytes long instead of the intendeded 8 bytes ) Commented Mar 3, 2015 at 12:19
  • @joop: presence of a null terminator does not create any problems I'm aware of - the string is used strictly as a static string for human-readable identification. Commented Mar 3, 2015 at 12:45
  • 1
    Why don't you just add to the question what the API is actually expecting? Commented Mar 3, 2015 at 13:48

2 Answers 2

2

You will have to initialise the byte array using a function like this:

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

If the struct contains any integers with a length greater than 1 (i.e. uint16, etc) then you will also need to consider their endianness during encoding.

Sign up to request clarification or add additional context in comments.

1 Comment

I am aware of runtime methods to initialize an array, though API expects the array to be statically (BSS segment) initialized for sizeof to report actual size. Sorry for misunderstanding, edited the question
0

C allows string literals (also in initialisers) to be broken up; the compiler will paste them for you.

So, you could do:

char unit1[8] = "\x40" "\x05" "Hello" "\x3e";
char unit2[9] = "\x40" "\x06" "World!" "\x3e";

char unitBoth[] = "\x40" "\x05" "Hello" "\x3e"
                  "\x40" "\x06" "World!" "\x3e";

The unitBoth[] array has no defined size; it is just one byte longer (the nul byte) than the sum of the two separate arrays.


#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;
}

And of course you could create a program or script to generate the definitions. (and include them in your main program, possibly in global scope)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.