C: size of *array[x]? - c

I have a question that should be fairly straightforward (I hope).
In c, the size of an array delcared as int array[10][10];,
for example, I understand as having 10 spots in which to store 10 integers. However, what's the size of an array declared as int *array[10];? I know that *array has 10 elements, but how many elements does array have?
This is a hole in my understanding I would really like to clear up. Thanks for any help!

int *array[10]; is an array of 10 int *s, so the number of elements is 10.
To elaborate, for int *array[10];, ty type of array variable is int * [10], an array of 10 elements of type pointer to integers.
The array size would be 10 * sizeof pointer-to-integer-in-your-platform.

You have to understand the declaration in C.
Start dividing it in parts:
int array[10][10];
array is the name of the variable, the part [10] means that it is an array of 10 arrays of int, each array holding 10 elements (the second [10]).
Now:
int * array[10];
array is the name of the variable, the part [10] means that it is an array of 10 elements of type int * (integer pointers not integers as before).
The sizes in the firs case will be 10 times the size of an array of 10 integers = the space required for 100 integers.
In the second case will be the size to hold 10 pointers to integer.
As side note maybe your confusion comes from the fact that C allows access to elements of both declaration in the same way. I.e. the following will get the 5th integer of the second array:
int b = array[2][5];
But the difference remains substantial because in the first declaration the compiler will allocate contiguous space to hold all 100 integers (organized, as per C allocating method, as 10 arrays of 10 integers each in succession), in the second case will be allocated only an array of 10 pointers each pointing to the location of an array of 10 integers. And the 10 arrays will not be allocated, nor the pointers initialized.
In that case it is programmer responsibility to allocate 10 arrays of int and assign the address of each one to the array of pointers.
Another point to clarify (thanks to alk to have pointed it out) is that in the case of the array of pointers the second dimension is undefined, meaning that each array of int pointed can be of 1, 10, 1000 or whatever elements.

how many elements does array have?
int *array[10];
array is array of 10 pointers to int, the same as int* array[10] - so array has 10 elements (each element being a pointer).

Related

how to iterate through an array without knowing the size in c [duplicate]

This question already has answers here:
How can I get the size of an array from a pointer in C?
(16 answers)
Closed 1 year ago.
I have a pointer to an array in C which I would like to iterate through, but I don't know the size:
int *array;
I am unsure as to how I should proceed. I was thinking that I should probably try by finding the size by doing:
int array_size = sizeof(array) / sizeof(int);
But I don't know if that could work. I was wondering if there was a more optimal way of doing this?
In C, there is no way to tell the number of elements in an array from a pointer to an element. sizeof(array) / sizeof(*array) only works for an actual array, not for a pointer, which is what a function receives as an argument, even if the array syntax is used in the function prototype. In this case sizeof(array) evaluates to the size of the pointer, so dividing that by the size of an element is meaningless.
The best approach for your function to get the number of elements is to provide it as a separate argument.
If this is not practical, there are different ways to infer the number of elements, relying on a convention that must be adhered to by the callers:
the array could have a known fixed number of elements
the array could have a sentinel value as the last element of the array.
It is common to use a null pointer (NULL) as such a sentinel for arrays of pointers, such as the char *argv[] argument of the main() function, but note that int argc is also provided to this function.
The null byte (\0) is used to tell the end of C strings, which are arrays of char.
In your case, you could consider 0 or -1 to signify the end of the array, but this convention must be used consistently by all callers of your function.
You cannot iterate over an array in c without knowking the number of elements.
Please note that sizeof(array) / sizeof(array[0]) won't work on a pointer, i.e it will not give the number of elements in the array.
It will also not work inside a function, where the array was passed as an argument due to array decay to pointer.
If the array does not contain a known sentinel value (as for example character arrays that contain strings have as the sentinel value the terminating zero character '\0') then you can not find its end.
If you have a pointer like this
int *array;
then the expression sizeof( array ) will yield the size of the pointer itself that does not depend on whether the pointer points to a single object of the type int or to the first element of an integer array with a known number of elements in the array. That size for example can be equal either to 4 or 8 depending on the used system. Thus the expression sizeof( array ) / sizeof( int ) in general will always yield either 1 or 2.
So you have to pass to the function explicitly also the number of elements in the array.
You could determine the number of elements in an array if you pass a pointer to the whole array. For example
void f( int( *a )[10] );
//...
int a[10];
//...
f( &a );
In this case dereferencing the pointer within the function you will get an object of the array type. Thus the expression sizeof( *a ) will yield the size of the original array.
I have a pointer to an array in c to which I would like to iterate through but I don't know the size:
You are in luck if you truly have a pointer to an array as the type of a pointer to an array carries information about the array size.
int some_array[7] = {1, 2, 3, 4, 5, 6, 7};
int (*pointer_to_an_array)[7] = &some_array;
#define N (sizeof(*pointer_to_an_array) / sizeof(*pointer_to_an_array[0]))
for (size_t i = 0; i < N; i++) {
printf("%d\n", (*pointer_to_an_array)[i]);
}
Unfortunately, with int *array;, code does not have a pointer to an array, but a pointer to an int and information about the original array size of some_array[] is not available through array.
int some_array[7] = {1,2,3,4,5,6,7};
int *array = some_array; // Not a pointer to an array
Carry information about array size in another variable.
size_t some_array_n = sizeof some_array/ sizeof some_array[0];

