Tag: c preprocessor

GNU C预处理器:对宏评估的结果进行字符串化

我有一个常见的字符串宏,我想转换为长度值字符串,所有这些都在宏中,如果可能的话,所以一切都以.rodata 。 #define PAYLOAD “xyz” #define PAYLOAD_LEN (sizeof(PAYLOAD)-1) 我想将PAYLOAD_LEN用作字符串,作为另一个字符串的一部分,例如 const char lv_macro[] = “” PAYLOAD_LEN “:” PAYLOAD; const char lv_wanted[] = “3:xyz”` 我怀疑这是不可能的,我应该将PAYLOAD_LEN定义为文字,例如#define PAYLOAD_LEN 3然后进行字符串化 。 我可以,但不想,忘记.rodata并在运行时生成它,例如 char lv[64]; snprintf(lv, sizeof lv, “%zu:” PAYLOAD, PAYLOAD_LEN); 请注意,这不是已经在此处提出和回答的问题,例如,以及许多其他问题。

连接X宏的多个标记

我正在尝试第一次使用X宏和预处理器连接。 我已经阅读了很多关于预处理器连接的SO的其他问题,但还没有能够解决它们或者如何使这些问题适应我的用例。 项目列表是一组structs的ID号列表,如下所示: #define LIST_OF_ID_NUMS \ X(1) \ X(2) \ X(3) \ X(4) \ X(5) \ X(6) \ X(7) \ X(8) \ X(9) \ X(10) \ X(11) 我可以像这样声明结构: #define X(id_num) static myFooStruct foo_## id_num ; LIST_OF_ID_NUMS #undef X // gives: ‘struct myFooStruct foo_n;’ where ‘n’ is an ID number 现在我还要初始化每个结构的一个成员等于ID号,这样foo_n.id = n; 。 通过使用以下内容,我已经能够实现第一个令牌连接: #define […]

像宏这样的函数是否需要强制括号? 在参考GCC cpp手册后我很困惑

这让我感到困惑: 要定义类似函数的宏,可以使用相同的’#define’指令,但是在宏名称后面紧跟一对括号。 我相信这是为了让代码脱颖而出,而不是该程序的作者。 像宏名称的其他CAPS规则一样。 但以下是我感到困惑的地方: 类似函数的宏只有在其名称后面带有一对括号时才会展开。 如果你只写这个名字,那就不管它了。 我读完之后立刻就不同意了。 并且gcc -Evalidation了以下代码 #define FUNC display() void display() { printf(“Display\n”); } int main() { FUNC; return 0; } 预处理的输出按预期显示main()函数的内容: int main() { display(); return 0; } 那我在这里错过了什么? 预处理器用于标记源,宏扩展是一个令牌,上面的代码以这种方式处理,预处理器不应该检查任何东西或validation任何东西,它只是转储令牌。 在那种情况下,gcc手册试图传达什么。 我正在学习C编程,所以我可能会经常发生误解,我搜索了一个正确的解释,最后在这里求助。 请帮我解决一下这个。

定义一个即使定义了NDEBUG也有效的断言

我想定义一个assert宏,它与标准的assert(3)调用相同,只是在定义NDEBUG时预处理器不会删除它。 这样的调用,让我们在这里称之为assert2 ,例如,如果你想在软件的发布版本中进行一些检查,那么它是有用的。 我怎样才能以合理的便携方式做到这一点? 我总是可以完全重新创建assert机制,如1 : #define assert2(cond) cond ? (void)0 : die_now(#cond, __FILE__, __LINE__) static die_now(char *cond_str, const char *file, int line) { // print a message to stderr here … abort(); // or maybe abort ? } …但我更倾向于使用与现有断言调用相同的机制。 特别是,内置的assert调用做了很好的事情,比如处理编译器和平台的所有各种奇怪的东西,用特殊的魔法注释断言条件,让编译器在调用后假设条件成立,相当打印函数名称,等等上。 在包含assert.h之前,我可以通过#undef NDEBUG获取内置assert – 但是我看不到如何将它重命名为assert2 。 我想我可以将系统头文件中assert的定义复制并粘贴到#define assert2行,但这是(a)可能违反某些许可或版权,(b)需要重复平台。 请不要开始辩论这种function是否有用,或者它是否是实现更高级别目标的合理方式。 我特别询问是否可以在不依赖于NDEBUG情况下以其他名称重用现有的assert调用。 1当然,将die_now声明为static函数并不理想,因为它将在每个使用as assert编译单元中复制die_now函数(或者更糟糕的是,甚至可能包括所有那些仅包含头部的那些),因此它应该真正定义在它自己的并发单元中脱节,但这是使用这个function的另一个复杂因素。

