我正在尝试在编译时计算字符串文字的长度.为此,我使用以下代码:
#include <cstdio>
int constexpr length(const char* str)
{
return *str ? 1 + length(str + 1) : 0;
}
int main()
{
printf("%d %d", length("abcd"), length("abcdefgh"));
}
Run Code Online (Sandbox Code Playgroud)
一切都按预期工作,程序打印4和8.由clang生成的汇编代码显示结果在编译时计算:
0x100000f5e: leaq 0x35(%rip), %rdi ; "%d %d"
0x100000f65: movl $0x4, %esi
0x100000f6a: movl $0x8, %edx
0x100000f6f: xorl %eax, %eax
0x100000f71: callq 0x100000f7a ; symbol stub for: printf
Run Code Online (Sandbox Code Playgroud)
我的问题:标准是否保证length函数将在编译时进行评估?
如果这是真的,编译时字符串文字计算的大门刚刚为我打开...例如,我可以在编译时计算哈希值等等......
在:C++ FAQ - 其他技术问题 - [39.6]对于需要将两个令牌粘贴在一起的宏应该怎么做?
有人可以向我解释原因吗?我所读到的只是相信我,但我不能仅仅相信某事,因为有人这么说.
我尝试了这种方法,但我找不到任何错误:
#define mymacro(a) int a ## __LINE__
mymacro(prefix) = 5;
mymacro(__LINE__) = 5;
int test = prefix__LINE__*__LINE____LINE__; // fine
Run Code Online (Sandbox Code Playgroud)
那么为什么我需要这样做呢(引自网页):
但是,当您使用##时,需要双层间接.基本上你需要为"令牌粘贴"创建一个特殊的宏,例如:
Run Code Online (Sandbox Code Playgroud)#define NAME2(a,b) NAME2_HIDDEN(a,b) #define NAME2_HIDDEN(a,b) a ## b相信我 - 你真的需要这样做!(并且请没有人写信给我说它有时可以在没有第二层间接的情况下工作.尝试用__ LINE__连接一个符号然后看看会发生什么.)
编辑:有人也可以NAME2_HIDDEN在下面宣布之前解释他为什么使用?NAME2_HIDDEN在使用宏之前定义宏似乎更合乎逻辑.这是某种伎俩吗?
这可以使用模板吗?
有两个字符串常量.它们来自不同模块中的定义.它们必须相等,否则如果它们不相等,我将引发编译时错误.我可以使用模板吗?
#define MY_STRING "foo"
CompileAssertIfStringsNotEqual(MY_STRING, HIS_STRING);
Run Code Online (Sandbox Code Playgroud)
PS我被假设"abc"[0]是常量表达式而被欺骗.它不是.在语言中奇怪的遗漏.如果"abc"[0]是constand表达式,那将是可能的.
我有一个C程序,它具有特定于平台的定义,可以访问低级硬件.在某些平台上,两个宏指向同一个变量,而另一个平台则不同:
//Platform_One.h
#define FOO_PORT (io.portA)
#define BAR_PORT (io.portB)
//Platform_Two.h
#define FOO_PORT (io.portC)
#define BAR_PORT (io.portC) //same
Run Code Online (Sandbox Code Playgroud)
我有一些初始化代码根据#defines是否相同而不同.从概念上讲,我喜欢这样的代码:
callback_struct_t callbacks[] = {
#if FOO_PORT == BAR_PORT //unfortunately invalid
{&FOO_PORT, handle_foo_bar_func},
#else
{&FOO_PORT, handle_foo_func},
{&BAR_PORT, handle_bar_func},
#endif
{0,0}
};
Run Code Online (Sandbox Code Playgroud)
如果两个任意宏具有相同的定义,是否有可靠的方法在编译时进行测试?
假设我有
#define Name Joe
Run Code Online (Sandbox Code Playgroud)
有没有办法区分宏的不同值.以下不起作用,但你明白了
#if Name==Joe
// some code
#elif Name==Ben
// some alternative code
#endif
Run Code Online (Sandbox Code Playgroud)
我想用它来生成来自相同源代码的各种目标文件.源差异很小,因此可以很容易地进行宏观控制.宏将通过-DName=Joe编译器标志传入.另请注意,这Name将是一个实际的符号名称,因此我们不能使用基于#define Joe 1等的技巧.
强制编辑请注意,这个类似的问题实际上处理的是字符串值宏.而且那里的答案没有帮助.接受的答案避免了问题(但没有解决),另一个答案strcmp在宏中使用,它依赖于扩展等.
我想知道是否可以将在编译行上带参数的宏传递给gcc或其他C/C++编译器.
我以前从未见过这个,但它实际上对于我一直在做的一些OpenCL开发很有用,我想用一个可以在编译时替换的宏来替换一个函数名.
以下是一个例子:
int y, x = 0;
y = HASH(x);
Run Code Online (Sandbox Code Playgroud)
如果可以在编译行上将HASH定义为宏,那将是很好的,所以当我编译程序时,我可以根据需要重新定义HASH.例如,如果我能这样做会很棒gcc -DHASH(X)=(hash_fcn1(X)) program.c -o program,但我以前从未见过这种事.
我用clBuildProgram尝试过但没有运气.
我意识到我可以让另一个程序通过程序并将正确的函数名替换为HASH,但我想知道是否有一种简单的方法可以在不使用sed,awk或字符串替换等工具的情况下执行此操作或者用我选择的语言编写正则表达式库.
另一个解决方案是在命令行上定义一个平面宏,然后在实际源文件中有一系列保护,控制如何在源文件中定义宏,例如在这个其他帖子中如何比较C中的字符串条件预处理程序指令.
有没有更好的方法来做到这一点(在 GCC C 中)?
我试图定义一些代表硬件平台的符号,用于条件编译。
但我也想要描述硬件的可打印字符串(用于诊断)。
理想情况下,我希望能够做到:
#define HARDWARE "REV4C"
#if (HARDWARE == "REV4C")
#define LED_RED // define pin addresses, blah blah...
#endif
printf("HARDWARE %s\n", HARDWARE);
Run Code Online (Sandbox Code Playgroud)
但我不认为这在 C 中是允许的。这有效,但它很难看:
#define REV4C (403) // symbols for conditional compilation
#define REV421 (421)
//#define HARDWARE REV4C // choose hardware platform (just one)
#define HARDWARE REV421
#if (HARDWARE == REV421) // define strings for printing
#define HARDWARE_ID "REV421"
#elif (HARDWARE == REV4C)
#define HARDWARE_ID "REV4C"
#else
#define HARDWARE_ID "unknown"
#endif
#if (HARDWARE == REV421) …Run Code Online (Sandbox Code Playgroud) 使用以下代码,当我打算获得"NOT VGA"时,我总是将"VGA"作为输出
#include<stdio.h>
#include<conio.h>
#define ADAPTER NVGA
#if ADAPTER==VGA
int main()
{
printf("VGA");
getch();
return 0;
}
#else
int main()
{
printf(" NOT VGA");
getch();
return 0;
}
#endif
Run Code Online (Sandbox Code Playgroud) 我想将宏定义为字符串,稍后在编译时包含基于字符串比较的代码:
#include <iostream>
#include <string_view>
constexpr bool strings_equal(char const * a, char const * b) {
return std::string_view(a)==b;
}
#define FOO "bar"
int main() {
#if strings_equal( FOO, "bar") == 0
std::cout << "got a bar!" << '\n';
#endif
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译这个
$ g++ -std=c++17 test.cpp -o my_test
Run Code Online (Sandbox Code Playgroud)
给出错误:
test.cpp:12:18: error: missing binary operator before token "("
12 | #if strings_equal( FOO, "bar") == 0
| ^
Run Code Online (Sandbox Code Playgroud)
编辑:
看来#if指令是否在函数内部很重要,因为如果它在函数内部,我们可以用它替换它if constexpr (...) { ... }但是如果它在 …