Number of bytes allocated with malloc call in C - c

#include<stdio.h>
#include<stdlib.h>
#define MAXROW 3
#define MAXCOL 23
int main(){
int (*p)[MAXCOL];
p = (int (*) [MAXCOL])malloc(MAXROW *sizeof(*p));
return 0;
}
I need to know how many bytes will be allocated for the following code (for this p).
also, is the casting before the malloc adds/frees bytes that were allocated in the malloc if the size is different ?
Thanks.

sizeof(*p) is the size of an array of MAXCOL ints, or MAXCOL * sizeof(int).
So, the malloc call you present will allocate MAXROW * MAXCOL * sizeof(int) bytes.
About the cast : it will not impact how many bytes are allocated by the malloc call. In fact, it's completely unnecessary (and in this case without any effect), and is better left out.

p is a pointer to an array of int of length MAXCOL. And so sizeof(*p) is the size of an array of int of length MAXCOL. Hence MAXROW *sizeof(*p) is equal to MAXROW*MAXCOL*sizeof(int).
Casting of the return value of malloc is not needed since malloc returns void*. As a general rule, in C code, you should not cast the return value of malloc.

I think it depends on your architecture, if ints are 32 or 64 bits. Then as David says, is MAXROW times that size.

Related

What are the difference between the following two statements? ptr = malloc (400); ptr = malloc (100 * sizeof(int))

What is the difference between the following two statements?
ptr = malloc (400);
and
ptr = malloc (100 * sizeof(int))
How does it work? Is there any difference between them?
types of ptr 'int'
It depends on your architecture. On a 64-bit machine, the int size should be 8 bytes and 4 bytes on a 32-bit. Though it is not a rule, your 64-bit compiler might register having 4 bytes instead.
So the difference is that the allocated memory might vary depending on the architecture you are targeting and what the compiler decides.
This is also true for the size of your pointers.
No there should not be any. Malloc allocates contiguous memory chunk in bytes at runtime, so as long as integer takes 4 bytes, then no problem.
You can also refer this, for more clarity.
Also since you did not mention the type of pointer you are using .. the 2 ways makes no difference. Suppose you wanted an integer type then here is an example:
int *ptr;
ptr = malloc(100 * sizeof *ptr);
The first form allocates 400 bytes.
The second form allocates enough space for 100 int objects.
These are not necessarily the same thing, as the size of an int can be 2, 4, or more bytes wide depending on the platform.
If you need to set aside space for N objects of a given type, use the following idiom:
T *ptr = malloc( N * sizeof *ptr ); // for any object type T
sizeof *ptr is equivalent to sizeof (T).

Malloc, and size on 32 bit machines

#include<stdio.h>
#include<stdlib.h>
int main()
{
int *p;
p = (int *)malloc(20);
printf("%d\n", sizeof(p));
free(p);
return 0;
}
On my 64-bit machine, 4 is printed as the size of p. I'm assuming this is because integers take up 4 bytes in memory, and p is an integer pointer. What if I was running a 32-bit machine? Also, what would happen if I replaced
int *p with double *p
and
(int *)malloc(20) with (double *)malloc(20)?
You are assuming wrong.
In printf("%d\n", sizeof(p)); you are not printing size of integer.You are printing here sizeof 'pointer to an integer' which is 4 bytes in your case.Most probably you will get same result on 32-bit machine.
Now about malloc, It allocates number of bytes and returns pointer to it.So same size of memory will be allocated even if you cast the pointer from int* to double*.
In pointers, It will take four bytes for all pointers.
So while you are checking with sizeof, even it is a character pointer it will give four bytes. If you need the value of that pointer use like this.
printf("%d\n", sizeof(p));// It will give the pointer size.
malloc is allocating the given bytes. And it will give equal to all the pointers. Then don't cast the result of malloc. Refer this link.
You have some misunderstanding let me point them,
p = (int *)malloc(20);
You are allocating memory of 20 bytes and malloc returns a void pointer and but compiler does the casting for you and (int *) is not needed. Even though you have a pointer to a double or an int it takes the same amount of bytes (In a 32bit system this merely for mapping 4GB memory space).
// Should this be 4 or 8?
printf("%d\n", sizeof(p));
This should be 8 on a x64 platform if your executable or the build is x64 only. I assume your build is 32bit and it returns 4.
Above printf has a wrong specifier. sizeof returns size_t and not an int. So correct form should be,
printf("%zu\n", sizeof(p));
Irrespective of whether 64-bit system or 32-bit system, size of a pointer variable is 4 bytes by default since 64-bit build settings also have Debug32 by default.
If we specifically change build settings on 64-bit, then the pointer variable can hold 8 bytes.
I'm assuming this is because integers take up 4 bytes in memory, and p is an integer pointer.
Your assumption is not correct ! To answer your doubt not only integer pointer take up 4 bytes.
int *ptrint;
char *ptrchar;
float *ptrfloat;
double *ptrdouble;
Here all ptrint, ptrchar, ptrfloat, ptrdouble takes 4 bytes of memory since it would be the address stored in that variable.
And if you replace int *p with double *p and (int *)malloc(20) with (double *)malloc(20) , the size would be still 4 bytes. I hope this ans cleared your doubts.

