【问题标题】:Struct pointer syntax confusion结构指针语法混乱
【发布时间】:2016-08-22 03:30:18
【问题描述】:

您好,我对 c 比较陌生,想知道是否有人可以解释我正在使用以下代码做什么。

我有一个结构:

typedef struct free_list_header {
   u_int32_t magic;  // ought to contain MAGIC_FREE
   vsize_t size;     // # bytes in this block (including header)
   vlink_t next;     // memory[] index of next free block
   vlink_t prev;     // memory[] index of previous free block
} free_header_t;

我正在使用以下函数在函数中对其进行初始化...

void vlad_init(u_int32_t size)
{

   int sizePow2 = pow(2, ceil(log(size)/log(2)));
   memory = malloc(sizePow2*sizeof(char));
   memory_size = sizePow2;
   strategy = BEST_FIT;

   free_header_t *freeHeader = (free_header_t*)memory;

   freeHeader->magic = MAGIC_FREE;    // the unique value
   freeHeader->size = memory_size;    // amount we malloc'd
   freeHeader->next = 0;              // position of next free block
   freeHeader->prev = 0;              // position of prev free block     
   free_list_ptr = 0;
}

我的问题是我到底在做什么,为什么有必要?

free_header_t *freeHeader = (free_header_t*)memory;

所以...我通过指向名为“freeHeader”的新结构来声明它?那是我分配的内存中指向它的指针吗?所以这是一种将结构放入 malloc 区域以从我初始化它的函数中访问它的方法?

【问题讨论】:

  • 他的代码是您编写的,还是作为作业或教程的一部分提供给您的?因为感觉怪怪的。比如,为什么要使用 char 的大小而不是 struct 的大小来初始化内存?为什么不直接初始化freeHeader,而不是先初始化memory,然后再进行赋值?
  • 嗯……您的术语不清楚,但这可能是问题的一部分。 sizePow2 是什么?它最好至少和memory_size 一样大,否则你(可能)会遇到问题。或者问题出在memory_size?或者两者兼而有之。
  • 所以它是一个内存分配器,初始化函数接受一个数字并将 2 的最小幂分配给 malloc 至少那么多。 memory_size ==sizePow2,我将编辑并添加整个函数。
  • 注释“# bytes in this block (including header)”表明内存分配应该覆盖结构的四个成员的内存,加上一些用于其他目的的空闲内存,所以分配结构的大小不会很好,在这里。空闲内存将是结构本身地址的一个恒定偏移量,因此可能的意图是以这种方式访问​​它。大概这是某种内存分配器的一部分,尽管它使用标准内存分配器来完成它的工作。
  • sizeof (char) 定义为 1。

标签: c pointers struct malloc


【解决方案1】:

Malloc 返回一个 void 指针(类型 void*)。这意味着它返回一个指向内存地址的指针,并且该指针未指向任何特定类型。所以在这行之后:

memory = malloc(sizePow2*sizeof(char)); //sizePow2 is n bytes to allocate

memory 是一个类型为 (void *) 的指针。

free_header_t *freeHeader = (free_header_t*)memory;

在这里,您正在创建一个名为 freeHeader 的指针,该指针指向包含 free_header_t 类型的内存地址 由于您明确表示此指针指向 free_header_t 类型的地址,因此您将另一侧(当前为 void * 类型)转换为将其匹配为 free_header_t *。

注意,在 C 中,这是可行的,但不是必需的。编译器会自动将 void * 转换为您需要的任何类型。然而,编写这样的代码是一种很好的做法,在 C++ 中你需要明确地这样做。

【讨论】:

  • A cast 是显式转换; void* 类型的值被隐式转换 为任何对象指针类型。显式转换malloc 的结果在C 中不是 好的做法(在C++ 中使用malloc 根本不是好的做法)。如果您需要编写同时编译为 C 和 C++ 的代码,则强制转换是必要的,但这是一个罕见的要求。
  • 此外,memory 的声明未在问题中显示,因此说它“是void * 类型的指针”充其量只是猜测。据我们所知,它也可能是free_header_t * 类型。
  • @KeithThompson 强制转换 malloc 如果编写在 C 和 C++ 上编译的代码?
  • @noob:差不多。在 C 中强制转换是不必要的(并且可以掩盖某些错误)。在 C++ 中,您通常使用 new 分配内存,而不是 malloc()
【解决方案2】:
free_header_t * freeHeader = (free_header_t*)memory;

您声明了一个指向名为 freeHeader 的 free_header_t 结构的指针(不是实际的结构),并为它分配了名为 memory 的指针的值。因为内存是指向 char 的指针,而你的是指向其他东西的指针,所以你使用了强制转换。

您当前只有一个指向分配区域的指针(大小为 sizePow2*sizeof(char) - 请注意,结构的大小应小于或等于分配内存的大小) .

【讨论】:

    【解决方案3】:

    您的代码基本上等同于:

    free_header_t *freeHeader = malloc(sizePow2 * sizeof(char));
    

    它正在分配一个包含sizePow2 字节的内存块,然后将其用作free_list_header 结构的地址。

    它使用memory 变量的原因是因为一些其他代码将使用nextprev 成员作为该内存块的索引。顾名思义,这个结构体只包含内存块开头的数据,其余的内存由其他结构体管理。

    【讨论】:

      【解决方案4】:
      memory = malloc(sizePow2*sizeof(char));
      

      你在这里分配了一些内存。最好只使用

      memory = malloc(sizeof(struct free_list_header));
      

      存储结构的对象。

      free_header_t *freeHeader = (free_header_t*)memory;
      

      在这里,您声明了一个指向先前分配的内存的指针。从技术上讲,您没有声明结构的对象。并且您没有将结构放入 malloc-ed 区域,而是将 malloc-ed 区域视为结构的对象。

      free_header_t freeHeader = {0}; 将声明结构的一个对象。

      【讨论】:

        【解决方案5】:

        每次调用malloc() 函数时,操作系统都会返回一个内存地址。当您将此指针转换为特定类型时,您会告诉编译器存储在分配的内存中的每个元素都将消耗指定类型的大小,这让事情变得更容易。

        假设您声明了一个 uint64_t* 并且分配的大小是 uint64_t 大小的 100 倍,因此一旦 uint64_t 占用 8 个字节,您就要求操作系统占用 800 个字节。如果你不投这个指针,每次你用your_variable++增加地址,你的程序只会跳过一个字节,你会进入“数字中间,会得到一个奇怪的值”,但是如果你投你的指针到 uint64_t 并用your_variable++ 增加地址,您的程序将跳过 8 个字节,直接转到下一个数字。

        在您的示例中,您告诉操作系统您的指针将存储free_header_t 的类型。您没有义务这样做,但这是一种非常好的做法。

        是的,如果你把这个地址返回给另一个函数,另一个函数可以很容易地改变这个内存区域中存储的值。

        希望对你有帮助!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-07-03
          • 1970-01-01
          相关资源
          最近更新 更多