为什么要在函数头中声明 C 数组参数的大小?

发布于 2024-10-20 05:19:37 字数 198 浏览 6 评论 0原文

谁能告诉我为什么我应该在函数头中指定 C 数组参数的大小?例如:

void foo (int iz[6]) { iz[42] = 43; }

With:

int is[2] = {1,2,3};

我们得到一个有用的错误。也许它有助于评论/文档?

Can anyone enlighten me as to why I should bother to specify the size of a C array argument in a function header? For example:

void foo (int iz[6]) { iz[42] = 43; }

With:

int is[2] = {1,2,3};

we get a useful error. Perhaps it helps with commenting/documentation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

羞稚 2024-10-27 05:19:37

谁能告诉我为什么我应该在函数头中指定 C 数组参数的大小?例如:

void foo (const char sz[6]) { sz[42] = 43; }

,你不应该。当您尝试将数组传递给函数时,真正传递的是指向数组开头的指针。由于函数接收的将是一个指针,因此最好将其编写为明确的:

void foo(char const *sz)

然后,由于现在很清楚该函数没有得到大小的线索,因此将其添加为单独的参数:

void foo(char const *sz, size_t size)

Can anyone enlighten me as to why I should bother to specify the size of a C array argument in a function header? For example:

void foo (const char sz[6]) { sz[42] = 43; }

IMO, you shouldn't. When you try to pass an array to a function, what's really passed is a pointer to the beginning of the array. Since what the function receives will be a pointer, it's better to write it to make that explicit:

void foo(char const *sz)

Then, since it's now clear that the function has been given no clue of the size, add that as a separate parameter:

void foo(char const *sz, size_t size)
森林散布 2024-10-27 05:19:37

这样做的唯一有意义的原因是出于文档目的 - 告诉未来的用户函数期望接收至少包含这么多元素的数组。但即便如此,这也是一个惯例——您必须事先与其他用户达成一致。无论如何,语言(编译器)都会忽略该大小。您的函数声明相当于 void foo(int iz[])void foo(int *iz)

使其对编译器有意义的唯一方法是将其声明为,

void foo (int iz[static 6])

这向编译器承诺该数组将至少有 6 个元素,这意味着编译器将能够使用该假设来优化该代码。此外,如果您确实想采用上述约定,那么专门使用 static 声明数组参数大小更有意义,因为该语言显式定义了此构造的语义。

我不清楚你所说的“我们得到一个有用的错误”是什么意思。该代码

int is[2] = {1,2,3};
is[42] = 42;

不包含任何约束违规。它会产生未定义的行为,但不需要在编译期间产生诊断消息。换句话说,不,我们不会从中得到任何“有用的错误”。

The only meaningful reason to do that is for documentation purposes - to tell the future users that functions expect to receive an array of at least that many elements. But even that is a matter of convention - something that you have to agree upon with other users in advance. The language (the compiler) ignores that size anyway. Your function declaration is equivalent to void foo(int iz[]) and to void foo(int *iz).

The only way to make it somewhat meaningful for the compiler is to declare it as

void foo (int iz[static 6])

which acts as a promise to the compiler that the array will have at least 6 elements, meaning that the compiler will be able to optimize that code using that assumption. Moreover, if you really want to adopt the convention mentioned above, it makes more sense to declare array parameter sizes with static specifically, since the language explicitly defines the semantics of this construct.

What you mean by "we get a useful error" is not clear to me. The code

int is[2] = {1,2,3};
is[42] = 42;

does not contain any constraint violations. It produces undefined behavior, but it is not required to produce a diagnostic message during compilation. In other words, no, we don't get any "useful error" from this.

空城旧梦 2024-10-27 05:19:37

这是一条评论。数组在函数参数中被降级为指针。然而,即使编译器不读取注释,注释仍然有用。

It's a comment. Arrays are demoted to pointers in function parameters. Comments can still be useful however, even if the compiler doesn't read them.

蔚蓝源自深海 2024-10-27 05:19:37

恕我直言,在现代编译器版本(如现代 gcc)中,以前的答案现在是错误的。
事实上,在这些编译器的现代版本中,编译器使用函数头中指定的 arraw 大小来发出非常有用的警告。

例子 :
在 gcc 12 上,如果您指定 :

int f(char string[32]) 

并使用 : 调用该函数,

int main{
char paul[6]="paul"
f(paul);
}

编译器将发出警告,表明您可以在 f 中执行使用 32 个字符的操作,但您仅指向 6 个字节的内存空间。

所以:在现代编译器中,它有助于精确你的意图,并让编译器对你的意图和你编码的内容进行额外的检查。

完整示例:

#include <stdio.h>

void f(char string[32])
{
        printf("%s\n",string);
}

int main(){
        char paul[5]="paul";
        f(paul);
}

将通过:

testi.c: In function ‘main’:
testi.c:12:9: warning: ‘f’ accessing 32 bytes in a region of size 5 [-Wstringop-overflow=]
   12 |         f(paul);
      |         ^~~~~~~
 testi.c:12:9: note: referencing argument 1 of type ‘char[32]’
 testi.c:5:6: note: in a call to function ‘f’
    5 | void f(char string[32])
      |      ^

对 gcc testi.c -o my_executable 进行简单调用

Imho, in modern compiler version (like modern gcc), the previous answers are now wrong.
Indeed, in modern version of those compilers, the size of the arraw specified in the header of a function is used by the compiler to through very useful warning.

Example :
On gcc 12, if you specify :

int f(char string[32]) 

And call the function with :

int main{
char paul[6]="paul"
f(paul);
}

The compiler will through a warning that say that you may does things in f that use 32 char, but that you point only to a 6 bytes memory space.

So : in modern compiler, it help to precise your intention and to let the compiler do additional checking about the concordance of your intention and what you have coded.

Full example :

#include <stdio.h>

void f(char string[32])
{
        printf("%s\n",string);
}

int main(){
        char paul[5]="paul";
        f(paul);
}

Will through :

testi.c: In function ‘main’:
testi.c:12:9: warning: ‘f’ accessing 32 bytes in a region of size 5 [-Wstringop-overflow=]
   12 |         f(paul);
      |         ^~~~~~~
 testi.c:12:9: note: referencing argument 1 of type ‘char[32]’
 testi.c:5:6: note: in a call to function ‘f’
    5 | void f(char string[32])
      |      ^

for a simple call to gcc testi.c -o my_executable

少女的英雄梦 2024-10-27 05:19:37

当您想要告诉客户端代码它必须传递已定义大小的数组时,这是一个有用的注释,即:

void foo(const char bar[5]);
/* It is expected that foo function receives an array of size 5 */

然而,文档在代码检查中不会替换:

void foo(const char bar[5])
{
    if (!bar) error();
    if (strlen(bar) != 4) error();
    /* ... */
}

It is a useful comment when you want to tell to client code that it must pass an array of defined size, i.e:

void foo(const char bar[5]);
/* It is expected that foo function receives an array of size 5 */

Yet, documentation doesn't replace in code checks:

void foo(const char bar[5])
{
    if (!bar) error();
    if (strlen(bar) != 4) error();
    /* ... */
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文