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 initialise arrays of instances of this structure, in one line of code per stock struct.
I have 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 it fails with:
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} },
^~~~~~~
It is the barcode field which is problematic, as it is char**.
(that was clang, but GCC reports a similar error, but less helpfully.)
It's almost as if the compiler has ignored the curly brace before "12345".
I can work 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 a different between char [] and char *, or is there something more subtle. (Perhaps you can initialise arrays of structs, but not structs of arrays.)
It's not as if the compiler is ignoring your brace, it's as if your brace is ignoring the syntax rules of the language, rather. :)
The field barcode
is a single pointer (to a pointer, but that's beside the point). You need to provide a valid pointer value, and the braced thing you're providing doesn't match.
You also can't 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're trying to do. Or, removing the struct
, you also can't do this:
int *pointer_to_a = &12; /* Not valid code. */
The solution where you've broken out the barcode
data is the way to do it.
To avoid to have to declare 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 a syntax of (type){ initializers }
which is available since c99 (and clang and gcc have them).
Edit: The lifetime of these compound literals is the same as your variable data_stock
so I suppose this is ok. In any case I think you should mark most of your fields also as const
, e.g const char*const key1p2;
Also it would be much easier to read if you'd use designated initializers something like
{ .keyp1 = "0001", ... }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With