我最近了解到了我可以在代码开头定义的##功能。我正在尝试编译以下代码:
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <stdio.h>
#include <string>
#define paste(x,y) *x##*y
int main()
{
TCHAR *pcCommPort = "COM";
TCHAR *num = "5";
cout << paste(pcCommPort,num);
return 0;
}
我一直收到以下错误:
expression must have arithmetic or unscoped enum type
我不喜欢我在“定义粘贴”行中使用指针的事实。没有任何指针,它只会返回变量“pcCommPort5”。我想要的是“COM5。”
我试过_tcscat,strcat,strcat_s,visual studio不喜欢这些......
答案 0 :(得分:1)
##
不会连接任意内容(尤其不是字符串)。它的作用是将解析器中的符号合并为一个符号。
让我们删除其中一个*
,看看发生了什么:
#include <iostream>
#define TO_STRING_HELPER(x) #x
#define TO_STRING(x) TO_STRING_HELPER(x)
#define CONCAT(x, y) *x##y
int main() {
char *pcCommPort = "COM";
char *num = "5";
std::cout << TO_STRING(CONCAT(pcCommPort, num)) << std::endl;
}
*pcCommPortnum
此代码中CONCAT
的作用是:
x
展开到pcCommPort
,将y
展开到num
。这给出了表达式*pcCommPort##num
。pcCommPort
和num
连接成一个新符号:pcCommPortnum
。现在表达式是*pcCommPortnum
(请记住,最后一部分(pcCommPortnum
)都是一个符号)。*
,后跟符号pcCommPortnum
。这成为表达式*pcCommPortnum
。请记住,这些是两个不同的符号:*
和pcCommPortnum
。这两个符号紧接着一个接一个。如果我们尝试使用*x##*y
,编译器的作用是:
x
展开到pcCommPort
,将y
展开到num
。这为我们提供了表达式*pcCommPort##*num
。pcCommPort
和*
连接成一个新符号:pcCommPort*
。pcCommPort*
不是有效的预处理令牌。请记住,此时不是两个单独的符号(不是两个符号pcCommPort
后跟*
)。它是一个单个符号(我们称之为token)。如果要连接两个字符串,最好使用std::string
。你不能*做你正在尝试用预处理器做的事情。
*请注意,编译器会将连续的字符串文字合并在一起(即"COM" "5"
将由编译器合并为单个字符串"COM5"
。但这仅适用于字符串文字,因此您必须#define pcCommPort "COM"
和#define num "5"
,此时您可以执行pcCommPort num
(不需要任何其他宏),编译器会将其评估为字符串"COM5"
。但除非你真的知道自己在做什么,否则你应该只使用std::string
。