为什么malloc(sizeof(指针))有效?

Bha*_*tan 8 c malloc gcc pointers

以下代码工作正常:

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

int main()
{
    struct node{
        int a, b, c, d, e;
    };
    struct node *ptr = NULL;
    printf("Size of pointer ptr is %lu bytes\n",sizeof (ptr));
    printf("Size of struct node is %lu bytes\n",sizeof (struct node));
    ptr = (struct node*)malloc(sizeof (ptr));               //Line 1
//    ptr = (struct node*)malloc(sizeof (struct node));    //Line 2

    ptr->a = 1; ptr->b = 2; ptr->c = 3; ptr->d = 4; ptr->e = 5;
    printf("a: %d, b: %d, c: %d, d: %d, e: %d\n",
            ptr->a,ptr->b,ptr->c,ptr->d,ptr->e);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

符合时:

gcc -Wall file.c
Run Code Online (Sandbox Code Playgroud)

我的问题是:为什么这样好?

malloc分配在其参数中指定的字节数.这sizeof ptr是我的64位Linux机器上的8个字节.我认为malloc将提供8个字节但是它如何访问所有变量a,b,c,d,e?是仅使用gcc还是我缺少标准C的东西?

据我所知,"第2行"应该在那里而不是"第1行",但任何一行都可以正常工作.为什么?

Kir*_*rov 11

你在这里有未定义的行为.

malloc 将分配8个字节(如你所说),但这个演员是"坏":

ptr = (struct node*)malloc(sizeof (ptr));
Run Code Online (Sandbox Code Playgroud)

在这一行之后,ptr将指向一个只有8个分配字节的内存块,其余的是一些"随机"字节.所以,制作

ptr->a = 1; ptr->b = 2; ptr->c = 3; ptr->d = 4; ptr->e = 5;
Run Code Online (Sandbox Code Playgroud)

你实际上改变了一些内存,而不仅仅是分配的内存malloc.

换句话说,你正在重写记忆,你不应该触摸.


pb2*_*b2q 8

第1行不正确,不会分配足够的空间.如果以后可以访问结构成员,那只是因为C不会阻止您访问不属于您的内存.

访问ptr->b,ptr-c等等,当你还没有为整个结构分配足够的空间是不确定的行为,并在下次你运行你的代码时,它可能会崩溃,或者你可能最终会在你的程序的其他部分覆盖数据.

要演示此问题,请struct node在第一个之后立即分配一秒.这不能保证证明问题,但您可能会看到类似于以下结果:

struct node *ptr = NULL;
struct node *ptr2 = NULL;

ptr = (struct node*)malloc(sizeof (ptr));  // Your Line 1
ptr2 = malloc(sizeof(struct node));        // alloc another struct on the heap

ptr->a = 1; ptr->b = 2; ptr->c = 3; ptr->d = 4; ptr->e = 5;
ptr2->a = 11; ptr->b = 12; ptr->c = 13; ptr->d = 14; ptr->e = 15;

printf("ptr:  a: %d, b: %d, c: %d, d: %d, e: %d\n",
        ptr->a, ptr->b, ptr->c, ptr->d, ptr->e);
printf("ptr2: a: %d, b: %d, c: %d, d: %d, e: %d\n",
        ptr2->a, ptr2->b, ptr2->c, ptr2->d, ptr2->e);
Run Code Online (Sandbox Code Playgroud)

输出:

ptr:  a: 1, b: 2, c: 3, d: 4, e: 11
ptr2: a: 11, b: 12, c: 13, d: 14, e: 15
Run Code Online (Sandbox Code Playgroud)

注意,ptr->e已经通过赋值修改了ptr2->a,因此您可以看到一个不正确分配的结构正在踩到另一个的内存.这肯定不是你想要的.

  • 没有为结构分配内存,并且分配不足的内存都是同样错误的,即使第二个可能更频繁地导致崩溃.仅仅因为第1行似乎**工作并不意味着它是正确的.始终使用第2行. (2认同)