malloc需要sizeof运算符吗?

lml*_*mlf 5 c

在这个程序(C,而不是C++)中,为什么无论使用sizeof运算符,malloc总是返回正确的大小?

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

int main(void) {
    char *c = malloc(3);
    short *s = malloc(3); /* or malloc(3 * sizeof(short))? */
    int *i = malloc(3);   /* or malloc(3 * sizeof(int))? */
    long *l = malloc(3);  /* or malloc(3 * sizeof(long))? */

    printf("%p\n", c++);
    printf("%p\n", c++);
    printf("%p\n", c++);

    printf("---\n");

    printf("%p\n", s++);
    printf("%p\n", s++);
    printf("%p\n", s++);

    printf("---\n");

    printf("%p\n", i++);
    printf("%p\n", i++);
    printf("%p\n", i++);

    printf("---\n");

    printf("%p\n", l++);
    printf("%p\n", l++);
    printf("%p\n", l++);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出是:

0x1e82010 (1 byte)
0x1e82011
0x1e82012
---
0x1e82030 (2 bytes)
0x1e82032
0x1e82034
---
0x1e82050 (4 bytes)
0x1e82054
0x1e82058
---
0x1e82070 (8 bytes)
0x1e82078
0x1e82080
Run Code Online (Sandbox Code Playgroud)

我错过了什么吗?

4.0.4-303.fc22.x86_64 clang版本3.5.0(标签/ RELEASE_350/final)目标:x86_64-redhat-linux-gnu线程模型:posix

Kei*_*son 10

long *l = malloc(3);
Run Code Online (Sandbox Code Playgroud)

这分配(或者更确切地说是尝试分配)3 个字节.

通常malloc()实际上会分配比您请求更多的内容,用于校准和簿记.因此,在调用之后malloc(3),您可能能够long在分配的内存中存储3个值.但它不能保证.

是的,你确实需要sizeof.

写这个的最好方法是:

long *l = malloc(3 * sizeof *l);
Run Code Online (Sandbox Code Playgroud)

通过使用指针指向(sizeof *l)的大小,您不必指定类型long两次,并且如果类型稍后更改,代码将不会中断.

更好的是:

long *l = malloc(3 * sizeof *l);
if (l == NULL) {
    /* malloc failed, recover or bail out */
}
Run Code Online (Sandbox Code Playgroud)

如果您愿意,可以将其写成:

long *l = malloc(3 * sizeof(*l));
Run Code Online (Sandbox Code Playgroud)

但额外的括号不是必需的,大小sizeof是一元运算符,而不是函数.

printf("%p\n", l++);
printf("%p\n", l++);
printf("%p\n", l++);
Run Code Online (Sandbox Code Playgroud)

递增指针会使其指向的类型大小增加.long在您的系统上显然是8个字节,因此这将提前l至少24个字节,远远超过您请求的3个字节malloc.结果是未定义的行为.

通过递增l,您已经丢失了返回的原始值malloc; 在打电话的时候你需要它free().

最后,%p格式说明符需要一个类型的参数void*.传递不同的指针类型很可能"工作",但你真的应该把它投射到void*:

printf("%p\n", (void*)l++);
Run Code Online (Sandbox Code Playgroud)


Joh*_*ger 5

我错过了什么吗?

是的,你完全忽略了这一点.

您正在测试指针算术,它是根据指向类型的大小定义的.这与分配的内存量完全无关,甚至与所malloc()讨论的指针是否完全指向有效地址无关.


Ism*_*awi 2

当您增加指针时增加的字节数仅基于其类型 - 例如,如果您将 an 增加int*1,则地址将增加 4 个字节。malloc这与或或任何事情无关sizeof

您会发现,如果开始在这些指针中存储值,您将遇到奇怪的行为,因为您没有分配足够的空间来存储 3 shorts、3 ints 或 3 longs。