【问题标题】:what's the correct way to malloc struct pointer using sizeof?什么是使用 sizeof 的 malloc 结构指针的正确方法?
【发布时间】:2015-04-07 08:36:23
【问题描述】:

想象一下我有以下结构

struct Memory {
    int type;
    int prot;
};

typedef struct Memory *Memory;

如何使用 malloc() 对其进行初始化?

Memory mem = malloc(sizeof(Memory));

或

Memory mem = malloc(sizeof(struct Memory));

正确的分配方式是什么?

【问题讨论】:

  • 您的typedef 在很多层面上都是错误的……这是一场等待发生的意外,真的。无论哪种方式,写struct memory { <members> }; 然后像这样分配struct memory *mem = malloc(sizeof *mem);
  • 你认为分配一个对象需要多少内存?可能是你要分配的对象类型的大小?
  • @EliasVanOotegem 谢谢。那么正确的尺寸应该是多少?是 8 字节还是 4 字节?
  • @juanchopanza,这就是我不确定的。我会使用我的结构作为指针,即 mem->type = 1;而不是 mem.type = 1。所以我的结构应该是 8 个字节还是 4 个字节?
  • 你真的应该花一些时间学习什么是结构和指针,因为你似乎有一些误解。您不能“将我的结构用作指针”。

标签: c


【解决方案1】:

您的结构声明有点混乱,并且 typedef 在许多层面上都是错误的。以下是我的建议:

//typedef + decl in one
typedef struct _memory {
    int type;
    int prot;
} Memory;

然后像这样分配:

Memory *mem = malloc(sizeof *mem);

像这样读取malloc 调用:“分配存储mem 指向的任何类型所需的内存量”。如果将 Memory *mem 更改为 Memory **mem,它将分配 4 或 8 个字节(取决于平台),因为现在它可能会分配 8 个字节,具体取决于 int 的大小以及编译器的方式填充结构check wiki for more details and examples。

使用sizeof *<the-pointer>一般被认为是分配内存的更好方式,但如果你愿意,你可以写:

Memory *mem = malloc(sizeof(Memory));
Memory *mem = malloc(sizeof(struct _memory));

他们都做同样的事情。请注意,如果您 typedef 一个结构,那可能是因为您想抽象某些东西的内部工作,并想编写某种 API。在这种情况下,您应该尽可能不使用struct _memory,而支持Memory 或*<the-pointer> 反正

如果你想给typedef一个指针,那么你可以这样写:

typedef struct _memory {
    int type;
    int prot;
} *Memory_p;

在这种情况下:

Memory_p mem = malloc(sizeof *mem);

可能似乎违反直觉,但它是正确的,因为是这样的:

Memory_p mem = malloc(sizeof(struct _memory));

但是这个:

Memory_p mem = malloc(sizeof(Memory_p));

是错误的(它不会分配结构所需的内存,而是分配内存来存储指向它的指针)。

这可能是个人喜好问题,但我个人认为typedefs 模糊了某些内容。在许多情况下,这是为了更好(即FILE*),但是一旦API 开始隐藏您正在使用指针的事实,我开始有点担心。它往往使代码更难阅读、调试和记录......

你可以这样想:

int *pointer, stack;

* 运算符修改给定类型的变量,指针 typedef 两者兼而有之。这只是我的看法,我敢肯定有很多程序员比我更熟练使用指针类型定义。
但大多数时候,指针 typedef 伴随着自定义分配器函数或宏,因此您不必编写像 Memory_p mem = malloc(sizeof *mem); 这样看起来很奇怪的语句,而是可以编写可以定义的 ALLOC_MEM_P(mem, 1);如:

#define ALLOC_MEM_P(var_name, count) Memory_p var_name = malloc(count * sizeof *var_name)

什么的

【讨论】:

  • 即使在抽象的情况下——通过使用不完整/不透明的类型来隐藏结构成员,我仍然不会在 typedef 中隐藏指针。因为如果你这样做了,用户会将该类型的变量视为数据块而不是指针。并且在不完整/不透明类型的情况下,您会将分配留给该代码模块的“成员函数”,而不是用户。 Here is an example.
  • @Lundin:我完全同意。我不认为指针类型定义是一个好主意,我想我已经说清楚了(如果不是,我会编辑我的答案)。我也同意你的观点,如果你 typedef 在某处的标头中的类型不完整,那么无论如何你都需要提供一个完整的 API,包括分配函数,就像 the lib I'm currently working with 的情况一样 not 使用指针类型定义,但确实使用不完整的类型
【解决方案2】:

两者

 typedef struct Memory * Memory;

和

 Memory mem = malloc (sizeof (Memory));

错了。正确的做法是:

typedef struct memory
{
     int type;
     int prot;
} *MEMPTR;

或

struct memory
{
     int type;
     int prot;
};

typedef struct memory *MEMPTR;

结构的名称应该不同于指向它的指针的名称。

【讨论】:

    【解决方案3】:

    这个结构

    struct {
        int type;
        int prot;
    } Memory;
    

    定义一个名为 Memory 的对象,该对象具有未命名的结构类型。

    因此下一个构造

    typedef struct Memory *Memory;
    

    定义 1) 一种新类型struct Memory,它与上面的定义和名称 Memory 没有任何共同之处。和 2) 另一个新类型名称 Memory,它是指向 struct Memory 的指针。

    如果这两种结构都存在于同一个编译单元中,那么编译器将发出错误,因为 typedef 声明中的名称 Memory(指针的名称)试图重新声明未命名结构类型的对象同名Memory。

    我认为你的意思是以下

    typedef struct Memory {
        int type;
        int prot;
    } Memory;
    

    在这种情况下,您可以使用类似 malloc 的两条记录

    Memory *mem = malloc( sizeof( Memory ) );
    

    和

    struct Memory *mem = malloc( sizeof( struct Memory ) );
    

    或

    Memory *mem = malloc( sizeof( struct Memory ) );
    

    或

    struct Memory *mem = malloc( sizeof( Memory ) );
    

    因为现在两个标识符 Memory 位于两个不同的名称空间中,第一个与标签 struct 一起使用,第二个在没有标签结构的情况下使用。

    【讨论】:

    • 我修复了我认为是代码中的错误。请确认我没有破坏任何东西。
    • @anatolyg 谢谢。好像有错别字。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-14
    • 1970-01-01
    • 1970-01-01
    • 2018-04-03
    • 1970-01-01
    • 2010-09-18
    • 1970-01-01
    相关资源
    最近更新 更多