强制宏参数为字符串文字

问题描述 投票:0回答:1

在查看一些代码时here,我看到一个宏,其中参数需要是字符串文字。

我发现了这个宏(来自 Jenn 的 Gustedt Modern C),它声称满足以下约束:

  • 是字符指针
  • 必须非空
  • 必须是不可变的
  • 必须以 0 结尾

如果我有:

#define SV(str)    (sizeof(str) - 1)

int main(void)
{
    static const char *const s = "hello";
    char word[] = "hello";
    double a = 0.0f;
    double *d = &a;
    
    printf("%zu\n", SV(NULL));
    printf("%zu\n", SV(word));
    printf("%zu\n", SV(d));
    printf("%zu\n", SV(s));
    
    return 0;
}

代码编译正确,没有发出错误或警告,输出为:

7
5
7
7

但是如果我在其扩展中使用空字符串文字,情况就会改变

"" str ""

#define SV(str)         (sizeof("" str "") - 1)

int main(void)
{
    static const char *const s = "hello";
    char word[] = "hello";
    double a = 0.0f;
    double *d = &a;

    printf("%zu\n", SV(NULL));
    printf("%zu\n", SV(word));
    printf("%zu\n", SV(d));
    printf("%zu\n", SV(s));

    return 0;
}

现在如果我编译这个,我会得到:

macro_str.c: In function ‘main’:
macro_str.c:4:33: error: called object is not a function or function pointer
    4 | #define SV(str)         (sizeof("" str "") - 1)
      |                                 ^~
macro_str.c:19:21: note: in expansion of macro ‘SV’
   19 |     printf("%zu\n", SV(NULL));
      |                     ^~
macro_str.c:4:40: error: expected ‘)’ before string constant
    4 | #define SV(str)         (sizeof("" str "") - 1)
      |                                ~       ^~
macro_str.c:19:21: note: in expansion of macro ‘SV’
   19 |     printf("%zu\n", SV(NULL));
      |                     ^~
macro_str.c:20:24: error: expected ‘)’ before ‘word’
   20 |     printf("%zu\n", SV(word));
      |                        ^~~~
macro_str.c:4:36: note: in definition of macro ‘SV’
    4 | #define SV(str)         (sizeof("" str "") - 1)
      |                                    ^~~
macro_str.c:4:32: note: to match this ‘(’
    4 | #define SV(str)         (sizeof("" str "") - 1)
      |                                ^
macro_str.c:20:21: note: in expansion of macro ‘SV’
   20 |     printf("%zu\n", SV(word));
      |                     ^~
macro_str.c:21:24: error: expected ‘)’ before ‘d’
   21 |     printf("%zu\n", SV(d));
      |                        ^
macro_str.c:4:36: note: in definition of macro ‘SV’
    4 | #define SV(str)         (sizeof("" str "") - 1)
      |                                    ^~~
macro_str.c:4:32: note: to match this ‘(’
    4 | #define SV(str)         (sizeof("" str "") - 1)
      |                                ^
macro_str.c:21:21: note: in expansion of macro ‘SV’
   21 |     printf("%zu\n", SV(d));
      |                     ^~
macro_str.c:22:24: error: expected ‘)’ before ‘s’
   22 |     printf("%zu\n", SV(s));
      |                        ^
macro_str.c:4:36: note: in definition of macro ‘SV’
    4 | #define SV(str)         (sizeof("" str "") - 1)
      |                                    ^~~
macro_str.c:4:32: note: to match this ‘(’
    4 | #define SV(str)         (sizeof("" str "") - 1)
      |                                ^
macro_str.c:22:21: note: in expansion of macro ‘SV’
   22 |     printf("%zu\n", SV(s));
      |                     ^~
make: *** [<builtin>: macro_str] Error 1

我的问题是:是否存在任何可能失败的边缘情况或漏洞?如果是这样,我该如何修改它以避免它们?

c c-preprocessor string-literals
1个回答
0
投票

是否存在任何可能失败的边缘情况或漏洞?

这些编译没有抱怨:

printf("%zu\n", SV());
printf("%zu\n", SV(/*comment*/));
printf("%zu\n", SV(-));
printf("%zu\n", SV("abc" - "def"));
© www.soinside.com 2019 - 2024. All rights reserved.