4

私は構造を持っています:

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;

そして、この構造体のインスタンスの配列を、ストック構造体ごとに1行のコードで初期化したいと思います。

私が試してみました:

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         }
};

しかし、それは失敗します:

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} },
                                                                         ^~~~~~~

char **であるため、問題となるのはバーコードフィールドです。

(それはclangでしたが、GCCは同様のエラーを報告しますが、あまり役に立ちません。)

これは、コンパイラが「12345」の前に中括弧を無視したかのようです。

私は以下を使用して問題を回避することができます:

const char *barcodes0001[] = {"12345", "23456", NULL};

stock_t data_stock[] = {
  { "0001", "Soup",  "Tomato Soup",     "71", 0, 100, 120, 10, 0, "",   barcodes0001 },

この問題の原因はchar []とchar*で異なりますか、それとももっと微妙なことがありますか。(おそらく、構造体の配列を初期化することはできますが、配列の構造体を初期化することはできません。)

4

2 に答える 2

6

コンパイラがブレースを無視しているのではなく、ブレースが言語の構文規則を無視しているようです。:)

フィールドbarcodeは単一のポインターです(ポインターへの、しかしそれは要点のそばにあります)。有効なポインター値を提供する必要があり、提供している波括弧が一致しません。

これもできません:

struct foo {
  int a, b;
};

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

これは、あなたがやろうとしていることと論理的に同じです。または、を削除するとstruct、次のこともできなくなります。

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

barcodeデータを分割したソリューションは、それを行う方法です。

于 2012-06-29T12:11:20.507 に答える
5

名前付きダミー変数を宣言する必要を避けるために、複合リテラルを使用できます

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         }
};

これは、c99 以降で使用可能な構文でローカル一時変数を定義する方法(type){ initializers }です (clang と gcc にはそれらがあります)。

編集:これらの複合リテラルの有効期間は変数と同じなdata_stockので、これで問題ないと思います。constいずれにせよ、ほとんどのフィールドを としてもマークする必要があると思います。const char*const key1p2;

また、次のような 指定されたイニシャライザを使用すると、読みやすくなります。

{ .keyp1 = "0001", ... }
于 2012-06-29T12:26:33.060 に答える