【问题标题】:C Preprocessor – exploding an array and its lengthC 预处理器——分解数组及其长度
【发布时间】:2013-12-17 06:41:12
【问题描述】:

我有一个问题。在我自己的网络服务器中,我在文件范围内有以下代码:

typedef struct {
    char *slice;
    int length;
} values_index;

const char *aHeaderKeys[] = {
    /* You can add here whatever you want! */
    "Accept",
    "Accept-Charset",
    "Accept-Encoding",
    "Accept-Language",
    "Authorization",
    "Expect",
    "From",
    "Host",
    "If-Match",
    "If-Modified-Since",
    "If-None-Match",
    "If-Range",
    "If-Unmodified-Since",
    "Max-Forwards",
    "Proxy-Authorization",
    "Range",
    "Referer",
    "TE",
    "User-Agent",
    "Connection"
};

int nHeadersSizes[sizeof(aHeaderKeys) / sizeof(*aHeaderKeys)];
values_index aHeaderValuesIndexes[sizeof(aHeaderKeys) / sizeof(*aHeaderKeys)];
const int nHeadersLen = sizeof(aHeaderKeys) / sizeof(*aHeaderKeys);

但是,由于aHeaderKeys是一个由常量字符串组成的定长数组,所以在程序执行过程中计算数组的长度是很愚蠢的,最好还是手动写:

typedef struct {
    char *slice;
    int length;
} values_index;

const char *aHeaderKeys[20] = {
    /* You can add here whatever you want! */
    "Accept",
    "Accept-Charset",
    "Accept-Encoding",
    "Accept-Language",
    "Authorization",
    "Expect",
    "From",
    "Host",
    "If-Match",
    "If-Modified-Since",
    "If-None-Match",
    "If-Range",
    "If-Unmodified-Since",
    "Max-Forwards",
    "Proxy-Authorization",
    "Range",
    "Referer",
    "TE",
    "User-Agent",
    "Connection"
};

int nHeadersSizes[20];
values_index aHeaderValuesIndexes[20];
const int nHeadersLen = 20;

但是我的数组元素的数量在开发过程中可能会发生变化,所以每次我想添加另一个元素时,我都必须在各处手动更改长度。 现在我的问题是:是否可以编写一个预处理器宏,类似于我用 JavaScript 编写的以下宏(作为伪代码)?

var aHeaders = [
    "Accept",
    "Accept-Charset",
    "Accept-Encoding",
    "Accept-Language",
    "Authorization",
    "Expect",
    "From",
    "Host",
    "If-Match",
    "If-Modified-Since",
    "If-None-Match",
    "If-Range",
    "If-Unmodified-Since",
    "Max-Forwards",
    "Proxy-Authorization",
    "Range",
    "Referer",
    "TE",
    "User-Agent",
    "Connection"
];

var sExplodedText = "const char *aHeaderKeys[" + aHeaders.length + "] = {\n\t\/* You can add here whatever you want! *\/\n\t\"" + aHeaders.join("\",\n\t\"") + "\"\n};\n\nint nHeadersSizes[" + aHeaders.length + "];\nvalues_index aHeaderValuesIndexes[" + aHeaders.length + "];\nconst int nHeadersLen = " + aHeaders.length + ";";

alert(sExplodedText);

【问题讨论】:

  • 编译器无论如何都会在编译时评估 sizeofs,所以没有必要这样做。

标签: c arrays c-preprocessor static-array


【解决方案1】:

不需要指定数组的大小,编译器会自己计算出来。 你可以这样做

const char *aHeaderKeys[] = {
...
};


#define NR_HEADERS (sizeof aHeaderKeys/sizeof aHeaderKeys[0])

然后在需要的地方使用 NR_HEADERS。这里的表达式将在编译时由编译器计算,没有运行时计算。

【讨论】:

  • 或:enum { NUM_HEADER_KEYS = sizeof(aHeaderKeys) / sizeof(aHeaderKeys[0]) }; 将所选名称放在符号表中,而不是在运行预处理器时丢失它,从而使调试更容易。
  • @nos 哇,谢谢!那么,你确定“这里的表达式会在编译时由编译器计算出来”吗?您真的是说预编译器会将 NR_HEADERS 分解为“20”而不是“(sizeof aHeaderKeys/sizeof aHeaderKeys[0])”吗?怎么可能??
  • 编译器,而不是预处理器,将在编译时评估它。这里的 sizeof 是常数,除法也是在编译时进行的。是的,我确定。
  • @nos 所以,添加到文件范围是没有用的: const int nHeadersLen = NR_HEADERS;我甚至可以在函数范围内使用 sizeof(aHeaderKeys) / sizeof(aHeaderKeys[0]) ,它会在编译时替换为 20... 对吗?
【解决方案2】:

感谢@nos 和@JonasWielicki,这就是解决方案。

确定NR_HEADERS在下面一行

#define NR_HEADERS (sizeof aHeaderKeys / sizeof *aHeaderKeys)

将始终替换为20在编译时,并且将在以下代码中没有运行时计算

const char *aHeaderKeys[] = {
    /* You can add here whatever you want! */
    "Accept",
    "Accept-Charset",
    "Accept-Encoding",
    "Accept-Language",
    "Authorization",
    "Expect",
    "From",
    "Host",
    "If-Match",
    "If-Modified-Since",
    "If-None-Match",
    "If-Range",
    "If-Unmodified-Since",
    "Max-Forwards",
    "Proxy-Authorization",
    "Range",
    "Referer",
    "TE",
    "User-Agent",
    "Connection"
};

#define NR_HEADERS (sizeof aHeaderKeys/sizeof sizeof *aHeaderKeys)

values_index aHeaderValuesIndexes[NR_HEADERS];
int nHeadersSizes[NR_HEADERS];

所以,问题解决了!

谢谢!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-17
    • 2011-12-13
    • 2023-03-15
    • 2021-06-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多