不是使用sizeof(type),而是使用sizeof * p,它安全又正确吗?

bhu*_*ura 4 c malloc

使用起来安全吗,此代码使用gcc 4.9.2编译,没有任何错误或警告

widget *p;
...
p = malloc(sizeof *p);
Run Code Online (Sandbox Code Playgroud)

我在SEI CERT C编码标准网站上找到了它。

单击此处 -没有类型不匹配的问题,无需强制转换。您每次分配正确的内存量。


struct widget;
typedef struct widget widget_t;

struct gadget;
typedef struct gadget gadget_t;

widget_t *newWidget(void)
{
    widget_t *p = malloc(sizeof *p);
    if (p) 
        /* initialize members of *p as necessary */
    return p;
} 

gadget_t *newGadget(void)
{
    gadget_t *p = malloc(sizeof *p);
    if (p)
        /* initialize members of *p as necessary */
    return p;
}

void deleteWidget(widget_t **p)
{
     /* delete any subelements of *p */
     free(*p);
     *p = NULL;
}

void deleteGadget(gadget_t **p)
{
    /* delete any subelements of *p */
    free(*p);
    *p = NULL;
}

...

widget_t *p = newWidget();
gadget_t *g = newGadget();

if (p)
    /* do stuff with p */

if (g)
    /* do stuff with g */
...
deleteWidget(&p); 
deleteGadget(&g); 

Run Code Online (Sandbox Code Playgroud)

pmg*_*pmg 5

It's a good coding practice!

Imagine this code

struct structv1 *p1 = malloc(sizeof (struct structv1));
struct structv1 *p2 = malloc(sizeof *p2);
Run Code Online (Sandbox Code Playgroud)

gets changed to

struct structv2 *p1 = malloc(sizeof (struct structv2));
//     ^^^^^^^^                     ^^^^^^^^^^^^^^^^^
// two changes! maybe the programmer forgets one of them
struct structv2 *p2 = malloc(sizeof *p2);
//     ^^^^^^^^
// one change only. the argument to malloc is already correct
Run Code Online (Sandbox Code Playgroud)


Vla*_*cow 5

The sizeof operator has the following definition

sizeof unary-expression
sizeof ( type-name )
Run Code Online (Sandbox Code Playgroud)

Thus in this declaration

widget_t *p = malloc(sizeof *p);
Run Code Online (Sandbox Code Playgroud)

there is used the first form of the operator where the expression *p is an unary expression and has the type of widget_t.

Thus these declarations

widget_t *p = malloc(sizeof *p);
widget_t *p = malloc(sizeof( widget_t ) );
Run Code Online (Sandbox Code Playgroud)

are totally equivalent.

The first declaration is preferable because the expression in the sizeof operator does not depend on the actual type. That is the type of the pointer can be changed but the declaration will be valid without any other changes.

在C语言中,不需要将malloc返回的指针转换为所分配的左值的类型,因为可以将void *类型的指针分配给任何类型的对象的指针。有时使用它(并且有时是有用的)来使程序具有自说明性。

  • @bhura:仅在C ++(不允许将“ void *”隐式转换为其他指针类型)或C89之前的实现中(“ void *”不存在,而“ * alloc”存在)才需要强制转换函数返回`char *`)。否则,这是不必要的,只会增加维护负担。 (4认同)
  • @bhura这在C语言中是多余的,因为可以将类型为void *的指针分配给指向任何对象类型的指针。强制转换有时用于代码的自我说明。 (2认同)
  • @JohnBode“仅增加维护负担”是完全错误的说法。在C中使用强制转换可以避免许多难以发现的错误,有时甚至使代码成为自记录文件。 (2认同)