传递给函数时,如何强制警告使用错误大小的数组?

klu*_*utt 5 c arrays casting undefined-behavior language-lawyer

假设您有一个将字符串作为参数的函数:

void foo(char *arg);
Run Code Online (Sandbox Code Playgroud)

如果我们确定数组(不要与字符串长度混淆,谢谢chux)总是有一定的大小,比方说 8,那么我们可以改为:

void bar(char (*arg)[8]);
Run Code Online (Sandbox Code Playgroud)

然后像这样调用它:

char str[8] = "Hello";
bar(&str);
Run Code Online (Sandbox Code Playgroud)

我们需要添加&它才能正常工作,但是如果您传递大小或类型错误的数组,上面的代码将发出警告,这正是我想要实现的。但是我们显然需要稍微修改一下身体。所以我的问题很简单,这种包装技术是否可行:

void bar(char (*arg)[8]) {
    char *tmp = (char*) arg;
    foo(tmp);
}
Run Code Online (Sandbox Code Playgroud)

我在这里试图实现的是,如果使用大小错误的数组调用,则应该发出警告。上述解决方案安全吗?将指向char数组的指针转换为指向char的指针是否安全?我试过了,它工作正常,并且没有发出警告-Wall -Wextra -pedantic。一旦我改变了我的大小,str我就会得到:

<source>: In function 'main':
<source>:18:9: warning: passing argument 1 of 'bar' from incompatible pointer type [-Wincompatible-pointer-types]
   18 |     bar(&str);
      |         ^~~~
      |         |
      |         char (*)[9]
<source>:9:17: note: expected 'char (*)[8]' but argument is of type 'char (*)[9]'
    9 | void bar(char (*arg)[8]) {
      |          ~~~~~~~^~~~~~~
Run Code Online (Sandbox Code Playgroud)

这正是我想要的。但它是安全的,还是UB?我想这样做,不仅通过包装器,而且还通过重写原始函数,例如

void foo(char (*argaux)[8]) {
    char *arg = *argaux;
    // Copy body of original foo
Run Code Online (Sandbox Code Playgroud)

我知道我可以使用结构实现基本相同的目的,但我想避免这种情况。

可运行代码:https : //godbolt.org/z/GnaP5ceMr

Lun*_*din 3

char *tmp = (char*) arg;是错误的,这些不是兼容的指针类型。不过你可以轻松解决这个问题:

char *tmp = *arg;
Run Code Online (Sandbox Code Playgroud)

*arg给出 a char[8],然后衰减为指向其第一个元素的指针. 这是安全且明确的。是的,指针在 C 中比按值传递具有更强的“类型”,因此编译器会识别是否传递了错误大小的数组。

但请注意,这会导致其他问题:您将不再具有 const 正确性。
请参阅数组指针的 Const 正确性?