Sizeof 应用于不完整数组类型的参数

发布于 2025-01-11 22:45:47 字数 541 浏览 5 评论 0原文

对于此代码:

int f(int x[])
{
    return sizeof x;
}

GCC 生成:

warning: 'sizeof' on array function parameter 'x' will return size of 'int *'

Clang 生成:

warning: sizeof on array function parameter will return size of 'int *' instead of 'int[]'

问题:如果 x 具有不完整的类型(因为大小不存在),那么它是否期望具有:

error: invalid application of 'sizeof' to incomplete type

Extra:这是否意味着 return 'int *' 的大小 是 GCC/Clang 扩展吗?

For this code:

int f(int x[])
{
    return sizeof x;
}

GCC produces:

warning: 'sizeof' on array function parameter 'x' will return size of 'int *'

Clang produces:

warning: sizeof on array function parameter will return size of 'int *' instead of 'int[]'

Question: if x has incomplete type (since the size is not present), then is it expected to have:

error: invalid application of 'sizeof' to incomplete type

Extra: does it mean that return size of 'int *' is a GCC/Clang extension?

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

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

发布评论

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

评论(4

妄断弥空 2025-01-18 22:45:48

作为函数参数的数组实际上是一个指针。来自 C 标准 关于函数声明符:

将参数声明为“类型数组”应调整为“指向的限定指针”
type'',
其中类型限定符(如果有)是在 [] 中指定的
数组类型推导。如果关键字 static 也出现在 []
数组类型推导,那么每次调用函数时,都会得到对应的值
实际参数应提供对数组第一个元素的访问,其数量至少与
由大小表达式指定的元素。

这意味着:

int f(int x[])
{
    return sizeof x;
}

与此完全相同:

int f(int *x)
{
    return sizeof x;
}

所以 x 确实具有完整的类型并且没有错误。 gcc 和 clang 都有助于生成警告,因为结果可能不是人们所期望的。

An array as an argument to a function is actually a pointer. From section 6.7.6.3p7 of the C standard regarding Function Declarators:

A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to
type’’,
where the type qualifiers (if any) are those specified within the [ and ] of the
array type derivation. If the keyword static also appears within the [ and ] of the
array type derivation, then for each call to the function, the value of the corresponding
actual argument shall provide access to the first element of an array with at least as many
elements as specified by the size expression.

This means that this:

int f(int x[])
{
    return sizeof x;
}

Is exactly the same as this:

int f(int *x)
{
    return sizeof x;
}

So x does have complete type and there is no error. Both gcc and clang are being helpful in generating a warning as the result might not be what one expects.

生死何惧 2025-01-18 22:45:48

不管表面上如何,f 函数的 x 参数不是一个不完整的类型。它是一个指针 (int*),因为任何数组在用作函数的声明参数时在语法上等同于指向数组第一个元素的指针。

因此,sizeof x 表达式的操作数是一个完整类型(指向 int 的指针); GNU 和 Clang 编译器给出的警告只是“提醒”您数组到指针的所谓“衰减”。

要“验证”上述总计等价性,请添加函数的前向声明,使用int* x作为形式参数 - 将有(或应该)没有进一步的警告:

int foo(int* x); // Foward declaration

int foo(int x[]) // Definition - No parameter type conflict
{
    return sizeof x ;
}

Despite appearances, the x parameter to your f function is not an incomplete type. It is a pointer (int*), because any array, when used as a declared parameter of a function is syntactically equivalent to a pointer to the array's first element.

Thus, the operand of your sizeof x expression is a complete type (pointer to int); the warnings given by the GNU and Clang compilers are merely 'reminding' you of this so-called "decay" of the array to a pointer.

To 'verify' the aforementioned total equivalence, add a forward declaration of the function, using int* x as the formal parameter – there will be (or should be) no further warning about that:

int foo(int* x); // Foward declaration

int foo(int x[]) // Definition - No parameter type conflict
{
    return sizeof x ;
}
帅的被狗咬 2025-01-18 22:45:48

问题:如果 x 的类型不完整(因为大小不存在),
那么预计会有:

错误:“sizeof”对不完整类型的无效应用

,当尝试确定不完整类型的大小时,这将是 gcc 发出的常见错误消息,但这不是示例代码中发生的情况。

在函数声明的参数列表中,所有声明为数组类型的参数(包括不完整的数组类型)都会调整为具有相应的指针类型。 C17 6.7.6.3/7 中对此进行了描述:

将参数声明为“类型的数组”应调整为
“指向类型的限定指针”,其中类型限定符(如果有)是
在数组类型派生的 [] 中指定的那些。 [...]

这是源代码的语义问题,而不是运行时转换,尽管它与运行时发生的数组自动转换为指针相吻合(原则上)。

额外:这是否意味着'int *'的返回大小是GCC/Clang
扩展名?

不。警告消息描述了标准 C 的语义(从今以后)。

就其价值而言,当我计划访问参数时,我倾向于更喜欢示例中的形式,就好像它指向数组的第一个成员一样(通过使用 [] 对其进行索引或执行指针算术上)。特别是,我总是将 main 的两参数签名写为:

int main(int argc, char *argv[]);

Question: if x has incomplete type (since the size is not present),
then is it expected to have:

error: invalid application of 'sizeof' to incomplete type

Yes, that would be the usual error message from gcc when one attempts to determine the size of an incomplete type, but that's not what is happening in the example code.

In the parameter list of a function declaration, all parameters declared to have array type -- including incomplete array types -- are adjusted to have corresponding pointer types. This is described in C17 6.7.6.3/7:

A declaration of a parameter as “array of type” shall be adjusted to
“qualified pointer to type”, where the type qualifiers (if any) are
those specified within the [ and ] of the array type derivation. [...]

That is a question of the semantics of the source code, not a runtime conversion, though it dovetails with the automatic conversion of array values to pointers that happens at runtime (in principle).

Extra: does it mean that return size of 'int *' is a GCC/Clang
extension?

No. The warning message describes the semantics of standard C (since forever).

For what it's worth, I tend to prefer the form in your example when I plan to access the parameter as if it pointed to the first member of an array (by indexing it with [] or performing pointer arithmetic on it). In particular, I always write the two-parameter signature of main as:

int main(int argc, char *argv[]);
安静被遗忘 2025-01-18 22:45:48

当您将数组传递给函数时,实际上是将其地址作为指针传递。在数组上使用 sizeof() 只会返回指针的大小。它不会产生错误,因为 sizeof(int*) 是有效的操作

When you pass an array into a function, you are actually passing it's address as a pointer. Using sizeof() on the array will only return the size of a pointer. It will not produce an error as sizeof(int*) is a valid operation

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文