C - Pass variable length array of strings to function and modify strings inside function [duplicate]

This question already has answers here:
Why can't we use double pointer to represent two dimensional arrays?
(6 answers)
Closed 6 years ago.
int main()
{
matrix[2][4] = {{11,22,33,99},{44,55,66,110}};
int **ptr = (int**)matrix;
printf("%d%d",**matrix,*ptr);
}
But when a 2-d array is passed as a parameter it is typecasted into (*matrix)[2] ..
what type does the compiler store this array as... is it storing as a 2-d array or a double pointer or an pointer to an array .. If it is storing as an array how does it interprets differently at different situations like above. Please help me understand.
Is 2d array a double pointer?
No. This line of your program is incorrect:
int **ptr = (int**)matrix;
This answer deals with the same topic
If you want concrete image how multidimensional arrays are implemented:
The rules for multidimensional arrays are not different from those for ordinary arrays, just substitute the "inner" array type as element type. The array items are stored in memory directly after each other:
matrix: 11 22 33 99 44 55 66 110
----------- the first element of matrix
------------ the second element of matrix
Therefore, to address element matrix[x][y], you take the base address of matrix + x*4 + y (4 is the inner array size).
When arrays are passed to functions, they decay to pointers to their first element. As you noticed, this would be int (*)[4]. The 4 in the type would then tell the compiler the size of the inner type, which is why it works. When doing pointer arithmetic on a similar pointer, the compiler adds multiples of the element size, so for matrix_ptr[x][y], you get matrix_ptr + x*4 + y, which is exactly the same as above.
The cast ptr=(int**)matrix is therefore incorrect. For once, *ptr would mean a pointer value stored at address of matrix, but there isn't any. Secondly, There isn't a pointer to matrix[1] anywhere in the memory of the program.
Note: the calculations in this post assume sizeof(int)==1, to avoid unnecessary complexity.
No. A multidimensional array is a single block of memory. The size of the block is the product of the dimensions multiplied by the size of the type of the elements, and indexing in each pair of brackets offsets into the array by the product of the dimensions for the remaining dimensions. So..
int arr[5][3][2];
is an array that holds 30 ints. arr[0][0][0] gives the first, arr[1][0][0] gives the seventh (offsets by 3 * 2). arr[0][1][0] gives the third (offsets by 2).
The pointers the array decays to will depend on the level; arr decays to a pointer to a 3x2 int array, arr[0] decays to a pointer to a 2 element int array, and arr[0][0] decays to a pointer to int.
However, you can also have an array of pointers, and treat it as a multidimensional array -- but it requires some extra setup, because you have to set each pointer to its array. Additionally, you lose the information about the sizes of the arrays within the array (sizeof would give the size of the pointer). On the other hand, you gain the ability to have differently sized sub-arrays and to change where the pointers point, which is useful if they need to be resized or rearranged. An array of pointers like this can be indexed like a multidimensional array, even though it's allocated and arranged differently and sizeof won't always behave the same way with it. A statically allocated example of this setup would be:
int *arr[3];
int aa[2] = { 10, 11 },
ab[2] = { 12, 13 },
ac[2] = { 14, 15 };
arr[0] = aa;
arr[1] = ab;
arr[2] = ac;
After the above, arr[1][0] is 12. But instead of giving the int found at 1 * 2 * sizeof(int) bytes past the start address of the array arr, it gives the int found at 0 * sizeof(int) bytes past the address pointed to by arr[1]. Also, sizeof(arr[0]) is equivalent to sizeof(int *) instead of sizeof(int) * 2.
In C, there's nothing special you need to know to understand multi-dimensional arrays. They work exactly the same way as if they were never specifically mentioned. All you need to know is that you can create an array of any type, including an array.
So when you see:
int matrix[2][4];
Just think, "matrix is an array of 2 things -- those things are arrays of 4 integers". All the normal rules for arrays apply. For example, matrix can easily decay into a pointer to its first member, just like any other array, which in this case is an array of four integers. (Which can, of course, itself decay.)
If you can use the stack for that data (small volume) then you usually define the matrix:
int matrix[X][Y]
When you want to allocate it in the heap (large volume), the you usually define a:
int** matrix = NULL;
and then allocate the two dimensions with malloc/calloc.
You can treat the 2d array as int** but that is not a good practice since it makes the code less readable. Other then that
**matrix == matrix[0][0] is true