What is the purpose of this code section?

#include <stdio.h>
#include <stdlib.h>
#define MAX 10
void main()
{
int *ptr, *arr[MAX];
int i, j;
for (i=MAX-1; i>=0; i--)
if (arr[i]=(int*)malloc(i*sizeof(int))) // <= that line!
for (j=0; j<i; j++)
*(*(arr+i)+j) = j*i;
ptr = *(arr+MAX-1);
while (*ptr)
printf ("%d ", *ptr--);
}
I am not understand what the purpose of this command:
arr[i]=(int*)malloc(i*sizeof(int))
I know that this malloc dynamic allocation.
But what is meant by arr[i] it gives the sizeof*i ?
Thanks.
The command that you are talking about allocates a block of length that is sufficient to store i items of type int, and stores the result at the i-th position in the array of pointers called arr. The program creates a "triangular" arr array: its elements are arrays of different lengths, arranged in such an order that arr[i] can hold i elements.
By the way, this code is missing calls to free for the items it has allocated.
int *ptr, *arr[MAX]
creates a pointer to int and an array with MAX elements of pointers to int.
arr[i]=(int*)malloc(i*sizeof(int))
Allocates space for i ints for every int pointer.
At first sizeof() "returns" (it should be replaced with numeric value during compilation) the size of provided type. Means 4 for int (8 on 64b machines), 1 for char and so on.
Therefore i*sizeof(int) means size for i ints (i = 4; sizeof( int) = 4; than it's 16).
malloc() uses number of bytes to allocate as parameter, therefore malloc(16) allocate 16bytes, enough space for 4 4B integers.
(int*) is just something like C-hack to have correct types (because you want to use those 16B as int[4] not as void *).
The whole code means to allocate space for i ints on i-th place of array (1 on first, 2 on second...). However I wander what will happen for 0, when you'll try to allocate 0 Bytes :)
It's allocating increasingly longer arrays as each element of the arr. so arr[0] points to a 0 size array, arr[2] points to an array of 2 ints and so on.
arr is an array of pointers to int. Every element of it - arr[x] - is a pointer to int, so an array. It's an array of arrays of ints.
For each element of the array, you create an array with size of the current index.
Note though that your code is illegal, since when i==0, you will call malloc(0).
Also, it's good practice not to cast the return type of malloc.

C dynamic memory allocation and sizeof()

I'm having some trouble understanding the difference between these two code segments:
I allocate space for an array of integers dynamically within my code with the following statement
int *arr = calloc(cnt, sizeof(int));
In another function, where I pass in arr, I would like to determine the size (number of elements) in arr.
When I call
int arr_sz = sizeof(arr)/sizeof(int);
it only returns 1, which is just the number of bytes in an int for both arguments I am assuming (4/4)=1.
I just assumed it would be the same as using an array
int arr[8];
int arr_sz = sizeof(arr)/sizeof(int);
which returns the actual number of elements in the array.
If anyone could clear this up, that would be great. Thanks!
int *arr; ----> Pointer
int arr[8]; ----> Array
First up what you got there - int *arr is a pointer, pointing to some bytes of memory location, not an array.
The type of an Array and a Pointer is not the same.
In another function where I pass in arr, I would like to determine the size (number elements) in arr. When I call
int arr_sz = sizeof(arr)/sizeof(int);
it only returns 1, which is just the number of bytes in an int for both arguments I am assuming (4/4)=1. I just assumed it would be the same as using an array
Even if it is assumed to be an Array -- that's because Arrays get decayed into pointers when passed into functions. You need to explicitly pass the array size in functions as a separate argument.
Go through this:
Sizeof an array in the C programming language?
There is a difference between a static array and dynamic memory allocation.
The sizeof operator will not work on dynamic allocations.
AFAIK it works best with stack-based and predefined types.
well, int *arr declares a pointer, a variable which keeps the address of some other variable, and its size is the size of an integer because it's a pointer, it just have to keep the address, not the pointee itself.
int arr[8] declares an array, a collection of integers. sizeof(arr) refers to the size of the entire collection, so 8*sizeof(int).
Often you hear that "array and pointers are the same things". That's not true! They're different things.
Mike,
arr is a pointer and as such, on your system at least, has the same number of bytes as int. Array's are not always the same as pointers to the array type.
sizeof(arr) is the same as sizeof(int*), i.e. the size of a single pointer. You can however calculate arr_sz as ... cnt!
*arr is not the same as arr[8] since it's size is not known in compile time, and sizeof is a function of the compiler. So when your arr is *arr sizeof will return the size of the pointer (sizeof(int *))in bytes, while when your arr is arr[8], the sizeof will return the size of array of 8 integers in bytes (which is sizeof(int) * 8).
When you pass a pointer to array to a function, you must specify its size, because the compiler can't do it for you. Another way is to end the array with null element, and perform a while loop.
If you have int arr1[8] the type of arr1 (as far as the compiler is concerned) is an array ints of size 8.
In the example int * arr2 the type of arr2 is pointer to an integer.
sizeof(arr1) is the size of an int array
sizeof(arr2) is the size of an int pointer (4 bytes on a 32 bit system, 8 bytes on a 64 bit system)
So, the only difference is the type which the compiler thinks that variable is.
You can't use sizeof with memory pointers:
int *arr = calloc(cnt, sizeof(int));
But it's ok to use it with arrays:
int arr[8];

Memory Allocation Problem

This question was asked in the written round of a job interview:
#include<alloc.h>
#define MAXROW 3
#define MAXCOL 4
main()
{
int (*p)[MAXCOL];
p = (int (*)[MAXCOL]) malloc(MAXROW*(sizeof(*p)));
}
How many bytes are allocated in the process?
To be honest, I did not answer the question. I did not understand the assignment to p.
Can anybody explain me what would be the answer and how it can be deduced?
It's platform dependent.
int (*p)[MAXCOL]; declares an pointer to an array of integers MAXCOL elements wide (MAXCOL of course is 4 in this case). One element of this pointer is therefore 4*sizeof(int) on the target platform.
The malloc statement allocates a memory buffer MAXROW times the size of the type contained in P. Therefore, in total, MAXROW*MAXCOL integers are allocated. The actual number of bytes will depend on the target platform.
Also, there's probably additional memory used by the C runtime (as internal bookeeping in malloc, as well as the various process initialization bits which happen before main is called), which is also completely platform dependant.
p is a pointer to an array of MAXCOL elements of type int, so sizeof *p (parentheses were redundant) is the size of such an array, i.e. MAXCOL*sizeof(int).
The cast on the return value of malloc is unnecessary, ugly, and considered harmful. In this case it hides a serious bug: due to missing prototype, malloc is assumed implicitly to return int, which is incompatible with its correct return type (void *), thus resulting in undefined behavior.
sizeof(*p) will be MAXCOL*sizeof(int). So totally MAXROW*MAXCOL*sizeof(int) number of bytes are alloctaed.
You might want to check out cdecl for help translating C declarations into English. In this instance, int (*p)[4]; becomes declare p as pointer to array 4 of int.
#include<alloc.h>
#define MAXROW 3
#define MAXCOL 4
main() {
int (*p)[MAXCOL];
p = (int (*)[MAXCOL]) malloc(MAXROW*(sizeof(*p));
}
How many bytes are allocated in the process ?
p is a pointer, so will occupy sizeof(int(*)[MAXCOL]) on the stack, which might look daunting but it's almost always the same as sizeof(void*), sizeof(int*) or any other pointer. Obviously pointer sizes are what give applications their classification as 16-, 32-, 64-etc. bits, and this pointer will be correspondingly sized.
Then p is pointed at some memory obtained from malloc...
malloc( MAXROW * sizeof(*p) )
sizeof(*p) is the size of the int array that p points to, namely sizeof(int) * MAXCOL, so we get
malloc( MAXROW * (sizeof(int) * MAXCOL) )
requested from the heap. For illustrative purposes, if we assume the common 32-bit int size, we're looking at 48 bytes. The actual usage may be rounded up to whatever the heap routines feel like (heap routines often used fixed-sized "buckets" to speed their operations).
To confirm this expectation, simply substitute a logging function for malloc():
#include <stdio.h>
#define MAXROW 3
#define MAXCOL 4
void* our_malloc(size_t n)
{
printf("malloc(%ld)\n", n);
return 0;
}
int main()
{
int (*p)[MAXCOL];
p = (int (*)[MAXCOL]) our_malloc(MAXROW*(sizeof(*p)));
}
Output on my Linux box:
malloc(48)
The fact that malloc's returned pointer is cast to p's type doesn't affect the amount of memory allocation done.
As R sharply observes, lack of a malloc prototype would cause the compiler to expect malloc to return int rather than the actually-returned void*. In practice, it's probable that the lowest sizeof(int) bytes from the pointer would survive the conversion, and if sizeof(void*) happened to be equal to sizeof(int), or - more tenuous yet - the heap memory happens to start at an address representable in an int despite the size of pointers being larger (i.e. all the truncated bits were 0s anyway), then later dereferencing of the pointer just might work. Cheap plug: C++ won't compile unless it's seen the prototype.
That said, perhaps your alloc.h contains a malloc prototype... I don't have an alloc.h so I guess it's non-Standard.
Any program will also allocate memory for many other things, such as a stack frame providing some context within which main() may be called. The amount of memory for that varies with the compiler, version, compiler flags, operating system etc..
int (*p)[MAXCOL] == int (*p)[4] == "pointer to array 4 of int" (see Note below)
sizeof(*p) would then be what p points to, i.e. 4 * sizeof(int). Multiply that by MAXROW and your final answer is:
12 * sizeof(int)
Note: This is in contrast to:
int *p[MAXCOL] == int *p[4] == "array 4 of pointer to int"
The parentheses make quite a bit of difference!
It should be MAXROW*MAXCOL*sizeof(int) number of bytes
I really dislike questions like this, because I think it's far better as a working engineer to run the experiment than to assume that you know what you are doing - especially if there's reason for suspicion such as a program not working as expected or someone crafting trick questions.
#include <stdlib.h>
#include <stdio.h>
#define MAXROW 3
#define MAXCOL 4
main()
{
int (*p)[MAXCOL];
int bytes = MAXROW * (sizeof(*p));
p = (int (*)[MAXCOL]) malloc(bytes);
printf("malloc called for %d bytes\n", bytes);
}
On a 32 bit linux system:
gcc test.c
./a.out
malloc called for 48 bytes
(edited to remove pasting accident of multiplying by maxrow twice, yielding mistaken size of 144 bytes)
Running the following in codepad.org:
//#include<alloc.h>
#define MAXROW 3
#define MAXCOL 4
int main()
{
int (*p)[MAXCOL];
p = (int (*)[MAXCOL]) malloc(MAXROW*(sizeof(*p)));
int x = MAXROW*(sizeof(*p));
printf("%d", x);
return 0;
}
prints out 48.
Why? Because MAXROW is 3, and sizeof(*p) is 16, so we get 3 * 16.
Why is sizeof(*p) 16? Because MAXCOL is 4, so p is a pointer to an array of 4 ints. Each int is 32 bits = 4 bytes. 4 ints in the array * 4 bytes = 16.
Why is sizeof(*p) not 4? Because it is the size of what p points to, not the size of p. To be the size of p it would have to be sizeof(p), which would be 4, as p is a pointer.
Pedantically you could add:
If the machine is 64 bit (say) the answer would be 96.
As the question states "How many bytes are allocated in the process?", you need to add the 4 bytes for the pointer p.
malloc can allocate more than you ask for (but not less) so the question cannot be answered.
In a similar vein as 2, you could argue that as the process is also loading system dlls such as the C runtime dll in order to run, it is allocating the space for those too. Then you could argue for the space allocated by dlls that are being injected into the process by other (non system) processes, such as those injected by Actual Window Manager and its ilk. But how pedantic do we want to get?
But I think the question is really asking for 48, with possible extra credit for explaining 96.
How about zero bytes because that won't even compile without the non-standard alloc.h. If you can't compile it, you can't run it and if you can't run it, it can't allocate any memory at all.

Resources