我可以确定参数是否是字符串文字?

是否可以确定在宏或函数中传递的参数在编译时或运行时是否是字符串文字?

例如,

#define is_string_literal(X) ... ... is_string_literal("hello") == true; const char * p = "hello"; is_string_literal(p) == false; 

要么

 bool is_string_literal(const char * s); is_string_literal("hello") == true; const char * p = "hello"; is_string_literal(p) == false; 

谢谢。

是! (感谢James McNellis和GMan进行更正。更新以正确处理像"Hello, " "World!"这样的连接文字"Hello, " "World!"它们在连接之前被串行化。)

 #define is_literal_(x) is_literal_f(#x, sizeof(#x) - 1) #define is_literal(x) is_literal_(x) bool is_literal_f(const char *s, size_t l) { const char *e = s + l; if(s[0] == 'L') s++; if(s[0] != '"') return false; for(; s != e; s = strchr(s + 1, '"')) { if(s == NULL) return false; s++; while(isspace(*s)) s++; if(*s != '"') return false; } return true; } 

这将在将参数传递给函数之前对其进行字符串化,因此如果参数是字符串文字,则传递给我们函数的参数将被引号字符包围。

如果你认为这是一个字符串文字:

 const char *p = "string"; // should is_literal(p) be true or false? 

我不能帮你。 您可以使用某些实现定义(或* shudder * undefined)行为来测试字符串是否存储在只读内存中,但是在某些(可能是较旧的)系统上可以修改p

对于那些质疑使用这种function的人,请考虑:

 enum string_type { LITERAL, ARRAY, POINTER }; void string_func(/*const? */char *c, enum string_type t); 

string_function在每次调用时显式指定string_function的第二个参数, is_literal允许我们用宏包装它:

 #define string_func(s) \ (string_func)(s, is_literal(s) ? LITERAL : (void *)s == (void *)&s ? ARRAY : POINTER) 

我无法想象为什么它会有所作为,除了在普通的C中,文字不是const并且由于某种原因你不想/不能把函数写成const char *而不是char 。 但是有各种各样的理由要做某事。 总有一天,你也可能觉得有必要采取可怕的黑客行为。

通过以下技术了解编译时(如上所述)。 您可以确定给定参数是否是字符串文字。 如果它是一些数组或指针,如const char x[], *p ; 那么它会抛出编译器错误。

 #define is_string_literal(X) _is_string_literal("" X) bool _is_string_literal (const char *str) { return true; } // practically not needed 

[注意:我之前的回答是由专家投票决定的,并且在编辑后仍未被接受或投票。 我正在提出另一个相同内容的答案。]

不可以。字符串文字只是char (在C中)或const char (在C ++中)的数组。

您无法区分字符串文字和其他一些char数组(在C ++中):

 const char x[] = "Hello, World!"; 

试试这个:

 #define is_string_literal(s) \ (memcmp(#s, "\"", 1) == 0) 

根据C / C ++变量命名约定,变量名必须以“_”或字母开头。

我有一个类似的问题:我想这么说

 MY_MACRO("compile-time string") 

是合法的,那

 char buffer[200]="a string"; MY_MACRO(buffer) 

是合法的,但不允许

 MY_MACRO(szArbitraryDynamicString) 

我使用了GCC的__builtin_types_compatible_p和MSVC的_countof,它们似乎以拒绝短字符串文字为代价正常工作。