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);
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 wondering where is foo and arr* being allocated in this sample program. Is foo allocated on stack with constant size or does it change when I use malloc on *arr? If I were to change foo.arr[i] for i from 0 to 4, would it change size of anything? Is foo.arr being allocated on heap? Does change of size of foo.arr change size of foo?
typedef struct {
int size;
int* arr;
} S;
int main(void) {
S foo;
int new_size = 5;
foo.size = new_size;
foo.arr = malloc(new_size * sizeof(int));
free(foo.arr);
return 0;
}
Your confusion stems from conflating the pointer with the allocated space. A pointer is, naively, just a variable that holds a value that describes the address in memory of another value. The space required for the pointer is determined by the maximum addressable space of architecture, not by the allocated block of memory. Think referentially.
In this case, foo is allocated in the stack and the size of the structure instance remains unchanged. malloc is taking care of the mechanics of memory allocation for you and returning a fresh memory address to the allocated space. Subsequently, you are taking that memory address and saving it in the arr member.
Furthermore, anything that is allocated in the stack has to be fixed size in nature. The size of the stack frame needs to be known upon calling the function. Consider the fact that every argument to a procedure has to be of known size or a pointer to some structure allocated in the heap.
Now, all that considered, there exist mechanisms to declare variable sized structures, but you would need to take care of allocating the structure in the heap and handling memory explicitly. The C99 standard introduced flexible array member, which allows placing a size undetermined array within a structure declaration, granted that it is accompanied by another member and it is placed as the last member of the structure.
When you do S foo; you allocate an element of type S in the stack composed of two int, generally 32 bits for an int, so you have allocated 64 bits.
Then you do foo.arr = malloc(new_size * sizeof(int));, you have allocated in the heap a certain amount of contiguous bits, and now foo.arr will point to (->) the first 32 bits.
Additional answers :
If I change foo.arr[i] for i from 0 to 4, would it change size of
anything?
No, since you will only change values in memory not size.
Does change of size of foo.arr change size of foo?
No, from the moment arr is allocate on heap the size of foo will remains the same.
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.
Hello I try to understand how realloc works so here is my question:
Let's say that first we call malloc in order to allocate enough memory for 1 int.
int *p=malloc(sizeof(int))
then we call realloc like this:
p=realloc(p,sizeof(int)*2);
The pointer p points to memory with available space for 2 or 1+2 ints?
As mentioned in the man pages:
void *realloc(void *ptr, size_t size);
[...]
The realloc() function changes the size of the memory block pointed
to by ptr to size bytes. The contents will be unchanged in the range
from the start of the region up to the minimum of the old and new
sizes. If the new size is larger than the old size, the added memory
will not be initialized. [...]
(My emphasis). In other words, the size parameter to realloc asks for how many bytes of memory you'd like allocated in total, not the number of bytes of memory that you'd like to add.
Hope this helps!
void* realloc (void* ptr, size_t size);
Changes the size of the memory block pointed to by ptr.
The function may move the memory block to a new location (whose address is returned by the function).
The content of the memory block is preserved up to the lesser of the new and old sizes, even if the block is moved to a new location. If the new size is larger, the value of the newly allocated portion is indeterminate.
In case that ptr is a null pointer, the function behaves like malloc, assigning a new block of size bytes and returning a pointer to its beginning.
In C90 (C++98):
Otherwise, if size is zero, the memory previously allocated at ptr is deallocated as if a call to free was made, and a null pointer is returned.
In C99/C11 (C++11):
If size is zero, the return value depends on the particular library implementation: it may either be a null pointer or some other location that shall not be dereferenced.
Argument ptr:
Pointer to a memory block previously allocated with malloc, calloc or realloc.
Alternatively, this can be a null pointer, in which case a new block is allocated (as if malloc was called).
Argument size:
New size for the memory block, in bytes.
size_t is an unsigned integral type.
Return Value:
A pointer to the reallocated memory block, which may be either the same as ptr or a new location.
The type of this pointer is void*, which can be cast to the desired type of data pointer in order to be dereferenceable.
In C90 (C++98):
A null-pointer indicates either that size was zero (an thus ptr was deallocated), or that the function did not allocate storage (and thus the block pointed by ptr was not modified).
In C99/C11 (C++11):
A null-pointer indicates that the function failed to allocate storage, and thus the block pointed by ptr was not modified.
From realloc(3)
Synopsis
void *realloc(void *ptr, size_t size);
Description
The realloc() function changes the size of the memory block pointed to by ptr to size bytes.
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.