Confusion: Dynamic Allocation of 2D array, C - 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.

Related

sizeof on array variable Vs sizeof on pointer in c [duplicate]

This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 2 years ago.
See below example in c:
#include <stdio.h>
int main()
{
int arr[] = {1, 2 ,3};
int *ptr = arr;
printf("sizeof arr[] = %d ", sizeof(arr));
printf("sizeof ptr = %d ", sizeof(ptr));
return 0;
}
output: sizeof arr[] = 12 sizeof ptr = 4
Why sizeof on pointer "ptr" outputs 4 and on array variable "arr"(although "arr" is also being a pointer) outputs 12 ?
Operator sizeof returns the size of an object's type. Your array has 3 integers so it is sizeof(int)*3.
A pointer size in bytes is platform-specific and in this case it is 4 bytes = 32 bits.
An array variable has pointer semantics, so when it is passed to a function or used in an assignment such as int *p = arr, it represents the address of its first element, however its type is not simply the type of its elements.
In your snippet the size is inferred by the compiler from the initializer you used, so your array type is int[3] in this case,and not simply int.
size of int is 4 bytes so the size of arr = sizeof(int) * 3 which is 12 as it contains 3 integers.
but ptr is a pointer to an array of integers. With a 32bit all the pointer will be size 4 bytes (32 bits)
Hope it helps
although "arr" is also being a pointer
NO, array is not a pointer.
The sizeof pointer depends on the architecture. It does not depend on what it points to.
The size of array is amount of all element in array. In this case, arr content of 3 integer elements, each element has 4 bytes in your system,
(the size of int may be 2 in other systems). So the size of arr is 3*sizeof(int) = 3*4 = 12.
See What is the size of a pointer?
Very useful for your question How to find the 'sizeof' (a pointer pointing to an array)?
And How do I determine the size of my array in C?

C language array byte size

char *myArray[] = { "aaaaaa", "ccccc", "bbbbbb", "111111" };
printf("%d\n", sizeof(myArray));
printf("%d\n", (int)(&myArray + 1) - (int)(&myArray));
My question is about why passing myArray into sizeof can get the same result as the second method.
I know myArray represent a address which points to the first of four int space addresses, but how does sizeof recognize the size of bytes of 4 int space?
sizeof is not a function, what is it?
why passing myArray into sizeof can get the same result as the second method.
char *myArray[] = { "aaaaaa", "ccccc", "bbbbbb", "111111" };
myArray is array of 4 pointers to char. So sizeof(myArray) = 4*sizeof(pointer_to_char). Typically in 64 bit machine sizeof(pointer) is 64 bit (8 bytes), and so it's 32 bytes.
As for your second printf
printf("%d\n", (int)(&myArray + 1) - (int)(&myArray));
Because myArray is array, then &myArray is pointer to array. Here (&myArray + 1) points to the next array of pointers. Think of that as the next block of 4 pointers to char. And so (&myArray + 1) - (&myArray) is the same as the size of the original array of pointers.
Btw, you should use proper printf control string:
For sizeof, use %zu:
printf("%zu\n", sizeof(myArray));
Your 2nd printf works but would give an warning with regard the cast to int:
warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
That warning can be get rid of by:
char *p_start = (char *)(&myArray + 1);
char *p_end = (char *)(&myArray);
printf("%td", p_start - p_end );
sizeof(myArray) gives you the size of an array of 4 character pointers, probably 4x4=16. sizeof is an operator, which is in most cases evaluated at compile-time. It is defined by the language to do this task - the language says that sizeof's job is to know the size of things, so that's how it knows.
&myArray gives you an array pointer of type char (*)[4]. &myArray+1 does arithmetic on such an array, giving the address of an array pointer pointing just past the 4x4 array. If you subtract that address with the original address, you will get the size of the array in bytes.
There is no real difference between the two forms functionality-wise, except sizeof is so much more readable.
(As a side note, the second version results in a type called ptrdiff_t, and if you wish to print this with printf, you should use the %tu format specifier.)

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);
}

Pointers in C - 1D and 2D

