简体   繁体   English

malloc需要sizeof运算符吗?

[英]Is the sizeof operator needed for malloc?

In this program (C, not C++) , why malloc always returns the correct size regardless of the use of the sizeof operator? 在这个程序(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;
}

The output is: 输出是:

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

Am I missing something? 我错过了什么吗?

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

long *l = malloc(3);

This allocates (or rather attempts to allocate) 3 bytes . 这分配(或者更确切地说是尝试分配)3 个字节

Typically malloc() will actually allocate more than you request, for alignment and bookkeeping purposes. 通常, malloc()实际上会分配比您请求更多的内容,用于对齐和簿记。 So after calling malloc(3) , you may well be able to get away with storing 3 long values in the allocated memory. 因此,在调用malloc(3) ,您可能能够在分配的内存中存储3个long值。 But it's not guaranteed. 但它不能保证。

Yes, you do need the sizeof . 是的,你确实需要sizeof

And the best way to write that is: 写这个的最好方法是:

long *l = malloc(3 * sizeof *l);

By using the size of what the pointer points to ( sizeof *l ), you don't have to specify the type long twice, and the code won't break if the type changes later. 通过使用指针所指向的大小( sizeof *l ),您不必long两次指定类型,如果类型稍后更改,代码将不会中断。

Even better: 更好的是:

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

If you prefer, you can write this as: 如果您愿意,可以将其写成:

long *l = malloc(3 * sizeof(*l));

but the extra parentheses aren't necessary, size sizeof is a unary operator, not a function. 但额外的括号不是必需的,size sizeof是一元运算符,而不是函数。

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

Incrementing a pointer advances it by the size of the type it points to. 递增指针会使其指向的类型大小。 long is apparently 8 bytes on your system, so this will advance l by least 24 bytes, well past the 3 bytes you requested from malloc . long显然是你系统上的8个字节,所以这将使l至少增加24个字节,远远超过你从malloc请求的3个字节。 The result is undefined behavior. 结果是未定义的行为。

And by incrementing l , you've lost the original value returned by malloc ; 通过递增l ,你已经丢失了malloc返回的原始值; you'll need that when it's time to call free() . 是时候打电话给free()

Finally the %p format specifier requires an argument of type void* . 最后, %p格式说明符需要类型为void*的参数。 Passing a different pointer type is likely to "work", but you really should cast it to void* : 传递不同的指针类型很可能“工作”,但你真的应该将它转换为void*

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

Am I missing something? 我错过了什么吗?

Yes, you are totally missing the point. 是的,你完全忽略了这一点。

You are testing pointer arithmetic , which is defined in terms of the size of the pointed-to type. 您正在测试指针算术 ,它是根据指向类型的大小定义的。 That has absolutely nothing to do with the amount of memory allocated by malloc() , or even whether the pointer in question points to a valid address at all. 这与malloc()分配的malloc()量完全无关,甚至与所讨论的指针完全指向有效地址无关。

Incrementing a pointer increments the stored address by the size of the base type. 递增指针会使存储的地址增加基本类型的大小。 It does not depend on what the pointer is pointing to. 它不依赖于指针指向的内容。

The number of bytes incremented when you increment a pointer is only based on its type -- eg if you increment an int* by 1, you'll increment the address by 4 bytes. 递增指针时递增的字节数仅基于其类型 - 例如,如果将int*递增1,则将地址递增4个字节。 This has nothing to do with malloc or sizeof or anything. 这与mallocsizeof或任何东西无关。

You'll find that if you start storing values in those pointers, you'll run into strange behavior, as you haven't allocated enough space to store 3 short s, or 3 int s, or 3 long s. 您会发现,如果您开始在这些指针中存储值,您将遇到奇怪的行为,因为您没有分配足够的空间来存储3个short s,3个int或3个long

You have fallen prey to a fallacy. 你已成为谬误的牺牲品。 You are not analyzing what malloc has returned, you are seeing that increment knows how to properly increment the pointer based on the size of the variable type. 您没有分析malloc返回的内容,您看到增量知道如何根据变量类型的大小正确递增指针。 Nothing about a malloc call tells you how much RAM was actually allocated. 没有关于malloc调用的信息告诉你实际分配了多少RAM。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM