You can do the same thing in C, but you should declare it of type char[], not char*, so that you can get its size with the sizeof operator:
char myArray[] = { 0x00, 0x11, 0x22 };
size_t myArraySize = sizeof(myArray); // myArraySize = 3
Answer from Adam Rosenfield on Stack OverflowYou can do the same thing in C, but you should declare it of type char[], not char*, so that you can get its size with the sizeof operator:
char myArray[] = { 0x00, 0x11, 0x22 };
size_t myArraySize = sizeof(myArray); // myArraySize = 3
Just for the sake of completeness, with C99 you can also use compound literals:
char *myArray = (char []) {0x00, 0x11, 0x22 };
If source code compatibility to C++ is a requirement, you better don't use this construct, because it is - afaik - not part of the C++ standard.
initialization - Initialize C array with bytes and string literals - Stack Overflow
Looking for method to initialize an array of structures (type contains some constant vectors)
Any good detailed resources on initializing arrays and the values we can give them?
C array initialization size in bytes - Stack Overflow
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.
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)
First post here, old-school C user for microcontrollers (using GCC in Eclipse-based SDK published by ST Micro).
I need to create and initialize an array of structures (these structures would end up in RAM, so not using the const declaration anywhere.
Each element (a structure) would contain a few integers and a few byte arrays (one expressed as ASCII characters, others are 8-bit integers.) Currently I create the structure (individual elements) and call a function to copy the elements into the structure which is one of N in an array, which is probably OK but makes the source code look clumsy(er).
This is roughly what I'd like to accomplish, but not sure how to code in C (please forgive the formatting and I suspect none of this would compile, but hopefully it conveys what I'm trying to accomplish.
this is one element of the example struct array:
struct a_type
{
uint8_t x;
uint8_t[8] y;
uint8_t[8] z;
}
This is the array of the structures (eight of these, for example:)
a_type structs[8]; // End up with eight of the above, each containing one byte scalar and two byte arrays of 8 elements each.
What I want to accomplish looks like this:
structs[0].x = 123; // Single uint8_t
structs[0].y = "ABCDEFGH"; // Each char/uint8_t, no zero terminator
structs[0].z = { 0, 1, 2, 3, 4, 5, 6, 7}; // Each are uint8_t
Grateful for any suggestions, requests for clarification, or criticism!
DaveI came across an issue where a char array wasn't initialised and the fix was to put "" into the value e.g. Char array [100] = "";
I don't get why this worked, i suspect it was just filling with garbage before, so i have looked online for some good explanations but have only come across a tonne of articles explaining assigning string literals to the array inside curly braces.
Are there any good resources explaining the different ways we can initialize arrays? I know a few but am definitely missing some.l and a complete list would be excellent.
Thankyou
That's because you have an array of pointers to char. Every pointer is 8-byte (on x64), so 16 pointers x 8 bytes = 128 bytes.
You've got an array of pointers to strings and the architecture you're compiling on has a 8-byte pointer size. 8 bytes times 16 pointers equals 128 bytes.
IMO the easiest one to optimize by the compiler (and very safe as well) is
void foo(uint16_t color, uint8_t *arr16, size_t n)
{
uint8_t data_8_bit[2] = {color >> 8, color & 0xff};
while(n--)
{
memcpy(arr16 + n * 2, data_8_bit, 2);
}
}
https://godbolt.org/z/8Wh5Pc3aP
Although quite unknown to many, you can use wmemset for this if sizeof(wchar_t) is a multiple of 2 on your platform, which is practically true for all the implementations
For example when it's a 2-byte type like on Windows, or on GCC with -fshort-wchar:
_Static_assert(sizeof(wchar_t)*CHAR_BIT == 16);
wchar_t pattern;
memcpy(&pattern, data_8_bit, 2);
wmemset((wchar_t*)data_16_bit, pattern, n);
If wchar_t is a 4-byte type like the default on most *nix platforms
_Static_assert(sizeof(wchar_t)*CHAR_BIT == 32);
wchar_t pattern;
memcpy(&pattern, data_8_bit, 2);
memcpy((char*)&pattern + 2, data_8_bit, 2);
wmemset((wchar_t*)data_16_bit, pattern, n);
wmemset should be hand-optimized with SIMD in assembly like memset so it'll be extremely fast compared to other solutions where the compiler isn't able to auto-vectorize. For example there are lots of optimized memset and wmemset versions for x86-64 in glibc including SSE2, AVX2 and even AVX-512
You may need to take care of alignment in some platforms though