编译时断言以确定指针是否为数组

Vla*_*tov 4 c assertion

目前,我有以下代码块来进行安全字符串复制(它的工作原理):

#define STRCPY(dst, src) do { assert(((void*)(dst)) == ((void*) & (dst))); \
                              strlcpy(dst, src, sizeof(dst)); } while (0)
Run Code Online (Sandbox Code Playgroud)

所以它接受如下构造:

const char *src = "hello";
char dest[5];
STRCPY(dest, src); //hell
Run Code Online (Sandbox Code Playgroud)

并否认以下内容:

void (char *dst) {
    STRCPY(dst, "heaven"); //unknown size of dst
}
Run Code Online (Sandbox Code Playgroud)

问题是代码块会产生一个断言.有没有办法在编译时执行此检查?

所以我想在编译时遇到错误(比如创建一个负大小的数组),而不是在可能的情况下崩溃代码.

Lun*_*din 5

如果标准C可用,那么您可以这样做:

#define STRCPY(dst, src)                                        \
  _Generic(&(dst),                                              \
           char(*)[sizeof(dst)]: strlcpy(dst,src,sizeof(dst)) )
Run Code Online (Sandbox Code Playgroud)

说明:

您不能_Generic在数组类型上使用表达式,因为它不是免于"数组衰减"规则的特殊情况之一(C176.3.2.1§3).因此,通过简单地_Generic((dst), ...在我的示例中使用,dst最终将作为char*表达式的计算时间,然后我们将丢失其原始类型的信息.

但是如果我们使用数组的地址&,我们会利用其中一种特殊情况,并且数组衰减不会发生.相反,我们最终得到一个数组指针,这意味着_Generic必须检查预期类型和大小的数组指针:char(*)[sizeof(dst)].


作为一个侧面注意/安全问题,我从不使用do-while(0)宏并阻止它们,但这是另一个故事.