【问题标题】:How can i identify the size of structure member?如何确定结构成员的大小?
【发布时间】:2017-06-02 12:07:35
【问题描述】:
struct busData{
int busNum;
char str[SIZE+1]; //SIZE  = 1000
};

int main(){
    struct busData *bus = (struct busData*)calloc(5, sizeof(struct busData));


printf("\n%d", sizeof(bus)); //result is 4
free(bus);    
return 0;
    }

现在根据平台显示“4”或“8”。我认为它应该显示 5040 对吗?因为我用calloc() 给了5 值。那么我怎样才能得到5040呢?我一直在使用 3 个元素,直到 'bus+2' 然后我释放了 free(bus);我想知道剩下多少元素(它应该显示 2008)。所以我需要5040?

【问题讨论】:

标签: c pointers structure sizeof


【解决方案1】:
sizeof(bus)

这里bus 是一个指针,所以sizeof() 将返回4,这是您使用的平台中指针的大小。(取决于使用的平台)。
如果你想知道结构体的大小,请使用sizeof(struct busData)sizeof(*bus)

【讨论】:

  • 大小取决于机器,不能确定是4。
【解决方案2】:

您试图输出指针bus 的大小,而不是指针指向的5 个对象。

试试下面的演示程序

#include <stdio.h>
#include <stdlib.h>

#define SIZE    1000

struct busData
{
    int busNum;
    char str[SIZE+1]; //SIZE  = 1000
};

int main(void) 
{
    struct busData *bus = (struct busData*)calloc(5, sizeof(struct busData));
    printf("\n%zu\n", 5 * sizeof( *bus ) );

    return 0;
}

程序输出是

5040

注意转换说明符和用作 printf 调用的参数的表达式

    printf("\n%zu\n", 5 * sizeof( *bus ) );
               ^^     ^^^^^^^^^^^^^^^^^

考虑到指针不提供信息是指向单个对象还是对象数组的第一个对象。因此,使用指针bus,您必须明确指定指针所指向的对象数量。

执行以下语句可以获得相同的结果

printf("\n%zu\n", sizeof( struct busData[5] ) );

【讨论】:

    【解决方案3】:

    现在结果显示为“4”。我认为它应该显示 5040 对吧?

    不,你错了。检查数据类型。

    首先,关于sizeof 运算符,来自C11,章节§6.5.3.4

    sizeof 运算符产生其操作数的大小(以字节为单位),可能是 表达式或类型的括号名称。 大小由类型决定 操作数。 [...]

    bus是一个指针,所以sizeof(bus)sizeof (struct busData*)一样,都是一个指针的大小,根据你的环境,可以给你结果,其中常见的有4 或 8。

    之后,结构元素之间和末尾可以有填充,所以结构定义如下

    struct busData{
    int busNum;
    char str[SIZE+1]; //SIZE  = 1000
    };
    

    定义该类型的变量并尝试通过sizeof 检查大小可能不会在大多数环境中为您提供(4+1000+1) == 1005 字节。

    再次引用,

    [....] 当 应用于具有结构或联合类型的操作数,结果是总数 此类对象中的字节,包括内部和尾随填充。

    因此,您还需要考虑填充。

    也就是说,

       printf("\n%d", sizeof(bus));
    

    实际上导致undefined behavior。你需要写

     printf("\n%zu", sizeof(bus));
    

    sizeof 产生size_t 类型的结果。

    【讨论】:

    • 那么你能告诉我如何获得5040吗?
    • @MukhammadAli 使用指向内存块开头的指针,您不能。如果它是一个数组,sizeof 就可以了。
    • @MukhammadAli 你不能。当您为结构的多个元素分配存储空间时,编译器将永远无法告诉您这个源自任何数据类型大小的内存量。这仅适用于单个数据对象。
    【解决方案4】:

    我认为代码从一开始就搞砸了。 sizeof 的问题已经在其他答案中解释过。

    另一个大问题是这样的:

    因为我用 calloc() 给了 5 个值。那么我怎样才能得到5040呢? 我正在使用 3 个元素,直到 'bus+2' 然后我释放了免费(公共汽车); 我想知道剩下多少元素(它应该显示 2008)。 所以我需要5040?

    这听起来你想在调用free 之后使用剩余的 2 个元素。

    第一:

    你有 1 个指针。编译器可以告诉您指针的大小和指针指向的单个元素的大小。 编译器不知道您为该类型的 1 个以上元素分配了内存,因此无法告诉您与指针大小或 1 个元素大小不同的任何内容。

    第二:

    没有像“使用”一些内存这样的概念。对于编译器和操作系统而言,是否向内存位置写入内容并不重要。它不关心某些字节是否仍然(或再次)填充为 0。

    第三:

    如果您分配一块内存并再次释放它,则 整个 块将被释放并且不能再使用。如果您希望有 2008 个字节仍然可以使用,那您就错了!在调用free 后,您的指针将指向无效地址。之后使用该指针访问内存是未定义的行为

    【讨论】:

      【解决方案5】:

      如何确定结构成员的大小?

      使用指向动态分配内存的指针,无法知道指针指向的内存大小。

      如果您需要知道malloc/calloc 之后的大小,您只需“记住”您malloc/calloced 的大小,即将它保存在一个变量中。

      您可以将它包装在另一个结构中并提供create 函数。比如:

      struct busData{
          int busNum;
          char str[SIZE+1]; //SIZE  = 1000
      };
      
      struct busDataContainer{
          size_t size;
          struct busData* busData;
      };
      
      struct busDataContainer createBusData(size_t n)
      {
          struct busDataContainer c;
          c.size = n * sizeof(struct busData);
          c.busData = calloc(n, sizeof(struct busData));
          return c;
      }
      
      int main(){
          struct busDataContainer bus = createBusData(5);
          printf("\n%zu", bus.size;
          return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 2018-02-11
        • 2011-03-23
        • 1970-01-01
        • 1970-01-01
        • 2021-06-04
        • 2014-01-07
        • 1970-01-01
        • 2015-11-05
        • 2019-12-31
        相关资源
        最近更新 更多