使用Visual Stduio 2017编译C++如下代码:
sprintf(lps,"length:%"C_LEN_STR"s\r\n",STR_LEN);
发生了以下错误:
error C3688: 文本后缀“C_LEN_STR”无效;未找到文文本运算符或文本运算符模板“operator """"C_LEN_STR”
其中,C_LEN_STR为宏定义:
#define STR_LEN 100
#define TOLEN(arg) #arg
#define C_LEN_STR TOLEN(STR_LEN)
宏展开后应该为字符串: "100"
这个问题在VC6中编译并无问题。
且不说这个编译错误的提示表达上的问题,这"文本运算符"是啥意思?
百度查了一下,找到了这篇文章:
用户定义的文本:https://learn.microsoft.com/zh-cn/cpp/cpp/user-defined-literals-cpp?view=msvc-170
大意为:
在 C++ 中,文本有六个主要类别:整数、字符、浮点、字符串、布尔和指针。 从 C++ 11 开始,可以基于这些类别定义你自己的文本,以便为常见惯用语提供快捷语法,并提高类型安全性。
通过以下形式之一在命名空间范围定义 operator"" 来实现用户定义的文本:
ReturnType operator "" _a(unsigned long long int); // Literal operator for user-defined INTEGRAL literal
ReturnType operator "" _b(long double); // Literal operator for user-defined FLOATING literal
ReturnType operator "" _c(char); // Literal operator for user-defined CHARACTER literal
ReturnType operator "" _d(wchar_t); // Literal operator for user-defined CHARACTER literal
ReturnType operator "" _e(char16_t); // Literal operator for user-defined CHARACTER literal
ReturnType operator "" _f(char32_t); // Literal operator for user-defined CHARACTER literal
ReturnType operator "" _g(const char*, size_t); // Literal operator for user-defined STRING literal
ReturnType operator "" _h(const wchar_t*, size_t); // Literal operator for user-defined STRING literal
ReturnType operator "" _i(const char16_t*, size_t); // Literal operator for user-defined STRING literal
ReturnType operator "" _g(const char32_t*, size_t); // Literal operator for user-defined STRING literal
ReturnType operator "" _r(const char*); // Raw literal operator
template
上例中的运算符名是你提供的任意占位符,但需要前导下划线。 (仅标准库才允许定义不带下划线的文本。)在返回类型中,你可以自定义文本执行的转换或其他操作。 此外,这些运算符中的任何一个都可定义为 constexpr。
具体可见上述文章。总之,文本运算符是C++11新增特性
回到这个编译错误,猜想应该是编译器将“C_LEN_STR ”判断为了用户定义的文本,而实际上这是一个宏定义,误判了,也许这是一个语言特性设计失误?
为了避免这个编译错误,在C_LEN_STR前加个回车,改为:
sprintf(lps,"length:%"
C_LEN_STR"s\r\n",STR_LEN);
编译通过。问题解决。