我可以确定参数是否是字符串文字吗? [英] Can I determine if an argument is string literal?

查看:21
本文介绍了我可以确定参数是否是字符串文字吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Is it possible to determine if an argument passed in macro or function is a string literal at compile time or run time?

例如,

#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 McNellisGMan 进行更正.已更新以正确处理连接的文字,例如 "Hello, " "World!",它们在连接之前会被字符串化.)

YES! (Thanks to James McNellis and GMan for corrections. Updated to correctly handle concatenated literals like "Hello, " "World!" which get stringized before concatenation.)

#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;
}

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

This will stringify the argument before passing it to the function, so if the argument was a string literal, the argument passed to our function will be surrounded with quote characters.

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

If you consider this a string literal:

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

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

I cannot help you. You might be able to use some implementation-defined (or *shudder* undefined) behavior to test whether or not a string is stored in read-only memory, but on some (probably older) systems p could be modified.

对于那些对使用此类功能有疑问的人,请考虑:

For those who question the use of such a function, consider:

enum string_type { LITERAL, ARRAY, POINTER };

void string_func(/*const? */char *c, enum string_type t);

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

Rather than explicitly specifying the second argument to string_function on every call, is_literal allows us to wrap it with a macro:

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

我无法想象为什么它会有所作为,除了在纯 C 中文字不是 const 并且由于某种原因您不想/不能将函数编写为采用 const char * 而不是 char.但是有各种各样的理由想要做某事.有一天,你也可能觉得有必要诉诸可怕的黑客攻击.

I can't imagine why it would make a difference, except in plain C where literals aren't const and for some reason you don't want to/can't write the function as taking a const char * instead of a char. But there are all kinds of reasons to want to do something. Someday you, too may feel the need to resort to a horrible hack.

这篇关于我可以确定参数是否是字符串文字吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