[英]Static structure initialization with a pointer to array of pointers member
我正在嘗試初始化一個需要指向指針數組的結構成員。 想法是靜態聲明結構數組,以避免初始化開銷,因為所有數據都是固定的,並且在編譯時已知。
不幸的是,我無法在Visual Studio 2015
下編譯代碼。 下面列出的代碼產生以下錯誤: C2099: initializer is not a constant
。 這似乎很奇怪,因為list
僅使用固定大小的字符串文字列表進行初始化。
#define DATA_LIST { \
L"some", \
L"example", \
L"data", \
L"in a list", \
NULL \
}
#define INFO_LIST { \
L"another", \
L"list", \
L"with", \
L"some", \
L"info", \
NULL \
}
typedef struct data {
unsigned int flag;
const wchar_t **list;
} dataset, *pdataset;
static dataset somedata[] = {
{ .flag = 2,
.list = (const wchar_t *[])DATA_LIST // C2099
},
{ .flag = 4,
.list = (const wchar_t *[])INFO_LIST // C2099
}
};
我還嘗試使用一個指向靈活數組的指針( const wchar_t *list[];
)。 這不是理想的解決方案,因為將不再能夠將somedata
聲明為結構數組。 緊接着,它還會產生警告(C4200: nonstandard extension used: zero-sized array in struct/union)
。
typedef struct data {
unsigned int flag;
const wchar_t *list[]; // C4200 (somedata can no longer be an array of structures)
} dataset, *pdataset;
static dataset somedata = {
.flag = 2,
.list = DATA_LIST
};
另一個想法是將list
定義為指向固定大小的指針數組的指針。 但這需要使用list
成員定義dataset
結構,該list
成員足夠大以容納最大列表。 當有很多小列表和一個大列表時,也不理想。
typedef struct data {
unsigned int flag;
const wchar_t *list[sizeof (wchar_t *[])INFO_LIST / sizeof *(wchar_t *[])INFO_LIST];
} dataset, *pdataset;
static dataset somedata[] = {
{ .flag = 2,
.list = DATA_LIST
},
{ .flag = 4,
.list = INFO_LIST
}
};
也許我正在監督某些事情,或者是否有一些語言擴展功能可以提供一個優雅的解決方案? 歡迎任何建議。
注意:即使添加了visual-c++
標記,該代碼仍被編譯為C代碼。
可能要添加的另一件有趣的事情是,當somedata
被聲明為非靜態數據(因此沒有static
關鍵字)時,編譯器將產生一些警告,但能夠編譯代碼。 通過聲明somedata
為非靜止的,該約束被移除,迫使用於初始化數據somedata
在編譯時是已知的。
如編譯警告所示,似乎編譯器在用它初始化list
成員之前,將字符串文字列表的地址臨時存儲在一個自動變量中。 不過,這仍然是猜測。 也許經驗豐富的人可以對這里實際發生的事情有所了解。
typedef struct data {
unsigned int flag;
const wchar_t **list;
} dataset, *pdataset;
// C4221: nonstandard extension used: 'list': cannot be initialized using
// address of automatic variable '$S1'
// C4204: nonstandard extension used: non-constant aggregate initializer
dataset somedata = {
.flag = 2,
.list = (const wchar_t *[])DATA_LIST // note: see declaration of '$S1'
};
最后但並非最不重要的一點是,當使用使用字符串文本列表的地址初始化的臨時變量初始化list
成員時,代碼最終可以正常編譯,而不會發出任何警告或錯誤。
static const wchar_t *temp[] = DATA_LIST;
static dataset somedata = {
.flag = 2,
.list = temp
};
但是,當將temp
聲明為指向指針的指針並類型轉換字符串文字列表時,由於初始化list
的表達式被標記為活動錯誤,因此無法再編譯該代碼: expression must have a constant value
static const wchar_t **temp = (const wchar_t *[])DATA_LIST;
static dataset somedata = {
.flag = 2,
.list = temp // marked as active error
};
如果我隨后決定再次使somedata
非靜態,則該表達式不再標記為活動錯誤。 但是,當嘗試編譯代碼時,再次出現以下錯誤: C2099: initializer is not a constant
我想知道Visual Studio 2017
行為方式是否相同,是否存在其他可用的方法來通過類似方式組織和處理數據。
MSVC對C標准的合規性很差。 解決方法是,可以使用命名對象代替復合文字:
static const wchar_t *x_data_list[] = DATA_LIST;
static const wchar_t *x_info_list[] = INFO_LIST;
static dataset somedata[] = {
{ .flag = 2,
.list = x_data_list
},
{ .flag = 4,
.list = x_info_list
}
};
我不確定您是否有意使列表成為非常量,但是如果您不打算在運行時寫入x_data_list
,則可以使其成為const
並為.list
成員指定const wchar_t * const *
的類型。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.