指向结构的指针:理解元素寻址

时间:2014-12-29 18:32:21

标签: c pointers memory-management pool

所以我有这个结构:

typedef struct my_structure_s{
    uint32_t* label;
    uint32_t* data_1;
    uint32_t* data_2;
} my_structure_t;

最终,我正在努力分配单个大块内存,并将指针移动到指向大块内存中的适当位置。这个块足够大,以便我可以为data_1和data_2提供N1和N2元素的空间,其中N1和N2在程序中计算。

实际上,我将会有一些这样的结构,我想最终将它们全部指向这个区域中的适当位置。我知道如何移动指针指向正确的位置,但我无法理解内部指针在内存中的创建位置。

例如我定义:

my_structure_t* my_struct = malloc( sizeof(my_struct) );
my_structure_t example_struct;
my_struct = &example_struct;

现在我想查看相关地址,所以我写道:

printf("Base Address: %p\n", &my_struct);
printf("First Element: %p\n", &(my_struct->label));
printf("Difference: %x\n\n", (uint32_t)&(my_struct->label) - (uint32_t)&my_struct);

由于某种原因,差异是负值!为什么?是的我使用的是32位内核。不应该把第一个元素放在堆旁边,但是要进一步向下吗?另外,为什么内存差异不是0x4而是-0x8?我认为一切都应该对齐......看看它是如何重复相同数据类型的结构......并且该数据类型的sizeof()为4。

其次,如果我没有将指针指向结构的实例,该怎么办?例如,如果我这样做:

my_structure_t* my_struct_2;
my_structure_t* big_pool =  malloc( sizeof(my_structure_t) );
my_struct_2 = big_pool;    

printf("Base Address: %p\n", &my_struct_2);
printf("First Element: %p\n", &(my_struct_2->label));
printf("Difference: %x\n",  (uint32_t)&(my_struct_2->label) - (uint32_t)&my_struct_2);

在这里,这些值非常古怪。有一次,我得到了0x49f02aac的区别。那么实际的标签指针放在内存中的位置是什么?在这种情况下,如何确保标签指针本身的地址在基址之后,而不将基指针指向正常的结构实例?能以某种方式分配吗?

也就是说,如果我在创建结构指针后将标签指针指向某处,那么标签指针本身将存储在哪里?如何确保所有这些内部指针以与定义相同的顺序存储在基指针之后?

是的,我可以定义data_1 [MAX_N1]或其他类似的工作,然后只定义一个结构指针数组,并为每一个分配一个固定的内存大小,但我没有。有各种原因。请坚持我提出的问题。

谢谢!

2 个答案:

答案 0 :(得分:3)

首先,malloc()不分配指针,它为你的struct分配内存,然后它返回一个指向它的指针。完全可能有一个未初始化的指针,或一个指向任何地方的指针(NULL)。

其次,在C中,有三种类型的变量,分别是:

  1. 静态变量(全局变量)。它们一直存在于程序运行中。
  2. 自动变量(本地人)。只要包含它们的代码块正在运行,它们就会存在。
  3. 动态变量(malloc)。它们一直存在,直到它们被释放。
  4. 考虑到这一点你的例子:

    my_structure_t* my_struct = malloc( sizeof(my_struct) );
    my_structure_t example_struct;
    my_struct = &example_struct;
    

    第一个结构是动态的,第二个结构是自动的。然后使指针指向自动指针。记住,你可以指向任何东西。动态变量丢失(泄露)。

    printf("Base Address: %p\n", &my_struct);
    printf("First Element: %p\n", &(my_struct->label));
    

    这很棘手:my_struct是一个指针,但是你得到它的地址,所以得到的是指针类型的自动变量my_struct的地址。

    -8之所以发生是因为您要比较两个局部变量的地址:本地指针my_struct和本地结构变量label的成员example_struct。那些恰好在记忆中如此布局。

    尝试改为:

    printf("Base Address: %p\n", (void*)my_struct);
    printf("First Element: %p\n", (void*)&(my_struct->label));
    

    (顺便说一句:在(void*)时投放到printf("%p")总是一个好主意。

    另一个例子有一个类似的错误:打印结构的地址或指针的值,但不打印指针的地址。

答案 1 :(得分:0)

my_struct是指向my_structure_t的指针。无法保证指针与其指向的对象相关的位置。

根据您对内存位置的评论

,我相信您要测试的内容
printf("Base Address: %p\n", my_struct);
printf("First Element: %p\n", &(my_struct->label));
printf("Difference: %x\n\n", (uint32_t)&(my_struct->label) - (uint32_t)my_struct)

请注意,与您的代码相比,在{2}之前的&之前删除了my_struct

回答您提出的实际问题

  

另外,为什么内存差异不是0x4而是-0x8?

sizeof(my_structure_t*)为8,或者编译器确定example_struct应该是8字节对齐,并在将堆变量添加到堆栈时添加填充。