Home > Software design >  How to initialize a static array within a c-style struct by an existing static array?
How to initialize a static array within a c-style struct by an existing static array?

Time:11-15

I'm currently doing c with OpenCL, where a c-style struct is required to carry configuration information from the c host to the OpenCL kernel. Given that dynamically allocated arrays are not guaranteed to be supported by every OpenCL implementation, I must ensure every array accessible by the kernel code be static-sized. However, I run into weird errors when initializing static arrays within a c-style struct.

The error could be reproduced by the following PoC:

#include <cstring>
#include <string>
#define ID_SIZE 16

struct conf_t {
    const unsigned int a;
    const unsigned int b;
    const unsigned char id[ID_SIZE];
};

int main() {
    const std::string raw_id("0123456789ABCDEF");
    unsigned char id[ID_SIZE];
    memcpy(id,raw_id.c_str(),ID_SIZE);
    struct conf_t conf = {10,2048,id};
}

And the following error:

poc.cc: In function ‘int main()’:
poc.cc:15:39: error: array must be initialized with a brace-enclosed initializer
   15 |         struct conf_t conf = {10,2048,id};
      |                                       ^~

It's true that I could remove the const keyword in the struct and get rid of the stack variable id, where &(conf.id) could be the first parameter of memcpy. However, I'd like to keep the immutability of fields in the conf struct, which enables the compilers to check undesired modifications.

For my understanding, structs in c should have the following memory layout:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|                               a                               |
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|                               b                               |
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|                                                               |
                                                                 
|                                                               |
                                id                               
|                                                               |
                                                                 
|                                                               |
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

Given the stack variable id is also with static size, I'm confused why the c compiler still looks for a brace-enclosed initializer even if id is already a static-sized array.

CodePudding user response:

The error on the initialization:

#include <cstring>
#include <string>
#define ID_SIZE 16

struct conf_t {
    const unsigned int a;
    const unsigned int b;
    const unsigned char id[ID_SIZE];
};

int main() {
    const std::string raw_id("0123456789ABCDEF");
    unsigned char id[ID_SIZE];
    memcpy(id, raw_id.c_str(), ID_SIZE);
    struct conf_t conf {10, 2048, {*id}};
}

is that you cannot initialize an array element of type const unsigned char with an lvalue of type unsigned char[16].

What you need to initialize your member, is to use the correct initialization syntax with curly braces { vals... }, and use the correct types on the initialization values. Thismeans, that you must dereference your id variable: {*id}

And everything compiles fine now. You can see a live example here

CodePudding user response:

Try either of these syntaxes:

struct conf_t {
    const unsigned int a;
    const unsigned int b;
    const unsigned char id[ID_SIZE];
};

conf_t syntax_1 = { 10, 1, { 'a', 'b', 'c' }};  // an array needs its own {}
conf_t syntax_2 = { 10, 1, "hello" };           // an array of char can be a string.
                                                // make sure you have room for the
                                                // null termination!
  • Related