Can't use fixed array in 'dynamic array' in struct [duplicate]

This question already has answers here:
Why can't we use double pointer to represent two dimensional arrays?
(6 answers)
Closed 6 years ago.
int main()
{
matrix[2][4] = {{11,22,33,99},{44,55,66,110}};
int **ptr = (int**)matrix;
printf("%d%d",**matrix,*ptr);
}
But when a 2-d array is passed as a parameter it is typecasted into (*matrix)[2] ..
what type does the compiler store this array as... is it storing as a 2-d array or a double pointer or an pointer to an array .. If it is storing as an array how does it interprets differently at different situations like above. Please help me understand.
Is 2d array a double pointer?
No. This line of your program is incorrect:
int **ptr = (int**)matrix;
This answer deals with the same topic
If you want concrete image how multidimensional arrays are implemented:
The rules for multidimensional arrays are not different from those for ordinary arrays, just substitute the "inner" array type as element type. The array items are stored in memory directly after each other:
matrix: 11 22 33 99 44 55 66 110
----------- the first element of matrix
------------ the second element of matrix
Therefore, to address element matrix[x][y], you take the base address of matrix + x*4 + y (4 is the inner array size).
When arrays are passed to functions, they decay to pointers to their first element. As you noticed, this would be int (*)[4]. The 4 in the type would then tell the compiler the size of the inner type, which is why it works. When doing pointer arithmetic on a similar pointer, the compiler adds multiples of the element size, so for matrix_ptr[x][y], you get matrix_ptr + x*4 + y, which is exactly the same as above.
The cast ptr=(int**)matrix is therefore incorrect. For once, *ptr would mean a pointer value stored at address of matrix, but there isn't any. Secondly, There isn't a pointer to matrix[1] anywhere in the memory of the program.
Note: the calculations in this post assume sizeof(int)==1, to avoid unnecessary complexity.
No. A multidimensional array is a single block of memory. The size of the block is the product of the dimensions multiplied by the size of the type of the elements, and indexing in each pair of brackets offsets into the array by the product of the dimensions for the remaining dimensions. So..
int arr[5][3][2];
is an array that holds 30 ints. arr[0][0][0] gives the first, arr[1][0][0] gives the seventh (offsets by 3 * 2). arr[0][1][0] gives the third (offsets by 2).
The pointers the array decays to will depend on the level; arr decays to a pointer to a 3x2 int array, arr[0] decays to a pointer to a 2 element int array, and arr[0][0] decays to a pointer to int.
However, you can also have an array of pointers, and treat it as a multidimensional array -- but it requires some extra setup, because you have to set each pointer to its array. Additionally, you lose the information about the sizes of the arrays within the array (sizeof would give the size of the pointer). On the other hand, you gain the ability to have differently sized sub-arrays and to change where the pointers point, which is useful if they need to be resized or rearranged. An array of pointers like this can be indexed like a multidimensional array, even though it's allocated and arranged differently and sizeof won't always behave the same way with it. A statically allocated example of this setup would be:
int *arr[3];
int aa[2] = { 10, 11 },
ab[2] = { 12, 13 },
ac[2] = { 14, 15 };
arr[0] = aa;
arr[1] = ab;
arr[2] = ac;
After the above, arr[1][0] is 12. But instead of giving the int found at 1 * 2 * sizeof(int) bytes past the start address of the array arr, it gives the int found at 0 * sizeof(int) bytes past the address pointed to by arr[1]. Also, sizeof(arr[0]) is equivalent to sizeof(int *) instead of sizeof(int) * 2.
In C, there's nothing special you need to know to understand multi-dimensional arrays. They work exactly the same way as if they were never specifically mentioned. All you need to know is that you can create an array of any type, including an array.
So when you see:
int matrix[2][4];
Just think, "matrix is an array of 2 things -- those things are arrays of 4 integers". All the normal rules for arrays apply. For example, matrix can easily decay into a pointer to its first member, just like any other array, which in this case is an array of four integers. (Which can, of course, itself decay.)
If you can use the stack for that data (small volume) then you usually define the matrix:
int matrix[X][Y]
When you want to allocate it in the heap (large volume), the you usually define a:
int** matrix = NULL;
and then allocate the two dimensions with malloc/calloc.
You can treat the 2d array as int** but that is not a good practice since it makes the code less readable. Other then that
**matrix == matrix[0][0] is true

