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.
class std::string str, so why do you writestruct conf_t conf?struct conf_t conf, as the current C++ solution for OpenCL kernel code is unstable. Also, I could find most of the documentation and tutorials about OpenCL writing kernel code in C. Therefore, I must craft a c-style struct to pass configuration information from the C++ host to the C kernel code.conf_t conf, no need for thestruct.structkeyword comes from the C-header included by the kernel code. Under this ground, if I copy and paste the exact struct definition with the keywordstructremoved, am I still expecting the memory layout between the c++ host and the c kernel be identical?structin C++ will have the same layout as astructin C. (So they'll be API compatible for the ABI.) Seestd::is_podand note that the check has been decomposed intostd::is_standard_layoutandstd::is_trivial.