【问题标题】:sizeof operator shows wrong size of struct in csizeof 运算符在 c 中显示错误的结构大小
【发布时间】:2021-05-06 02:33:47
【问题描述】:

拥有这个简单的代码:

#include <stdio.h>

typedef struct
{
    int a;
    char c;
} foo;

void func(void *arg)
{
    printf("sizeof arg: %ld\n", sizeof(*arg));
}

int main()
{
    foo f = {6, 'c'};
    func(&f);

    printf("the real sizeof struct foo: %ld\n", sizeof(f));
}

输出:

sizeof arg: 1
the real sizeof struct foo: 8

如您所见,该函数显示错误的结果。如果原因是invalid application of ‘sizeof’ to incomplete type,那为什么会显示sizeof arg: 1void 不是 1 字节长,而是不完整的类型,那为什么会是这个结果呢?

【问题讨论】:

  • 您对一个考虑不周的语言扩展感到困惑,一些具有邪恶幽默感的恶作剧者决定在 GCC 中默认启用该扩展。我的建议是禁用所有语言扩展。 -std=c11 -Wall -Werror -pedantic 是一种方法。
  • 鉴于void *argsizeof( *arg ) 是无效代码。您不能取消引用 void * 指针。

标签: c sizeof void incomplete-type


【解决方案1】:

您正试图获得 C 标准不允许的 void 的大小。但是,某些实现将 sizeof(void) 定义为 1,这就是您在此处看到的。

函数无法知道你传递给它的void *实际上是foo *。您将需要其他方式来传达该信息。

【讨论】:

    【解决方案2】:

    此声明

    printf("sizeof arg: %ld\n", sizeof(*arg));
    

    不正确。表达式*arg 具有不完整类型void。你需要写

    printf("sizeof arg: %ld\n", sizeof(* ( foo * )arg));
    

    C 的早期版本没有void 类型。相反,char 类型被用作void 类型。由于sizeof( char ) 始终等于1,因此一些向后兼容旧C 规范的编译器将sizeof( void ) 设置为1,尽管从C 标准的角度来看这是不正确的。

    【讨论】:

      【解决方案3】:

      结果应该是一个诊断结果,因为sizeof (void)sizeof (*arg) 解析为)是一个违反约束

      6.5.3.4 sizeof_Alignof 运算符

      约束

      1    sizeof 运算符不得应用于具有函数类型或 不完整的类型,这种类型的括号名称,或表达式 指定位域成员。 _Alignof 运算符不应应用于 函数类型或不完整类型。
      C 2011 Online Draft

      void 是一个无法完成的不完整类型 - 您无法创建该类型的对象,因此在其上使用 sizeof 是一种编码错误,句号。

      然而,出于某种原因,某些实现决定让 sizeof (void) 评估为 1,除非您处于“迂腐”模式。显然有人认为它在某些情况下很有用,但我不建议使用它。

      【讨论】:

      • 出于某种奇怪的原因,我无法将“以一种让新程序员感到困惑的方式破坏语言(字面意思!)”与“有用”联系起来。
      • @AndrewHenle — 与 GCC 团队进行讨论(并且,AFAIK,clang 实现 sizeof(void) == 1 以与 GCC 兼容)。 OTOH,影响 GCC 的决定可能为时已晚 20 年;向后兼容性意味着它永远存在。见Arithmetic on void and function pointers
      猜你喜欢
      • 2016-06-27
      • 2011-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-03
      相关资源
      最近更新 更多