In this program (C, not C++), why malloc always returns the correct size regardless of the use of the sizeof operator?
#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
long *l = malloc(3);
This allocates (or rather attempts to allocate) 3 bytes.
Typically malloc()
will actually allocate more than you request, for alignment and bookkeeping purposes. So after calling malloc(3)
, you may well be able to get away with storing 3 long
values in the allocated memory. But it's not guaranteed.
Yes, you do need the 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.
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.
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
. The result is undefined behavior.
And by incrementing l
, you've lost the original value returned by malloc
; you'll need that when it's time to call free()
.
Finally the %p
format specifier requires an argument of type void*
. Passing a different pointer type is likely to "work", but you really should cast it to 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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With