How to initialize complex C structure in one line?

I have a structure:

typedef struct stock { const char* key1p2; // stock code const char* key2p2; // short desc const char* desc1; // description const char* prod_grp; // product group const char dp_inqty; // decimal places in quantity const long salprc_u; // VAT excl price const long salprc_e; // VAT includive price const long b_each; // quantity in stock const long b_alloc; // allocated qty const char* smsgr_id; // subgroup const char** barcodes; // barcodes } stock_t; 

and I want to initialize arrays of instances of this structure in one line of code for the stock structure.

I tried:

 stock_t data_stock[] = { { "0001", "Soup", "Tomato Soup", "71", 0, 100, 120, 10, 0, "", {"12345", "23456", NULL} }, { "0002", "Melon", "Melon and Ham", "71", 0, 200, 240, 10, 0, "", {"34567", "45678", NULL} }, ... { NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, NULL, NULL } }; 

but fail:

 data.c:26:74: warning: incompatible pointer types initializing 'const char **' with an expression of type 'char [6]' [-Wincompatible-pointer-types] { "0001", "Soup", "Tomato Soup", "71", 0, 100, 120, 10, 0, "", {"12345", "23456", NULL} }, ^~~~~~~ 

This barcode field is problematic as it is char **.

(it was clang, but GCC reports a similar error, but less helpful.)

It is almost as if the compiler ignored the curly braces before "12345".

I can get around the problem using:

 const char *barcodes0001[] = {"12345", "23456", NULL}; stock_t data_stock[] = { { "0001", "Soup", "Tomato Soup", "71", 0, 100, 120, 10, 0, "", barcodes0001 }, 

Is the cause of this problem different from char [] and char *, or is there something more subtle. (Perhaps you can initialize arrays of structures, but not array structures.)

+4
source share
2 answers

To avoid declaring a named dummy variable, you can use a compound literal

 stock_t data_stock[] = { { "0001", "Soup", "Tomato Soup", "71", 0, 100, 120, 10, 0, "", (const char*[]){"12345", "23456", NULL} }, { "0002", "Melon", "Melon and Ham", "71", 0, 200, 240, 10, 0, "", (const char*[]){"34567", "45678", NULL} }, ... { NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, NULL, NULL } }; 

This is a way to define a local temporary variable with the syntax (type){ initializers } , which is available with c99 (and clang and gcc have them).

Edit: The lifetime of these compound literals is the same as your data_stock variable, so I assume this is normal. In any case, I think you should mark most of your fields as const , for example, const char*const key1p2;

It would also be much easier to read if you used designated initializers, e.g.

 { .keyp1 = "0001", ... } 
+4
source

It is not as if the compiler ignored your figure, it is as if your bracket ignored the syntax rules of the language. :)

The barcode field is the only pointer (to the pointer, but next to the dot). You need to specify a valid pointer value, and the obscure thing you provide is not consistent.

You also cannot do this:

 struct foo { int a, b; }; struct foo *pointer_to_foo = &{ 1, 2 }; /* Not valid code. */ 

Which is logically the same as what you are trying to do. Or by removing the struct , you also cannot do this:

 int *pointer_to_a = &12; /* Not valid code. */ 

The solution where you broke the barcode data is a way to do this.

+6
source

All Articles