Experimenting with Pointers and Arrays in C

Can someone explain to me the difference between:
int *arr[5] vs. int (*arr)[5] vs. int *(*arr)[5]
I'm trying to wrap my mind around how pointers/arrays are actually represented in C...
I would suggest using http://cdecl.org.
int *arr[5] "declare arr as array 5 of pointer to int"
int (*arr)[5] "declare arr as pointer to array 5 of int"
int *(*arr)[5] "declare arr as pointer to array 5 of pointer to int"
plus a visit to this page from MSDN: Interpreting more complex declarators.
The first makes a variable named arr that is of an array length 5 of type int*, so it is an array length 5 of int pointers.
The second declares a variable named arr that is a pointer to an array length 5 of type int. So it is a pointer to an array of ints length 5.
The third is a variable named arr that is a pointer to an array of length 5 of type int pointer. So it is a pointer to an array length 5 of int pointers. Or, a pointer to the type of the first case!
To think of how to analyze things like this in the future, realize that parenthesis have the highest priority here so by having (*arr) it is first, and foremost, a pointer. Then the array notation has second highest priority, so (*arr)[5] is a pointer to an array of length 5...but what type of array? Well the type is the lowest priority, so that comes last. If we have int (*arr)[5], then it is a pointer (1st) to an array length 5 (2) of type int (3).
With that we can look at something like: int** (*arr)[7] It is a pointer named arr (1) to an array length 7 (2) of type int**, or pointers to pointers of ints (3).
As far as wondering how pointers/arrays are represented in C...
pointers and arrays are both 32 bit variables (like ints on most systems) that contain a 32 bit address to a memory location (where they point). Arrays obviously point to the beginning of an array, so *arr == arr[0]. While pointers can point to anything. When you declare an array (arr[5], arr[1000], etc.) it makes a pointer named arr as well as reserves whatever space is in between the brackets (5 or 1000). But when you declare a pointer (*arr), it does not reserve any space. Otherwise, the variable arr in both cases is simply a pointer. Also, if you want to be confusing, you could even dereference your pointers like so: pointer[0], instead of *pointer.
As a final note example, we can look at something like: int * (*arr)[5][7] and analyze both what it is and what the compiler is doing:
First, it is a pointer named arr (1), to an array length 5 (2) each to an array length 7 (3) but because an array length n is just a pointer to a reserved location in memory, so really (2) is an array length 5 to a pointer (pointing to memory blocks of size 7). Finally, each of the memory blocks of size 7 (3) is of type int * (4).
So, it is a pointer to an array length 5 of pointers to arrays of length 7 of type int *!
I hope this helps! I know I had a lot of fun playing with C and seeing what was possible and what different things did =)
A pointer is the address of another object. An array is a contiguous block of objects. So:
int *a[5];
a is an array of 5 pointers to int. This means that a represents a block of 5 contiguous address values, where each of those values can hold the address of an int.
int (*b)[5];
b is a pointer to an array of 5 ints. This means that b is a single address value, where that value can hold the address of an array of 5 ints.
int *(*c)[5];
c is a pointer to an array of 5 pointers to int. This means that c is a single address value, where that value can hold the address of an array of 5 pointers to int. This could hold the address of the first object a, so c = &a; would be valid.
int *arr[5] is an array of five int*s.
int (*arr)[5] is a pointer to an array of five ints.
int *(*arr)[5] is a pointer to an array of int*
Generally, one makes a typedef:
typedef int fiveintarray[5];
typedef int* intptr;
typedef intptr fiveintptrarray[5];
And then uses it:
fiveintarray array; //array of five integers
fiveintarray* pointer_to_array; // pointer to array of five integers
fiveintptrarray array; //array of five pointers to integers
fiveintptrarray* pointer_to_array; //pointer to array of five pointers to integers
int *arr[5] -> an array, of length 5, of pointers to int
int (*arr)[5] -> a pointer to int arrays of length 5
int *(*arr)[5] -> a pointer to a pointer to int arrays of length 5

