I have problems finding the number of array elements in my dynamical allocated array.
If I have a normal Array I know how to find out how much elements are in there with:
int array[] = {1,2,3};
printf("Number of array elements: %i\n",(int)(sizeof(array) / sizeof((array)[0])));
this prints me:
Number of array elements: 3
But when I want to dynamically allocate an array and know its size I can't get it working the same way:
int *array;
array = malloc(3*sizeof(int));
printf("Number of array elements: %i\n",(int)(sizeof(array) / sizeof((array)[0])));
This always gives me:
Number of array elements: 2
No matter how much how small or big I make the allocation it always prints
2
Please can someone help?
The reason you see different size is because the underlaying data isn't the same.
In you first example, you have statically compiled array of integers. This array elements are all aligned in memory and array is the array. Using sizeof(array) allows you to get the overall size of this array.
In the second example, you have a dynamically allocated pointer on an array of integers. This is totally different in memory. The array variable isn't the array practically speaking. It's the pointer to the first element. Using sizeof(array) here returns the size of the pointer on the first element, hence 8.
Related
I just discovered zero-length arrays and I'd like to use it for a 2d array, the advantage of these arrays is to avoid pointers inside a structure so we can just free the structure instead of having to free it's data, so it can better be used inside a container structure like a linked list for example without having to pass a destructor function, but the problem is I can't figure out how to use it for 2d arrays. I have a structure looking like this:
struct s_arg
{
int argc;
char argv[0][0];
};
But the problem is: how to keep track of each member size without another array containing sizes? Is this possible to do this with no malloc for struct members ?
No.
The only reason an array can be used with no size known is because you do not need to know the size in order to access elements. Given an array a, a[0] is at the start of the array, a[1] is one element beyond that, and so on. The location of any element a[i] can be computed without knowing the size of the array.
Naturally, for an array to exist, somebody has to allocate memory for it, and so they must know the size. So the creator of an array must know its size, but the user does not need to.
GCC allows zero-length arrays as an extension so that a structure can have an array at its end, where the memory is allocated by the creator of the structure, who knows its size. Except to support old software, this extension became unnecessary once the C standard supported arrays of unknown size (declared with no size, [], called flexible array members).
For two-dimensional arrays, the ability to use an array without knowing its size does not apply. Given a two-dimensional array of char named a, a[i][j] is located j elements after the start of a[i]. Each of those elements is a char, so calculating j char beyond a[i] is easy. And a[i] starts i elements after the start of a. But the elements of a are arrays of char. To know how big i elements is, you must know the size of the element; you must know the size of the array of char.
So a two-dimensional array cannot be used unless the size of the second dimension is known.
There are ways to use a two-dimensional array whose second-dimension size is known at run-time, including:
Use a one-dimensional array and calculating indices into it manually, as with a[i*size + j].
Use a one-dimensional array and convert its address. For example, from some structure s with member m, (char (*)[size]) s.m, which can then be used as ((char (*)[size]) s.m)[i][j]. (See other Stack Overflow questions and answers for language-lawyer issues about treating one-dimensional arrays as two-dimensional arrays.)
Also, your member name argv suggests you might want this structure to store command-line arguments passed as a parameter of main. If so, you should be mindful that the argv second parameter of main is a pointer to pointers, not a pointer to an array. The data in those strings is generally not arranged in memory for use as a two-dimensional array of char. You could copy the strings into a two-dimensional array, but that would generally be wasteful.
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).
I am learning C using learn-c.org, and on this page it says I can use
char name[] = "John"
In its own example on the bottom frame of the page, if I do
char last_name[] = "Doe"
no errors are reported but the program won't run. It will only run if I do char last_name[4] or greater... so the question:
Can an array be declared without a size or do I need to know the max values the array will hold? So kind of a second question, if I do int array[10], what would happen if I needed more than 10 values?
Can an array be declared without a size or do I need to know the max
values the array will hold?
Depends on whether you initialize it. When you initialize it, the compiler will count the elements for you. So, this is valid:
int a[] = { 0, 1, 2, 3 };
This effectively creates an array of 4 elements. If you provide a size and initialize the array, then if the size is greater than the number of elements, the first elements are initialized accordingly, and the rest of them are initialized to their default initialization value (0 for integers, null for pointers, etc.).
If the size is less than the number of elements, it is an error.
If you do not initialize, then you have to declare the size.
With this:
char last_name[] = "Doe";
The compiler creates an array of 4 chars (one of them is the null terminator).
If I do int array[10], what would happen if I needed more than 10
values?
You can't do anything. If you need more than 10, you need a bigger array.
You can either have an array with fixed size or a pointer to an array (starts with *) that can have any size (up to its limits that is).
As for the second question, the program would crash as the array would get out of its boundaries.
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
Please look at this peice of code :-
#include<stdio.h>
int main()
{
int arr[2][2]={1,2,3,4};
printf("%d %u %u",**arr,*arr,arr);
return 0;
}
When i compiled and executed this program i got same value for arr and *arr which is the starting address of the 2 d array.
For example:- 1 3214506 3214506
My question is why does dereferencing arr ( *arr ) does not print the value stored at the address contained in arr ?
*arr is type integer array of length 2, so it shares the same address as arr. They both point to the beginning of their arrays, which is the same location.
in C, a 2d array is not represented in memory as an array of arrays; rather, it is a regular 1d array, in which the first given dimension is needed in order to calculate the right offset within the array at execution time. This is why in a multi-dimensional array you always need to specify all the dimensions except the last one (which is not required); for example, if you declare an array like
int a[2][3][4];
the array would be represented in memory as a single array of 2*3*4 elements in total. Trying to access the element at position (i,j,k), will actually be translated into accessing the element 3*i+4*j+k in the plain array. In some sense, the initial dimensions are needed to know where to put "row breaks" in the 1d array.