C dynamic memory allocation and sizeof() - c

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];

Related

C function malloc() does not work as I expected [duplicate]

This is my code.
#include<stdio.h>
typedef struct {
int a,b;
} integers;
void main() {
integers *ptr = (integers *)malloc(10*sizeof(integers));
printf("%d",sizeof(*ptr)); // prints 8
}
From what I understand about Malloc, the above code should actually reserve 10x8=80 bytes of memory for ptr to point to.
Why then does using sizeof(*ptr) give only 8? How do I find the total size being allocated for ptr?
Because you're using sizeof(*ptr) you're actually asking for the size of the first element in the allocated buffer, thus sizeof will return the size of the first element in ptr (i.e. 2x4 bytes integers on 32bits system) rather than the allocated size.
Also, please note that even if you'd use sizeof(ptr) you'd get the size of the ptr pointer which on 32bits system would be 4 bytes.
Well, I know that this question is pretty outdated but finding no suitable answer, I decided to write one.
When specifying sizeof(*ptr), you're actually trying to reach out for the size of data type you've stored in the variable that the pointer is pointing to( here its the first element of the array). Here, that's quite evidently 8.
Even when you'll try to print sizeof(ptr), you'll be again printing the size of the pointer address which by default is 8 bytes in GCC compilers as the data type is long unsigned int.
Why then does using sizeof(*ptr) give only 8? How do I find the total size being allocated for ptr?
The type of the expression *ptr is integers - thus,
sizeof *ptr == sizeof (integers) == sizeof (int) + sizeof (int)
You cannot determine the size of the allocated buffer by looking at the pointer (it doesn't store any metadata about the buffer size). You will have to keep track of that information separately.
Edit
Note that you can do something like the following:
integers (*foo)[10] = malloc( sizeof *foo );
if ( foo )
printf( "sizeof *foo = %zu\n", sizeof *foo );
and that will give you the result you're expecting. In this case, foo is a pointer to an array of integers, not to a single instance of integers, so sizeof *foo will give you the size of the allocated array. The downside is that you have to expliticly dereference foo before applying the subscript:
(*foo)[i].a = some_value(); // or foo[0][i].a
(*foo)[i].b = some_other_value(); // or foo[0][i].b
This is normally done when you want to allocate an NxM array and make sure all the rows are contiguous:
integers (*foo)[10] = malloc( 10 * sizeof *foo );
will allocate a 10x10 array of integers such that the rows are all adjacent in memory.
Also, a pointer to a 10-element array of integers is not compatible with a pointer to an 11-element array of integers, making it more difficult to write functions that can work with pointers to arrays of different sizes. IOW, if you have a function declared as
void bar( integers (*foo)[10] ) { ... }
it can only work with Nx10 arrays of integers. There are ways around this that involve varying levels of pain, but that's a topic for another day.

Why am I not getting the correct size after using malloc and printing using sizeof?

This is my code.
#include<stdio.h>
typedef struct {
int a,b;
} integers;
void main() {
integers *ptr = (integers *)malloc(10*sizeof(integers));
printf("%d",sizeof(*ptr)); // prints 8
}
From what I understand about Malloc, the above code should actually reserve 10x8=80 bytes of memory for ptr to point to.
Why then does using sizeof(*ptr) give only 8? How do I find the total size being allocated for ptr?
Because you're using sizeof(*ptr) you're actually asking for the size of the first element in the allocated buffer, thus sizeof will return the size of the first element in ptr (i.e. 2x4 bytes integers on 32bits system) rather than the allocated size.
Also, please note that even if you'd use sizeof(ptr) you'd get the size of the ptr pointer which on 32bits system would be 4 bytes.
Well, I know that this question is pretty outdated but finding no suitable answer, I decided to write one.
When specifying sizeof(*ptr), you're actually trying to reach out for the size of data type you've stored in the variable that the pointer is pointing to( here its the first element of the array). Here, that's quite evidently 8.
Even when you'll try to print sizeof(ptr), you'll be again printing the size of the pointer address which by default is 8 bytes in GCC compilers as the data type is long unsigned int.
Why then does using sizeof(*ptr) give only 8? How do I find the total size being allocated for ptr?
The type of the expression *ptr is integers - thus,
sizeof *ptr == sizeof (integers) == sizeof (int) + sizeof (int)
You cannot determine the size of the allocated buffer by looking at the pointer (it doesn't store any metadata about the buffer size). You will have to keep track of that information separately.
Edit
Note that you can do something like the following:
integers (*foo)[10] = malloc( sizeof *foo );
if ( foo )
printf( "sizeof *foo = %zu\n", sizeof *foo );
and that will give you the result you're expecting. In this case, foo is a pointer to an array of integers, not to a single instance of integers, so sizeof *foo will give you the size of the allocated array. The downside is that you have to expliticly dereference foo before applying the subscript:
(*foo)[i].a = some_value(); // or foo[0][i].a
(*foo)[i].b = some_other_value(); // or foo[0][i].b
This is normally done when you want to allocate an NxM array and make sure all the rows are contiguous:
integers (*foo)[10] = malloc( 10 * sizeof *foo );
will allocate a 10x10 array of integers such that the rows are all adjacent in memory.
Also, a pointer to a 10-element array of integers is not compatible with a pointer to an 11-element array of integers, making it more difficult to write functions that can work with pointers to arrays of different sizes. IOW, if you have a function declared as
void bar( integers (*foo)[10] ) { ... }
it can only work with Nx10 arrays of integers. There are ways around this that involve varying levels of pain, but that's a topic for another day.

What is the size of pointer to an array of type int?

I have the following code
#include <stdio.h>
int main(void) {
int arr[] = {10,20,30,40};
int* ptr = arr;
printf("%d\n",sizeof(arr));
printf("%d",sizeof(ptr));
return 0;
}
The output is
16
4
size of pointer in C is 4. 'arr' is also a pointer to an integer but its size comes out to be 16, which is product of size of one element and number of elements.
On the other hand if I store the same pointer into another pointer variable then its size becomes 4. This is very confusing. The same thing happens if I try to send arr as an argument to a function and then print the size of arr in that function. How does C handle a pointer to an array?
'arr' is also a pointer to integer
No, it's not. arr is an array. The size of an array is the size of an element times the number of elements. If it were a pointer, it's size would be the same as any other pointer.
How does C handles pointer of array?
C handles pointers to arrays the same way it handles all other pointers. However there are no pointers to arrays in your code, only a pointer to int (ptr).
A pointer is just a memory address, therefore on 32-bit systems it is always 4 bytes. Depending on the environment it is 4 or 8 bytes on 64-bit systems.
There is no real confusion in your example. arr is an array of 4 32-bit integers, therefore 16 bytes. It is 'handled', or 'passed around', as a pointer to the first int, an int*, which is why you can copy it to other variables of that type, either explicitly or as a parameter. At which time there is no longer a relationship to the original array, and it is just a pointer - 4 bytes on your system.
The best way to look at it is that there is an implicit conversion possible from int[] to int*, like there is from char to int.
When you do sizeof(arr) you will get the size of array which is number of elements * size of int.
When you do sizeof(ptr) you will get the size of pointer which is size of int.
This is very confusing. The same thing happens if I try to send arr as an argument to a function and then print the size of arr in that function.
When you send the array like this foo(arr), you are actually sending the base address of arr. And when we pass address of a variable to a function, it will store the address in a pointer. So again if you try to get the size of arr you'll get the size of pointer.
sizeof only works to find the length of the array if you apply it to the original array.
int a[5]; //real array. NOT a pointer
sizeof(a); // :)
However, by the time the array decays into a pointer, sizeof will give the size of the pointer and not of the array.
int a[5];
int * p = a; // assigning address of the array to pointer
sizeof(p); // :(
It will return always 4 bytes on 32-bit system and 8 bytes on 64-bit system!
Arrays decaying into pointers when they are passed to a function and continuing to keep the array length in the type system.
When you pass an array to a function it decays to pointer. So the sizeof function will return the size of int *
So when you pass the array to the function you need to pass the Number of elements also-
void function (size_t sz, int *arr) { ... }
:
{
int x[20];
function (sizeof(x)/sizeof(*x), x);
}

Confusion: Dynamic Allocation of 2D array, C

I yesterday came across a question on SO, that wanted to dynamically allocate a 2-D array in C.
One of the answers was to allocate it this way:
int (*place)[columns] = malloc(rows * sizeof *place);
This apart from being beautiful, brought a question to my head. The question goes below:
Following is the code in which i allocate a 4x4
int (*arr)[4] = (int (*)[4]) malloc(4 * sizeof *arr);
printf("%d\n", sizeof arr); //Dynamic 2-D array by above method
int **arr1 = (int**) malloc(4 * sizeof(int*));
for(int i = 0; i < 4; i++)
arr1[i] = (int *) malloc(sizeof(double));
printf("%d\n", sizeof arr1); //Usual dynamic 2-D array
int *arr2 = (int*) malloc(4 * sizeof(int));
printf("%d\n", sizeof arr2); //Dynamic 1-D array
The usual output is:
4
4
4
However, if i try to print sizeof *arr, sizeof *arr1 and sizeof *arr2, the output is:
16
4
4
I don't understand why this is happening. Any idea why the output for sizeof *arr is 16? How is the memory being being allocated in the first case?
Also, when i try to print the address of arr and *arr, both the printed values are same. *arr means "value at" arr. So does that mean arr stores its own address, i.e., it is pointing to itself (which i don't think is possible)? Am slightly confused. Any idea where am I going wrong?
Thanks for your help!
However, if I try to print sizeof *arr, sizeof *arr1 and sizeof *arr2, I get 16, 4, and 4.
where:
int (*arr)[4];
int **arr1;
int *arr2;
You must be working on a 32-bit machine, not a 64-bit machine.
The type of arr is 'pointer to an array of 4 int'. When you dereference it, you get an 'array of 4 int'. When passed to sizeof, the array is of size 16 (4 * sizeof(int)). Most of the time, when you reference an array, the type is adjusted to 'pointer to zeroth element of the array', but sizeof() is the primary exception to that rule; it sees an array as an array and returns the size of the whole array.
The type of arr1 is 'pointer to pointer to int'. When you dereference it, you get a 'pointer to int'. When passed to sizeof, the pointer is of size 4 (sizeof(int *)).
The type of arr2 is 'pointer to int'. When you dereference it, you get an int. When passed to sizeof, the int is of size 4.
Okay! I get most of it. But ... why isn't the output 16 when I do sizeof arr2?
As James noted in his comment:
because sizeof(arr2) reduces to sizeof(int*) which on a 32-bit machine is 4.
That is, arr2 is a pointer; the size of a pointer is 4 on a 32-bit machine.
Also, arr is a 'pointer to an array of 4 int', i.e., a single pointer. Then how do I get a 4×4 matrix.
You can use either of these:
int mat1[4][4];
int (*mat2)[4][4];
The first is a straight-forward 4×4 matrix. The result of sizeof(mat1) will be 64 on a 32-bit machine (and most 64-bit machines, as it happens).
The second is a pointer to a 4×4 matrix of int. The result of sizeof(mat2) will be 4 on a 32-bit machine; mat2 is a pointer (to a 4×4 matrix of int), so it is of size 4, the same as every other object pointer (and, in practice, the same size as every function pointer, though the C standard does not guarantee that function pointers and object pointers are the same size; POSIX does guarantee that, though).
The result of sizeof(*mat2) is the size of the object that mat2 points at, which is a 4×4 matrix of int, so the size is 64 again.
In a 32 bit system it needs 4 bytes or 32 bit to identify each memory address uniquely. A pointer is nothing just the holder of the address. so it takes 4 byte. In the first case arr is an array of pointer of length 4. so it takes 4*4 =16 bytes. in the other two case arr1 and arr2 are just a single pointer. so they take 4 bytes.

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.

Resources