For illustration,two dimensional pointer arrays in C like int* x[][4] can be declared ,where first index can be fixed at run time that it is dynamic then can i say that dynamic declaration of dynamic one-dimensional array can be achieved in someway by replacing the second index to value 1 like int*[][1] and for two dimensional array dynamic two-dimensional array by int*[][][1] Does calloc() malloc() internally use them is my logic correct at all and this applied that is in a simplistic case of dynamic array declaration use inside a function in C language program
For illustration,two dimensional pointer arrays in C like int* x[][4]
can be declared
Only in two cases:
when an initializer for x implicitly conveys the value of the first dimension,
int* x[][4] = { {NULL, NULL, NULL, NULL}, {NULL, NULL, NULL, NULL} };
as the type of a function parameter. In that case, it is exactly equivalent to declaring the parameter to have type int *(*)[4]: pointer to array of four pointers to int. And that would also be the case if the first dimension were actually given.
void foo(int* x[][4]);
,where first index can be fixed at run time
In case (1) above, no, the first dimension is determined at compile time.
In case (2) above, not exactly. It is then the declaration of a pointer to a 1D array. Such a pointer can point to the first element of a 2D array of int *, and it can be indexed as if it in fact designated such a 2D array. The size of the first dimension is not conveyed, but if the pointer in fact points to an object then that dimension is fixed for the function's purposes, whether the pointed-to object is dynamically allocated or not.
that it is
dynamic then can i say that dynamic declaration of dynamic
one-dimensional array can be achieved in someway by replacing the
second index to value 1 like int*[][1]
That change produces a statically different type (in those contexts where it is valid at all). In case (2), but not case (1), both this type and the one we were discussing previously can point to a dynamically-allocated object, but they can also point to an automatic- or static-duration object of appropriate type. There's nothing inherently dynamic there.
and for two dimensional array
dynamic two-dimensional array by int*[][][1]
No. Not even for the type of a function parameter. At most the (one) leading dimension can be omitted.
Does calloc() malloc()
internally use them
Not at all. How could they? The allocation functions do not see this datatype at all. You tell them only how much space to allocate, either as a single composite value (malloc) or as an (element count, element size) pair (calloc). Thus the caller needs to know how much memory is needed. And this in any event applies only in case (2). Case (1) inherently produces static or automatic allocation, not dynamic.
is my logic correct at all
No.
and this applied that
is in a simplistic case of dynamic array declaration use inside a
function in C language program
Neither as a local variable of a function (case 1) nor as a function parameter (case 2).
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.
This question already has answers here:
Finding length of array inside a function [duplicate]
(7 answers)
Closed 2 years ago.
In C I can write a function declaration in 2 different ways (Which I was told are totally equal)
void test (int *arr);
void test (int arr[]);
But why we every need to use the first one? I mean the latter allows us to get the number of elements in the array using sizeof() something which isn't possible in the first one.
I mean the latter allows us to get the number of elements in the array using sizeof() something which isn't possible in the first one.
No, that's not possible for the latter, too. Here is a misunderstanding of yours. Both notations are absolutely equivalent as function parameter and denote a pointer. arr[] does not denote an array nor a pointer to an array explicitly.
Take a look at here:
C pointer notation compared to array notation: When passing to function
You can only get the size of the array if you use sizeof() at the array name itself inside of the scope the array is visible or pass another argument/parameter to the function which contains the information about the size of an array from the previous sizeof() use.
You cannot use sizeof() at a pointer to an array to get the array size, neither in the function where the array is declared nor in another.
But why we every need to use the first one?
To simple symbolize that it is a single pointer and not an array as this confusion in fact already brought you to here. :-)
I mean the latter allows us to get the number of elements in the array using sizeof() something which isn't possible in the first one.
This statement is wrong.
Both versions are in fact identical.
The function does not know the size of the array and you cannot use sizeof to get the size of the array. Instead you will only get the size of the pointer which the passed array decays to.
I mean the latter allows us to get the number of elements in the array
using sizeof()
No, it is not right information at all as to functions. After passing an array to a function taking the array as a parameter, the array decays into pointer thereby yielding size of the type's pointer type rather than that of the type per se.
For example for int type,
sizeof int
sizeof *int
Many people say compiler would not know the size information if no column size is provided. But How compiler knows the row size? And why column size can't be interpreted?
While passing an array as an argument to a function, compiler implicitly converts the array reference to the pointer. This can be clearly seen in the case of one dimensional array, like
int method(int *a)
int method(int a[])
Both these lines are equivalent here (although pointer and array reference are different) because whenever an array appears in an expression, the compiler implicitly generates a pointer to the array's first element, just as if the programmer had written &a[0]. However this rule is not recursive i.e. passing a 2d array is treated as pointer to an array, not a pointer to a pointer.
int method(int b[3][5]);
is converted to
int method(int (*b)[5]);
And since the called function doesn't allocate space for the array so size of row is not important, however size of column is still important to provide the size of array. For further reference you can visit here.
I'm not sure if the history tag is relevant, but feel free to add it.
I would presume the reason is historical, which is why I suggest this.
Why is it that I cannot declare a function signature such as the following?
void foo(int doubly_indexed_array[][]) {
...
}
which gives
$ gcc mem.c
mem.c:4: error: array type has incomplete element type
Why must you declare one of the dimensions as in the following?
void foo(int doubly_indexed_array[][10]) {
...
}
You need to declare the second one and not only one. It has to do with memory layout, a 2-d array is stored contiguously in memory which means all the second dimension arrays are contigous.
So for int[2][2] the memory layout looks like(assuming initialization to 0):
[[0, 0][0, 0]]
Compiler has to know by how much to increment the pointer when indexing on the first dimension for example. So if an int array is named a,
a[i][j] is really (address of a) + i*sizeof(int)*second_dimension + j*sizeof(int)
All of this need to be known at compile time so the compiler can generate code.
In essence, all arrays in C are one-dimensional. In order to be able to access an element by it's index, C needs to now the type of the elements.
Consider a one-dimensional array of ints. Since C knows the size of an int (say 4 bytes) it knows that to access element 50 it simply adds 50 * 4 = 200 bytes to the base address of the array. So it only needs to know the base address and the type of the elements, and not the overall number of elements (since C does not check for an out-of-range access, which would otherwise require the overall size).
Now a two-dimensional array is really a one-dimensional array whose elements are themselves arrays. In order to access an element in the "outer" array, you need to know its "type", which is an array of a certain type and size.
Consider a two-dimensional array declared as int a[100][10]. Since C knows that the type of the "outer" array is an array of 10 ints, it can calculate the position of the element (which itself is an array) at offset 50 by adding 50 * 4 * 10 to the base address. Note that the size of the "inner" array is necessary to find the position of the element. From that point it does the same thing as the previous example to find the position within the "inner" array of the requested int element.
Overall you have to declare the sizes of all the dimensions except the outermost one in order for C to be able to properly access the array.
The declaration void foo(int array[][]) violates C 2011 (N1570) 6.7.6.2 1, which addresses array declarations and says, in part, “The element type shall not be an incomplete or function type.” Since array is an array of array of int, its element type is array of int, and it is incomplete because the number of int in that array is not specified.
Contrary to other answers, though, this number is not needed by the compiler at this point. You can make an equivalent declaration of void foo(int (*array)[]). There are two points to note about this:
It does not violate the rule in 6.7.6.2 because it declares array to be a pointer, rather than an array. Pointers are permitted to point to incomplete types.
If the first declaration were permitted, it would actually be the same as this declaration, because 6.7.6.3 says “A declaration of a parameter as “array of type” shall be adjusted to “qualified pointer to type”,…
However, the only way you can access elements with this declaration is in the form (*array)[i]. This is legal because the * operator may dereference a pointer to an incomplete type, so *array is the first row of the array, and then (*array)[i] is the ith element of that row.
You cannot properly access other rows of the array, because this requires an expression such as array[j][i], which requires performing pointer arithmetic on array, and pointer arithmetic requires that the pointer point to an object of complete type (because, for the compiler to figure out where objects beyond the one pointed to are, it must know how big the objects are, so it must have complete information about their size).
Array in C is just like pointers, it doesn't include the size. Therefore if you don't provide the last dimension the compiler won't know how to calculate the address of the element
TYPE array[A][B];
&array[a][b] = (char*)array + a*sizeof(array[a]) + b
= (char*)array + a*(B*sizeof(array[a][b])) + b
= (char*)array + a*B*sizeof(TYPE) + b
As you see, if B is not declared then it have 3 unknown variables to solve when you're accessing array[a][b], that's the 2 dimension's index and B. That's why the compiler needs the last dimension size to produce code. Similarly it'll need the last n-1 dimensions of an n-dimensional array
I have a function in C (I am using gcc 4.8.0) which receives an array as its argument. Is there a way to accurately determine the number of elements in the array, without passing an additional argument array_count?
There is no way to determine in general the number of array elements passed as parameter.
When you pass a array as argument in C, you only pass the pointer to that array, that is the pointer to the first element (indexed 0) of the memory zone holding that array.
Very often, programmers have the convention of passing, as another argument, the size of that array. For example, the standard qsort(3) library function is expecting, as its second nmemb argument, the number of elements in the array to be sorted.
Alternatively, you might use flexible array members, e.g. pass (in C99, not in earlier C standard) address of structures like
struct my_flexarray_st {
int size; // allocated size
int len; // used length, should be less than size
double arr[]; /// only len numbers are meaningful
};
Whatever method you use, you need to understand that array sizes are conventionally known by functions when passed by argument. So please, document that convention. You could even have the (bad) convention that all arrays have some global variable as their dimension.
For heap allocated memory zones, the standard gives you malloc, calloc and friends to get such fresh zones, but no way to query their allocated sizes. Some C libraries have non-standard extensions to query that (but I don't recommend using them).
In recent C++11 (which is not the same as the C language) you might be interested by std::vector and std::array template containers.
Arrays decay into pointers in function arguments so size cannot be determined.
An lvalue [see question 2.5] of type array-of-T which appears in an expression decays (with three exceptions) into a pointer to its first element; the type of the resultant pointer is pointer-to-T because an array is not a "modifiable lvalue,"
(The exceptions are when the array is the operand of a sizeof or & operator, or is a literal string initializer for a character array.)
You can't , unless the array is static (i.e. not dynamic-allocated) , then you can use sizeof operator.
Not possible. This is why you either use a data structure like a linked list where you can actually determine the length or you require a length argument in your function.
Even with the required length argument alone there is no way to know it is true.
So, your API should also require a standard sentinel value to terminate the array.
Generally this could be NULL or something but depends on your array type.
This is doable in C. You can query size of array if you are in the same scope of its definition via sizeof. If you are in scope of function which takes array as parameter you need to declare the parameter as pointer to array (not just as array - in this case array will decay to pointer to first element), in this case size of array would be saved during argument passing:
void foo(int (*param)[3] ) { assert (sizeof(*param) == sizeof(int)*3; }
However, if you mean by "array" pointer to some dynamically allocated memory with not-known at compile time size, then you definetely need to pass size separately.
you can do a while look
function(arr[])
{
/* not this is pseduo code */
int i = 0;
while (*arr[i++] != null)
{
}
// i is number of elements
}