Declaring multidimensional Arrays: Pointer or Array Definiton

What's the difference between declaring multidimensional arrays like this:
int a[5][5];
or this
int* a[5];
?
Which one is better to use? Thanks.
Both may be used to declare 2-dimensional arrays.
In the first case, 25 int elements are allocated in a contiguous region in memory.
In this case the expression a[i][j] is translated by the compiler to *(a + i*5 + j).
The second one allocates 5 pointers to int. You can make it work as a two dimensional array by allocating vectors of int and making these pointers point to these vectors.
In this case a[i][j] means get the pointer that a[i] points to, then look up the 5th element in that vector. I.e. a[i][j] is translated to *(a[i] + j).
Note that in the second case, rows need not be of the same length.
int a[5][5]; says that the compiler should allocate enough memory to store 25 ints, and to treat it as a two-dimensional array called a.
int* a[5]; says that the compiler should allocate enough memory to store 5 pointers to integers, and treat it as an array of pointers called a. To actually use this as a two-dimensional array, you will have to allocate more memory and initialize those pointers to point at it. For example:
int * a[5];
for(int i = 0; i < 5; i++){ a[i] = malloc(sizeof(int) * 5); }
Without knowing your requirements it's hard to say which one is better for you. The second one allows you to efficiently swap two rows and is generally more flexible, but it takes more code to allocate and free the data structure.
The first one you are declaring bidimensional array (an array of arrays).
The second you're declaring an array of pointers to ints which can used as multidimensional array.
Is int *array[32] a pointer to an array of 32 ints, or an array of 32 pointers to int? Does it matter?
Take a look at http://www.cplusplus.com/doc/tutorial/arrays/ for declaring multidimensional arrays
Which is better apple or orange ?
this notation int a[ROWS][COLS]is used to create rectangular 2D array which dimensions are known at declaration time.
And this int * a[ROWS] notation is used when number of columns are unknown at 2D array declaration time OR number of columns can vary in run-time OR simply one wants to create non-rectangular (jagged) array like this:
1 2 3 4
4 6
7 1 1 1 5 6 7
9

Resources