0

I know that the following 2 initializers are equivalent:

char T1[]="abc";
char T2[]={'a', 'b', 'c', 0};

I have an array initializer like this:

char T[]={0x10, 0xF, 0xF0, 'H', 'e', 'l', 'l', 'o', 0xC1, 0xD0};

Leaving aside the signed/unsigned char potential problems, is there a way to mix the 2 styles of initializer, doing something like that (which doesn't work):

char T[]={0x10, 0xF, 0xF0, "Hello", 0xC1, 0xD0};
dargaud
  • 2,431
  • 2
  • 26
  • 39

2 Answers2

4

You can't mix them like that. What you can do is to insert hex codes withing a string, such as with:

char T[] = "\x10\x0f\xf0" "Hello" "\xc1\xd0";

Keep in mind this will put a \0 at the end of that array so you may need to adjust for that if you're using sizeof to get the byte count:

size_t bytesInT = sizeof(T) - 1;

Similarly, there won't be a null at the end of the Hello but you can fix that with:

char T[] = "\x10\x0f\xf0" "Hello\0" "\xc1\xd0";

You may wonder why the string is separated into three components. This is valid because a very early stage of the compilation process involves concatenating adjacent strings, meaning that "paxdiablo" and "pax" "diablo" are functionally equivalent.

One reason is for readability, but the important one is to ensure that the hex specifications don't "swallow" the following characters. It won't matter for Hello since the H is not a valid hex character but you can see the problem here:

#include <stdio.h>
int main(void) {
    printf ("%d %d\n", sizeof("\x20Hi"), sizeof("\x20Bi"));
    return 0;
}

This will output 4 3 despite the only difference (seemingly) in the two strings being a change of one character. The lengths are different because the B in Bi is actually consumed as a hex digit, being treated as \x20B (although gcc, for one, will warn you that the resultant value is out of range).

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 3
    You have to be careful with `\x` though. For example `char T[] = "\x10\x0f\xf0Byee!\xc1\xd0";` wouldn't work as expected. Using string literal concatenation would fix it: `char T[] = "\x10\x0f\xf0" "Byee!" "\xc1\xd0";` – Ian Abbott Apr 05 '17 at 13:17
  • @Ian, good point, have incorporated your info into the answer. – paxdiablo Apr 05 '17 at 13:30
2

You cannot mix the two styles, but you can include HEX characters inside a null-terminated string with HEX escape sequences:

// Instead of this
char T1[] = {0x10, 0xF, 0xF0, 'H', 'e', 'l', 'l', 'o', 0xC1, 0xD0};
// Do this:
char T2[] = "\x10\x0F\xF0" "Hello" "\xC1\xD0";
// or even this:
char T3[] = "\x10" "\x0F" "\xF0" "Hello" "\xC1" "\xD0";

The only difference between the above and the initializer that you have is that T2 and T3 are going to have one extra byte with null terminator at the end.

The above syntax exploits the feature of C which automatically concatenates multiple string literals separated by whitespace.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Perhaps separate the string literals when starting text after a hex escape `"\x10\x0F\xF0ByeBye\xC1\xD0";`is a problem. `"\x10\x0F\xF0" "ByeBye\xC1\xD0";` is OK – chux - Reinstate Monica Apr 05 '17 at 13:01