I know that, for the following:
int a[10];
a is a pointer of the type int * to a[0], while &a is a pointer of type int (*)[10].
Now my question is for the following 2D array:
int b[20][30];
Is b a pointer of the type int **? Or is it a pointer of the type int (*)[30]?
Is &b a pointer of the type int (*)[20][30]?
Arrays are not pointers (this point cannot be stressed enough).
That being said, an array decays to a pointer to its first element. For example:
int a[10];
int b[20][30];
void print_a(int *);
void print_b(int (*)[30]);
print_a(a);
print_b(b);
The first element of a is a[0], and similarly the first element of b is b[0]. You basically take that first dimension away, and change it to a (*); I'll explain more in a moment since it is a bit more complex than that.
The relationship between pointers and arrays is riddled with contextual subtleties that aren't terribly difficult to grasp, but the size information in various scopes makes it interesting and also helps to give you an idea of how the decay works:
#include <stdio.h>
int h(int *pa)
{
printf("h(int *): sizeof pa=%zu\n", sizeof pa);
printf("h(int *): sizeof *pa=%zu\n", sizeof *pa);
return *pa;
}
int g(int (*pa)[5])
{
printf("g(int (*)[5]): sizeof pa=%zu\n", sizeof pa);
printf("g(int (*)[5]): sizeof *pa=%zu\n", sizeof *pa);
return h(*pa);
}
int f(int (*pa)[3][5])
{
printf("f(int (*)[3][5]): sizeof pa=%zu\n", sizeof pa);
printf("f(int (*)[3][5]): sizeof *pa=%zu\n", sizeof *pa);
return g(*pa);
}
int main(void)
{
int arr[2][3][5] = {{{11235}}};
printf("main: sizeof arr=%zu\n", sizeof arr);
printf("main: sizeof *arr=%zu\n", sizeof *arr);
printf("%d\n", f(arr));
}
Every pointer is the same size (this may not always be true on all platforms!), but by dereferencing the pointer, you see the size of a given element of the array, whether you dereference using the unary * operator or the [N] array notation, which is equivalent to *((array)+(N)) by definition.
Anyway, going back to the difference between pointers and arrays, you should understand that int[20][30] is not the same as int **. Why is that? Because of the fact that int[20][30] decays to a pointer of type int(*)[30], no more decay can occur until the pointer is dereferenced. Moreover, int ** is actually int *(*), which means it can point to the first element of an array of pointers. That is, int ** might have once been int *[N].
int foo[x][y][z] <=> int (*foo)[y][z]
int *foo[m][n] <=> int *(*foo)[n]
int (*foo[a])[b] <=> int (**foo)[b]
In the first case, we have a 3-D array, which decays to a pointer to a 2-D array; in other words, an array of arrays and a pointer to an array are closely related and interchangeable in many contexts aside from the size issue. The first dimension x is the one that decays, leaving the y and z dimensions.
In the second case, we have a 2-D array of pointers. This decays to a pointer to an array of pointers. Again, an array of arrays is closely related to a pointer to an array, and dimension m decays, leaving dimension n.
In the third case, we have an array of pointers to arrays. It decays to a pointer to a pointer to an array. Since dimension a is closest to the variable name, that is the one that decays, leaving dimension b. Note that since it is an array of pointers to arrays, the pointers could point to the first element of arrays themselves:
int arr[2][3][5];
int (*foo[2])[5] = { arr[0], arr[1] };
int (**foo_ptr)[5] = foo;
Recap:
Array (size A) of arrays (size B) <=> Pointer to array (size B)
Array (size A) of pointers <=> Pointer to pointer
The array that decays/grows is always the innermost array/pointer, the innermost being the one closest to the variable name in the variable declaration, with arrays having higher associativity than pointers, though of course parentheses make all the difference.
This rabbit hole obviously can be confusing, but I hope I helped a bit at least!
First of all make it clear that arrays are not pointers. Relationship between pointers and arrays is subtle. I would suggest you to read second chapter of tutorial on pointers by Ted Jensen first.
I would like to tell you something in a nutshell what has been describe in this chap. Consider following example.
int a[10];
int *p;
Now you can write
p=a;
that is equivalent to
p=&a[0];
This thing make many texts to say array is name of pointer. But it is better if you say "the name of the array is the address of first element in the array" .
Because though you can write
p=a;
but you can not write
a=p;
Now come to your question:
From above discussion it should be clear that b is not pointer of type int** .For example:
int b[10][10];
int **x;
int *p;
b=&p; // this is error
x=&p; // this fine
For your other questions you may use online CDECL.
if you write
int b[10][10]; --> declare b as array 10 of array 10 of int
int (*p)[10]; --> declare p as pointer to array 10 of int
int (*p)[10][20]; --> declare p as pointer to array 10 of array 20 of int
No, a is not of type int*, it is of type int [10] (i. e. of an array type). This is why sizeof(a) will give you the size of the array (40 bytes, assuming 32 bit integers).
Likewise, b is of type int [20][30], which is nothing other than an array of arrays. I. e. sizeof(b[0]) is the size of one line array, which is 120 in this case, the size of the entire array (sizeof(b)) is 20 times the size of the line arrays, which is 2400 bytes in this case.
The trick is, that an array decays into a pointer to its first element in almost all contexts. So when you do pointer arithmetic (as in b[3]) on the 2D array, b decays into a pointer of type int (*)[30], so the pointer arithmetic skips rows, adding three times the size of a row (360 bytes in this case) - the rows are the elements of the 2D array. The resulting type of b[3] is int [30], i. e. the dereferenced pointer.
Once you have dereferenced to a row array with b[3], you can again invoke pointer arithmetic to select the correct element in this row (b[3][5]). Again, the array-pointer-decay is invoked, the mechanic is the same.
Note that there is no pointer array involved as is the case when you emulate a 2D array with an int**. The double dereference b[3][5] translates into something like ((int*)b)[3*30 + 5] by virtue of array-pointer-decay, only the element itself is accessed from memory.
int* temp;
int arraySize = 20;
temp = (int *)malloc(arraySize * sizeof(int));
This will create a section in memory 20 "ints" long, similarly as you mentioned.
int** temp;
int arraySize = 20;
int rowSize = 10;
temp = (int **)malloc(arraySize * sizeof(int *));
for(i=0; i<arraySize; i++){
temp[i] = (int *)malloc(rowSize * sizeof(int));
}
That is what the 2D array would actually look like.
temp[0] would give you the address of the first "array". In which you could do something like above int *array = temp[0] then access it like a normal array but using *array[0] to get the value.
2D arrays really don't mesh well with pointers and saying *temp[0] to get the values of the first array. You can try to mess with it, you'll figure it out, but don't have a machine that can compile C with me right now.
Reference that may help: http://www.cs.swarthmore.edu/~newhall/unixhelp/C_arrays.html

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

Resources