I am assigning a new memory chunk to a pointer, but apparently the size of the chunk is not the one which I pass as a parameter to malloc
char *q="tre";
printf("q in main %zu\n", sizeof(q));
q = (char*)malloc(6);
printf("q in main %zu\n", sizeof(q));
Outputs
8
8
The pointer however does point to a new memory chunk.
How is this possible?
sizeof returns size of pointer, in your case it is (char*), it will not give the memory allocated by the malloc. Keep the memory size in separate variable for later use.
char *q;
printf("%zu\n", sizeof(q));
sizeof(q) refers to the size of the pointer, not the amount of memory it points to.
What you are obtaining is the size of the variable q as a pointer type. In general all pointers will have the same size in your program.
Since 8 bytes are 64 bits, it seems you are doing 64-bit applications. :)
sizeof(q) returns the size of the pointer q which will on a 64 bit machine be 8 bytes, not the size of the memory block allocated at that pointer. sizeof is a compile time not a runtime operation.
I'm not clear what you want to do here, but if you want to allocate enough memory for a string at location s, then you want to malloc(strlen(s)+1) (+1 for the terminating NULL).
Perhaps you want to get the size of malloc()ed block. There is not a portable way to do this to my knowledge, but malloc_usable_size nearly does it on glibc. From the man page:
malloc_usable_size() returns the number of bytes available in the dynamically allocated buffer ptr, which may be greater than the requested size (but is guaranteed to be at least as large, if the request was successful). Typically, you should store the requested allocation size rather than use this function.
Note the last sentence.
Related
I read that:
sizeof operator returns the size of the data type, not the amount of memory allocated to the variable.
Isn't the amount of memory allocated depends on the size of the data type? I mean that sizeof will return 4 (architecture-dependent) when I pass int to it.
Am I missing something here?
sizeof returns the number of bytes that a variable or stack allocated array occupies.
Examples:
sizeof(char)=1 (in most configurations)
But sizeof(char*)=8 (depending on the platform)
If you dynamically allocate memory with malloc, you will receive a pointer to that block of memory. If use the sizeof on it, you will just get the size of the pointer.
However, sizeof() a stack allocated array like when you write int a[10] is the size of the allocated memory (so 4*10)
The size of the pointer doesn't depend on the size of the datatype it represents. (On 32 bit platforms, a pointer is 32bit)
The text you quote is technically incorrect. sizeof variable_name does return the size of memory that the variable called variable_name occupies.
The text makes a common mistake of conflating a pointer with the memory it points to. Those are two separate things. If a pointer points to an allocated block, then that block is not allocated to the pointer. (Nor are the contents of the block stored in the pointer -- another common mistake).
The allocation exists in its own right, the pointer variable exists elsewhere, and the pointer variable points to the allocation. The pointer variable could be changed to point elsewhere without disturbing the allocation.
sizeof returns the number of bytes
The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type.
but the size of each byte is not guaranteed to be 8. So you don't obtain directly the amount of memory allocated.
A byte is composed of a contiguous sequence of bits, the number of which is implementation-defined
anyway you can deduce the amount of memory allocated using the CHAR_BIT constant, which contains the number of bit is a byte.
"Memory allocation" in C typically refers to explicit allocation (i.e: on the heap - malloc() and friends), or implicit allocation (i.e: on the stack).
As you've defined, sizeof() returns the size of the data type:
sizeof(char) - a single char
sizeof(void *) - an void pointer
If you call malloc(sizeof(int)), you're requesting "enough memory to hold the data for an int", which may be 4 bytes on your system... you may find that more memory than you requested is allocated (though this will typically be hidden from you, see canaries).
Additionally, if you call int *x = malloc(1024), and sizeof(*x), you might get 4, because an int happens to be 4 bytes... even though the memory you've allocated is 1 KiB. If you were to incorrectly call sizeof(x), then you'll get the size of a pointer returned, not the size of the type it points to. Neither of these (sizeof(*x) or sizeof(x)) will return 1024.
I am learning C programming and this is my first course in programming. I am having some trouble with this snippet of code:
int* intArray;
intArray=(int*)malloc(5*sizeof(int));
I believe the number of elements in the array is 5 integers. However, what I don't really understand is the malloc function. Does it allocate enough memory for the addresses of 5 integers in this case?
Malloc returns a void pointer to the allocated space, or NULL if there is insufficient memory available. The parameter is the size, in bytes, to be allocated. So in the line intArray = (int*)malloc(5*sizeof(int)); you are requesting the allocation of memory sufficient for 5 ints (sizeof(int) gives the size of an int type). (malloc)
Using malloc requests the allocation of memory sufficient for 5 new integers.
No, the malloc allocates enough memory for 5 integers. It allocates what is passed into the function: 5*sizeof(int). What might be confusing you is that intArray is a pointer allocated on the stack, which points to the memory address of the beginning of the malloc'ed memory.
If you want memory for addresses of 5 integers, you would do something like:
int** intArray;
intArray=(int**)malloc(5*sizeof(int*));
The malloc function allocates the number of bytes you request in the argument and returns the address in memory of the beginning of the block. In this case you have requested a block of memory large enough to hold 5 integer values.
You cast it to an int * so the compiler will handle the address as containing integers when indexing and dereferencing.
Malloc function call as you observe requires a value specifying number of bytes. From the documentation on malloc:
void* malloc (size_t size);
Allocate memory block. Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
The content of the newly allocated block of memory is not initialized, remaining with indeterminate values.
Hence, in your code snippet:
intArray=(int*)malloc(5*sizeof(int));
int size is 2 bytes. sizeof(int) returns 2. Hence 5 * sizeof(int) = 10. So, code resolves to intArray = (int*)malloc(10);
I want to know the size of a buffer allocated using calloc in byte. By testing the following in my machine:
double *buf = (double *) calloc(5, sizeof(double));
printf("%zu \n", sizeof(buf));
The result was 8 even when I change to only one element I still get 8. My questions are:
Does it mean that I can only multiply 8*5 to get the buffer size in byte? (I thought sizeof will return 40).
How can make a macro that return the size of buffer in byte (the buffer to be checked could be char, int, double, or float)?
Any ideas are appreciated.
Quoting C11, chapter ยง6.5.3.4 , (emphasis mine)
The sizeof operator yields the size (in bytes) of its operand, which may be an
expression or the parenthesized name of a type. The size is determined from the type of
the operand. [...]
So, using sizeof you cannot get the size of the memory location pointed to by a pointer. You need to keep a track on that yourself.
To elaborate, your case is equivalent to sizeof (double *) which basically gives you the size of a pointer (to double) as per your environment.
There is no generic or direct way to get the size of the allocated memory from a memory allocator function. You can however, use a sentinel value to mark the ending of the allocated buffer and using a loop, you can check the value, but this means
the allocation of an extra element to hold the sentinel value itself
the sentinel value has to be excluded from the permissible values in the memory.
Choose according to your needs.
sizeof(buf) is the size of the buf variable, which is a pointer, not the size of the buffer it points to.
Due to memory alignment requirements (imposed by the hardware), the size of the block allocated with calloc() is at least the product of the values you pass to calloc() as arguments.
In your case, the size of the buffer is at least 5 * sizeof(double).
Afaik there is no way to find the size of a dynamically allocated block of memory but as long as you allocate it, you already know its size; you have to pass it as argument to the memory allocation function (be it malloc(), calloc(), realloc() or any other.
char *c = (char *)malloc(30*sizeof(char));
printf("%lu \n",sizeof(c));
In the above code I am trying to print the size of 'c'. No matter what number I give instead of '30' in the code, I get the sizeof(c) as 8.
What is the problem? How can I determine the size of an array?
Is length and size the same for an array?
At the moment you are asking for the size of a pointer which on a 64 bits machine is 8 bytes. Since this is a malloc and not a real array, you can't retrieve the size of the buffer allocated through c.
If c was declared as
char c[30];
You could determine size with
size_t size = sizeof(c)/sizeof(c[0])
But to be honest if I had to do that, I would just #define the array size even though the size calculation would be stripped out at compilation. It makes the code clearer in my opinion.
You are printing the size of a char * which in your system is 8.
If you want to know the amount of memory that was "malloc"ed you must store it somewhere. In your case your should store the 30 for future use if you are going to need it.
sizeof(c) means give me the size of the variable c. Since c is a pointer it's giving you back the number of bytes that the pointer takes up in memory. The fact you're seeing 8 suggests you're compiling for 64bit. On a 32bit built it would be 4.
It's your job to remember the size of the thing you've allocated. After all, you asked for an amount of memory, so you do know how much you allocated! In your case, size_t size = 30*sizeof(char) will give you the amount you've allocated.
sizeof is an operator, not a function, thus the compiler creates the code equivalent to something like sizeof(char *) and pointer of a char (depending on the architecture of course) is of 8 bytes.
Actually sizeof(*c) will return 1. The size of a mallocced buffer cannot be determined compile time (which is what sizeof does).
You're getting the size of the variable c, not the size of the memory region it points to. There's no way to get the size of an array inside a function because it always decays to pointer. You must store the size yourself. If you've passed the size to malloc then why can't you store that size to a variable?
Reading some literature, I was able to grasp that realloc takes in a void pointer and a size variable and re-allocates the memory of the block the void pointer points to.
What will happen if realloc is called on an integer pointer (int *)
with a size of character? And vice versa.
What can be a possible application of this? (An example would definitely help.)
The realloc() function is the all-in-one memory management system.
If called with a null pointer and a non-zero size, it allocates memory.
If called with a valid pointer and a zero size, it frees memory.
If called with a valid pointer and a non-zero size, it changes the size of the allocated memory.
If you call realloc() with an invalid pointer โ one which was not obtained from malloc(), calloc() or realloc() โ then you get undefined behaviour.
You could pass realloc() an integer pointer to an allocated space of sizeof(char) bytes (1 byte), but you'd be in danger of invoking undefined behaviour. The problem is not with realloc(); it is with the code that was given an unusable integer pointer. Since only 1 byte was allocated but sizeof(int) is greater than 1 (on essentially all systems; there could be exceptions, but not for someone asking this question), there is no safe way to use that pointer except by passing it to free() or realloc().
Given:
int *pointer = malloc(sizeof(char));
you cannot do *pointer = 0; because there isn't enough space allocated (formally) for it to write to. You cannot do int x = *pointer; because there isn't enough space allocated (formally) for it to read from. The word 'formally' is there because in practice, the memory allocators allocate a minimum size chunk, which is often 8 or 16 bytes, so there actually is space after the one byte. However, your are stepping outside the bounds of what the standard guarantees, and it is possible to conceive of memory allocators that would hand you exactly one byte. So, don't risk it. An integer pointer to a single byte of allocated memory is unusable except as an argument to the memory allocation functions.
The first argument to realloc() is a void *. Since you're going to have a prototype in scope (#include <stdlib.h>), the compiler will convert the int * to a void * (if there's anything to do for such a cast), and as long as the space pointed at was allocated, everything will be fine; realloc() will change the allocation size, possibly returning the same pointer or possibly returning a different pointer, or it will release the space if the new size is zero bytes.
There is a vitally important requirement to non-NULL pointers that you pass to realloc: they must themselves come from a call to malloc, calloc or realloc, otherwise the behavior is undefined.
If you allocate a chunk of memory sufficient to store an int and then realloc for a char, you will always get back the same pointer, because sizeof(char) is less than or equal to the sizeof(int):
int* intPtr = malloc(sizeof(int));
int* otherPtr = realloc(intPtr, sizeof(char));
// intPtr == otherPtr
If you try it the other way around, you will almost certainly get back the same pointer as well, because memory allocators rarely, if ever, parcel the memory to chunks smaller than sizeof(int). However, the result is implementation-dependent, so theoretically you may get back a different address.
As far as the utility of any of the above exercises goes, it is not useful: realloc has been designed with the intention to help you manage variable-sized arrays, simplifying the code for growing the size of such arrays, and potentially reducing the number of allocations and copying. I do not see a reason for realloc-ing a scalar.
The type of the first parameter of realloc is void *, as you said yourself. So the function argument that you pass is converted to a void pointer, which is an implicit and safe conversion.
It's the same as if you called a function with a long int parameter with an int argument, essentially.
Realloc takes the size in bytes. If you do
int* a= malloc(sizeof(int));
and then
a=realloc(a,1);
of course a will now not be big enough for an int type and writing an int in it will give you odd behavior.
As stated by dasblinkenlight, realloc doesn't make sense for a scalar.
In your example:
int * a = malloc(sizeof(int));
int * b = realloc(a,sizeof(char));
Would result in a == b, simply because sizeof(char) < sizeof(int) and there is no reason for moving the data to a new location.
The difference is, that after the realloc you are writing your int to unallocated space, as you decreased the allocated space using realloc. Here this is only of theoretical relevance. Because of alignment it is very unlikely, that the os is reusing the freed memory. But you shouldn't rely on that. This is undefined behavior.
It could become relevant, if you resize the space of a long int to an int. This depends on your architecture.
Writing to unallocated space is like laying a time bomb and not knowing when it will explode. You should only read from / write to allocated space.