[英]How to create an array literal of struct literals in C?
我的目標是自動生成基於舊知識的系統的控制邏輯,該系統本質上是一系列數百個結構類似的if-then語句。 我們還希望通過某種反射來了解這些語句的屬性,數組文字有助於生成這些反射。
我在這里回顧了許多關於SO的答案,但是其中大多數是關於字符串文字數組的,這不是我想要實現的。
我正在嘗試制作一個X宏,它包含一個結構文字數組作為其參數之一,可用於初始化堆棧分配的數組變量。
這是一些未編譯的代碼,顯示了我的嘗試:
#include <stdio.h>
typedef enum qty_t {
qty_None, qty_Some, qty_Many
} qty_t;
typedef enum arg_t {
arg_X, arg_Y, arg_Z
} arg_t;
typedef struct action_t {
int id;
qty_t quantity;
arg_t argument;
} action_t;
/* a change is a sequence of actions, and a change identifier */
/* the outermost {} are the array, the inner ones being the structs */
#define CHANGES \
CHANGE(1, ({{.id=1,.quantity=qty_None,.argument=arg_X}, \
{.id=2,.quantity=qty_Many,.argument=arg_Z}\
}\
)\
)\
CHANGE(2, ({{1,qty_Some,arg_Y}}))
int main(void) {
// your code goes here
#define CHANGE(change_id, actions) \
action_t current_actions ## change_id[] = actions;
CHANGES
#undef CHANGE
return 0;
}
如何在CHANGE宏中放入結構常量的數組常量,特別是可用於初始化current_actions1變量的數組常量?
那個怎么樣 :
#define CHANGES \
CHANGE(1, {{.id=1,.quantity=qty_None,.argument=arg_X}, \
{.id=2,.quantity=qty_Many,.argument=arg_Z}\
}\
\
)\
CHANGE(2, {{.id=1,.quantity=qty_Some,.argument=arg_Y}})
int main(void) {
// your code goes here
#define CHANGE(change_id, actions ...) \
action_t current_actions ## change_id[] = actions;
CHANGES
#undef CHANGE
return 0;
}
我在CHANGES中刪除了括號,並在CHANGE中添加了...
該編譯和gcc -E foo.c
給出:
int main(void) {
action_t current_actions1[] = {{.id=1,.quantity=qty_None,.argument=arg_X}, {.id=2,.quantity=qty_Many,.argument=arg_Z} }; action_t current_actions2[] = {{.id=1,.quantity=qty_Some,.argument=arg_Y}};
return 0;
}
不管是否有文字本身,都沒有“結構文字數組”之類的東西。 數組的元素可以是結構,您可以使用結構文字來初始化結構數組(yuck)的元素(包括數組文字),但數組的元素本身不是文字。 這聽起來可能(確實,可能是)是學究的,但是使用一致且正確的術語可以提高思想和溝通的清晰度。
實際上,您根本沒有使用結構文字或數組文字。 您只是在結構體的初始化程序內使用結構體初始化程序。 這已經稍微簡化了問題。
您的代碼的第一個問題是放在數組初始化程序周圍的CHANGE
宏定義中的括號。 這些是每次CHANGE
宏調用的第二個參數的一部分,因此,它們作為宏CHANGES
的替換文本的一部分發出。 但是它們不是初始化器允許的語法的一部分,因此生成的代碼無效。
我假設首先要放在括號中,以避免初始化程序內部的逗號被解釋為分隔宏參數。 解決該問題的另一種方法(在這種情況下,至少要這樣)是使您定義CHANGE
宏可變參數:
#define CHANGE(change_id, ...) \
action_t current_actions ## change_id[] = __VA_ARGS__;
這使用C99中介紹的標准形式的可變參數宏為我解決了問題。
另一個更結構化的替代方法是為結構初始化程序添加宏,以使內部及其之間的逗號不影響宏參數標識。 例如,
#define FIRST_ACTION(i,q,a) {.id=i,.quantity=q,.argument=a}
#define ACTION(i,q,a) ,FIRST_ACTION(i,q,a)
#define CHANGES \
CHANGE(1, {\
FIRST_ACTION(1,qty_None,arg_X)\
ACTION(2,qty_Many,arg_Z)\
})\
CHANGE(2, {\
FIRST_ACTION(1,qty_Some,arg_Y)\
})
// ...
#define CHANGE(change_id, actions) \
action_t current_actions ## change_id[] = actions;
CHANGES
當然,所有這些都假設您的情況下從X宏方法中可以獲得一些好的價值。 這至少需要在代碼的其他地方使用CHANGES
宏。 在您呈現的內容中,沒有任何明顯的事物,但可以將其省略。 但是,我目前還不清楚,您的特定CHANGES
宏提供了其他用途,而其他方法無法更好地滿足這一需求。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.