宏交换(t,x,y)交换类型为t的两个参数

所以我基本上试图创建一个交换两个t类型参数的SWAP(t,x,y)宏。 当这两个参数都是这种forms时,我试图想到解决这个问题 v [i ++]和w [f(x)],即SWAP(int,v [i ++],w [f(x)])。 下面的代码基本上崩溃了…… #define SWAP(T,x,y) {T *p = x; T *q = y; T z = *p; *p = *q; *q = z;} int f (int x){ return (0-x); } int main(void) { int v[] = {1,2,3}; int i = 0; int w[] = {4,5,6}; int x = […]

C预处理器能够通过char处理字符串char吗?

我想在编译时隐藏字符串。 我知道它可以在其他预处理器中完成,但我还没有找到一种方法来使用C预处理器。

C中的宏指令,我的代码示例不起作用

我想获得以下代码片段: #define READIN(a, b) if(scanf(‘”#%d”‘, ‘”&a”‘) != 1) { printf(“ERROR”); return EXIT_FAILURE; } int main(void) { unsigned int stack_size; printf(“Type in size: “); READIN(d, stack_size); } 我不明白,如何使用#运算符指令。 我想多次使用带有打印错误等的scanf ,但是”‘”#%d”‘和'”&a”‘”我认为是完全错误的。 有没有办法让它运行? 我认为宏是最好的解决方案吗?

宏执行整数运算

是否可以使用宏执行算术(我的情况下的乘法)? 我明白写一个像: #define mult(a,b) ((a)*(b)) 将产品替换到处都是。 但我有两个参数作为常量。 我知道编译器也会静态执行乘法,但问题是我必须使用#将结果转换为字符串。 知道如何做到这一点? 如果它可以用C ++宏完成,我还是可以的。 我可以用C ++编写那些特定的模块并将其链接起来。 以下是我目前的代码 #define ARG_COPY() __asm__(“subq $8, %rsp”); \ __asm__(“movq %gs:0xe8, %r10”); \ __asm__(“movq $16, %r11”); \ __asm__(“1:”); \ __asm__(“movq -8(%r10, %r11, 8), %rax”); \ __asm__(“pushq %rax”); \ __asm__(“decq %r11”); \ __asm__(“jne 1b”); \ #define ARG_REMOVE() __asm__(“add $136, %rsp”); 现在上面的代码是在没有参数的情况下编写的 – 136是16 * 8 […]

如何连接,评估和字符串化宏?

我试图对宏连接的替换(评估)进行字符串化。 例如: #include #define FOO_ONE 12 #define FOO_TWO 34 #define BAR_ONE 56 #define BAR_TWO 78 #define MAKE_MAC(mac) // … what to do here? void main(int argc, char *argv[]) { printf(“FOO: ” MAKE_MAC(FOO) “\n”); printf(“BAR: ” MAKE_MAC(BAR) “\n”); } 我想要的结果是: FOO: 1234 BAR: 5678 我尝试了几种forms,我认为最好的尝试是这样的: #define STRINGIFY(mac) #mac #define CONCAT(mac1, mac2) STRINGIFY(mac1 ## mac2) #define MAKE_MAC(mac) […]

#define在整个库中的范围?

说我有一个常数: #define PI 3.14 假设我有一个包含多个头文件和源文件的静态库。 如果我在头文件中声明它,它的范围是否适用于所有源文件? 或者源文件是否需要包含带有PI声明的标头?