Array its not printing its size inside function [duplicate] - arrays

This question already has answers here:
How do I determine the size of my array in C?
(24 answers)
Miscalculation of array size inside a function
(3 answers)
Closed 1 year ago.
It's printing 0 but I expect 1. The size of first dimension in array is omitted because I want to pass multiple arrays entries in this same method how to get this for iteration
void printValues(char hotelData[][3][50], int n);
char hotelData [1][3][50] =
{
"unidadeid1Fk", "john fernandes", "executiveRoom"
};
int main( void )
{
printValues(hotelData, 0);
}
void printValues(char hotelData[][3][50], int n)
{
int arraySize = sizeof (hotelData) / sizeof (hotelData[0]);
printf("ArraySize: %i ", arraySize);
}
Output is
ArraySize: 0
And this code is returning this warning that I don't know what means and how to solve it:
teste.c: In function 'printValues': teste.c:29:32: warning: 'sizeof' on array function parameter 'hotelData' will return size of 'char
(*)[3][50]' [-Wsizeof-array-argument]
int arraySize = sizeof (hotelData) / sizeof (hotelData[0]);
^ teste.c:27:27: note: declared here
void printValues(char hotelData[][3][50], int n)

When an array is passed as an argument to a function, it is automatically converted to a pointer to its first element.1 Similarly, when a declaration of a parameter to a function is an array, it is automatically adjusted to be a pointer.
When the pointer to the first element of the array is passed, no size information is automatically passed. If, inside of the function, you want to know the size of the array, you must pass it as an argument or otherwise make it available to the function.
In contrast, the compiler knows the size of hotelData[0] because it knows the complete type of hotelData[0]. While hotelData has been converted to a pointer, it is a pointer of type “pointer to array of 3 arrays of 50 char” (also known as char (*)[3][50]), so it points to an array of 3 arrays of 50 char, and the size of that is 3•50•1 = 150.
The size of the pointer hotelData is likely 4 or 8 bytes. In any case, it is certainly less than 150 bytes, so dividing it by 150 yields 0 (in integer arithmetic).
Generally, the compiler only knows the sizes of things whose complete type declarations are visible. Even neglecting the fact that the parameter declaration char hotelData[][3][50] is automatically adjusted to char (*hotelData)[3][50], the complete type of hotelData[][3][50] is not visible at this point in the source code because the [] is empty. C does not pass any extra information about the size of an object along with the function argument; the type information has to be completely known from the parameter declaration. (Although you and I can see the call to printValues in the main routine above, the compiler is not able to use the information about the external object named hotelData in application to the parameter named hotelData; they are different things in spite of having the same name.)
Footnote
1 Whenever an array is used in an expression, it is automatically converted to a pointer to its first element unless it is the the operand of sizeof, is the operand of unary & or is a string literal used to initialize an array.

Related

Create a function to return the length of an int array in C [duplicate]

This question already has answers here:
Finding length of array inside a function [duplicate]
(7 answers)
Closed 2 years ago.
I'm new to c programming. I want to create a function that takes an integer array as argument and returns length of the array. I know that the code below calculates the length correctly.
int arr[] = {1, 2, 3, 4, 5};
int length = sizeof(arr) / sizeof(arr[0]);
But if I create a function like below and pass the array as an argument, it doesn't work.
int length_of(int* arr) {
return sizeof(arr) / sizeof(arr[0]);
}
My guess is that I'm not passing the array into the function correctly. What is the correct way of implementing this?
Well, there's no way of getting this done from a function. Any array, passed to a function as argument will decay to a pointer type (to the first element). So, inside the called function, all you will get is a size of a pointer.
An indirect way of achieving this would be to have something called a sentinel value in the array, and from the called function, iterate over the array elements to find the sentinel value while incrementing a counter, and once found, take the length of that counter.
Here's what the standard says (C99 6.3.2.1/3 - Other operands - Lvalues, arrays, and function designators):
Except when it is the operand of the sizeof operator or the unary & operator, or is a
string literal used to initialize an array, an expression that has type ‘‘array of type’’ is
converted to an expression with type ‘‘pointer to type’’ that points to the initial element of
the array object and is not an lvalue.
This means that pretty much anytime the array name is used in an expression, it is automatically converted to a pointer to the 1st item in the array.
As already answered, you cannot do this in a function. A common solution for that is to use a Macro. See e.g. Common array length macro for C?
You are passing a pointer as the parameter into your function, so it is not possible to know the size of the array by just knowing the size of parameter you pass to the function.
The most standard way of calculating size of an array in C is the one you mentioned in your question:
int a[10];
size_t n = sizeof(a) / sizeof(a[0]);
As other answers have pointed out, it is not possible to determine the size of an array inside of a function in the general case, i.e. without assumptions.
If this is really about returning the size of an array from a function at any cost, I chip in the general method of determining the length based on special knowledge/assumptions on the CONTENT of the array. This is how the strlen() function determines the length of NULLTERMINATED character sequences, which is the closest thing C has to string.
The special assumption on the content of the character sequence is that they only contain the terminating '\0' at the end. Many a StackOverflow question was asked because of the traps and vulnerabilities involved in that concept causing misunderstandings.
So, if you can for example assume that the array in question only contains non-negative integers (i.e. positive values and 0) and that the last valid value inside the array, at index (size-1), is negative, then you can determine the length of the array by search for that terminator, i.e. the first negative value you find at or behind the address from the pointer parameter.
If your prime intention is to return the array size from the function then pass the size as the argument.
Because once the argument is passed to function it will be pointing to the first element
So the code goes like
#include <stdio.h>
int func_len(int number)
{
return number;
}
int main()
{
int arr[]={1,2,3,4,5};
int size = sizeof(arr)/sizeof(arr[0]);
printf("Length is %d\n",size);
printf("Length is %d",func_len(size));
}
Output will be
Length is 5
Length is 5

Number of bytes in void pointer [duplicate]

This question already has answers here:
C: Extrapolating type from void pointer
(4 answers)
How to get memory block length after malloc?
(7 answers)
Closed 5 years ago.
Let's say I have a C function:
Func(void* param);
Is there a way to know number of bytes of param content?
No, it is not possible. That's why almost all functions that takes pointers as arguments has an extra argument for size. It should be like this:
void func(void *param, int size);
Also note that it is up to the function to interpret the size argument. It can be number of bytes, number of elements or whatever.
The important thing here to remember is the only thing param is, is a memory address. Nothing more, nothing less.
Some functions doesn't utilize this. One example is strcpy(char * dest, char * src) that copies a string, but this function assumes two things. It assumes that src is a zero-terminated string. strcpy will read from src until it hits a '\0' character. Furthermore, it assumes that dest points at a memory location big enough to hold the string.
sizeof(*param) will not work. param is only a pointer to where the memory chunk starts. It would be the same as using sizeof(void)
For starters the type void is an incomplete type that is its size in bytes is indeterminate.
From the C Standard (6.2.5 Types)
19 The void type comprises an empty set of values; it is an incomplete
object type that cannot be completed.
However if you have a pointer of some other type as an argument of a function as for example
T *param
then in general case you again will be unable to determine the number of bytes occupied by the referenced actual data.
Pointers do not keep information whether they point to a single object or the first object of an array.
For example if you have a function declared like this
void f( const char *s );
then it can be called for example for these objects of different types
char c = 'A';
f( &c );
and
char s[] = "Hello";
f( s );
Of course you can get the number of bytes occupied by the element of an array or a single object referenced to by pointer as for example using expression
sizeof( *param )
But in case of the type void * you may not do even this though some compilers have their own language extensions that allow to apply the operator sizeof for the type void. In this case the returned value of the expression is usually equal to 1.
No. Without knowing what param is pointing to, you can't know what size it is.

Why is char*p[10] considered char** p by the compiler? [duplicate]

This question already has answers here:
Should I use char** argv or char* argv[]?
(10 answers)
Closed 8 years ago.
I've been fiddling around to see if there's any way to retain information about an array's length automatically when passed into a function (see my other question here: Why is this array size "workaround" giving me a warning?), but my question is more about a warning that gcc is giving that doesn't make sense to me.
According to this website (EDIT: I misread the website), char *p[10] declares a pointer to a 10-wide array of chars. But when I tried to pass in a pointer to an array into a function, I got this error message from the compiler:
Here is the rest of the program:
I know that when an array is passed into a function, it decays into a pointer (losing information about its length), but it seems that the declaration itself is decaying. What's going on here?
EDIT: When I replace the char *p[10] with char (*p)[10], it doesn't give the warning anymore, and more importantly, it displays the proper array length: 10. I guess my questions are 1) Why do the parentheses change things? and 2) Is this a well-known workaround or am I relying on some behavior of the compiler that isn't guaranteed? (i.e. that array length info can be passed by indirectly passing in a pointer to it?)
In fact char *p[10] is an array, of length 10, of pointers to char. You are looking for char (*p)[10]. That is a pointer to an array, of length 10, of char.
You might find http://cdecl.org/ a useful resource to help you test your understanding of declarations.
Regarding the discussion surrounding dynamic arrays, you are going to have to accept that once you allocate an array dynamically, the system provides no means for you to recover the length of the array. It is your responsibility to remember that information.
The subject of your question has been answered already but I wanted to address the heart of it, which is "can I encode the length of an array in its type?" Which is in fact what a pointer-to-array does. The real question is whether you can actually gain any brevity or safety from this. Consider that in each scope where you have a declaration of your type, the length still needs to be known a-priori. To show you what I mean let's generalize your example slightly by making 10 a compile-time constant N.
#define N 10
size_t arraylength(char (*arrayp)[N]) {
return sizeof(*arrayp);
}
int main(void) {
char array[N];
assert( arraylength(&array) == N ); //always true
}
So far so good. We didn't have to pass the length of array anywhere. But it's easy to see that anywhere the expression sizeof(*arrayp) is used, we also could have written N. And any place we declare a char(*)[ ], the bracketed length must come from somewhere.
So what if N isn't a compile time constant, and array is either a VLA or a pointer-to-array from malloc? We can still write and call arraysize, but it looks like this:
size_t arraylength(size_t N, char (*arrayp)[N]) {
return sizeof(*arrayp);
}
int main(void) {
size_t N = length_from_somewhere();
char array[N];
assert( arraylength(sizeof(array), &array) == N );
}
In defining arraysize N must still be visible before the declaration of arrayp. In either case, we can't avoid having N visible outside of the declaration of arrayp. In fact, we didn't gain anything over writing arraysize(size_t N, char* array) and passing array directly (which is a bit silly given the purpose of this function.) Both times arraylength could have equally been written return N;
Which isn't to say that array pointers are useless as parameters to functions -- in the opposite situation, when you want to enforce a length, they can provide type checking to make sure somefunc(char (*)[10]); receives a pointer to an array that is really (sans shady casting) 10 elements long, which is stronger than what a construct like [static 10] provides.
Also keep in mind that all of the length measurements above depend on the underlying type being char where length == size. For any larger type, taking the length requires the usual arithmetic e.g.
sizeof(*arrayp)/sizeof((*arrayp)[0])
In C, arrays decay to pointers to their first elements on most uses. In particular, what a function receives is always just a pointer to the first element, the size of the array is not passed with it.
Get a good text on C and read up on arrays.
I've been fiddling around to see if there's any way to retain information about an array's length automatically when passed into a function
The problem is so annoying that lots of programmers would love to have an answer. Unfortunately, this is not possible.
It seems that the declaration itself is decaying
Pointer to an array is not the same as a pointer to a pointer; that is why you are getting an error.
There is no decaying going on in your code, because you are not passing an array in your code sample: instead, you are trying to pass a pointer to an array &p. The pointer to an array of characters is not compatible to the expected type of the function, which is char**. Array size from the declaration is ignored.
You need to keep in mind two things:
1. Arrays are not pointers.
2. Array names decays to pointers (in most cases) when passed as arguments to functions.
So, when you declare
int a[10]; // a is an array of 10 ints
int *b; // b is a pointer to int
both of a and b are of different types. Former is of type int [10] while latter is of type int *.
In case of function parameter
void foo1 (int a[10]); // Actually you are not passing entire array
void foo2 (int a[]); // And that's why you can omit the first dimension.
void foo3 (int *a); // and the compiler interprets the above two third
ain all of the above function declarations is of same data type int *.
Now in your case
unsigned long arraySize(char *p[10]);
you can declare it as
unsigned long arraySize(char *p[]);
and hence
unsigned long arraySize(char **p);
All are equivalent.
char *p[10] char *p[] and char **p all are exactly equivalent but when they are declared as parameter of a function otherwise char *p[10] (an array of 10 pointers to char) and char **p (a pointer to pointer to char)are entirely of different type.
Suggested reading: C-FAQ: 6. Arrays and Pointers explains this in detailed.
Array name itself is a constant pointer. for example int arr[10]={0};
arr contains the address of arr[0]. hence arr equals&arr[0] .
when u pass the arraysize(&p) , you are actually passing a double pointer .
The correct format to pass a array pointer would be arraysize(&p[0]) or arraysizeof(p)
Note Array name is constant pointer , you cant change its value .
int arr[10];
arr++;
is invalid.
In your case you cant find a size of an array in function by passing the array name . it would return size of pointer(4 or 8 depends on your processor .
The method is to pass the size along with the array
func(array_name , array_size);

What happens when I call a function with an array name as an argument? [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 9 years ago.
I am reading the TCPL by K&R, when I read something about array and pointer, I write this small code below:
#include <stdio.h>
int sum(int a[])
{
int t = 0;
int length = sizeof(a) / sizeof(a[0]) ;
// printf("%d\n",length);
for(int i = 0; i != length; ++i)
{
t += a[i];
}
return t;
}
int main()
{
int b[5] = {1, 2, 3, 4, 5};
printf("%d\n",sum(b));
return 0;
}
The output answer is 1 NOT 15, then I debug this code by adding printf("%d\n",length); the output length is 1 NOT 5.
The TCPL tells that a array name converts to pointer when the array name used as argument, but the output answer is wrong, so I wonder that:
What happend when call a funcion with array name used as argument?
The array a[] used parameter in sum(int a[]) has storage or not?
I see two styles when calling a array : fun(int a[]); fun(b) and fun(int *a);fun(b),what the difference?
Thx very much :-)
You cannot call a function and pass a whole array; if you use an array name as a function argument, it is implicitly rewritten as ("decays to") a pointer to its first element. It is equivalent to writing
int sum(int *a) { ... }
Thus, within the function, sizeof array, does NOT give you the size of the array, only the size of a pointer to its first element.
So how do you know how many elements there are in the array? You need to pass this number explicitly to functions (or define a macro with the number of elements and use it where needed).
Your third question gets to the heart of the matter: there is no difference between those two as far as the compiler is concerned. Everything about how the argument is passed is the same.
Therefore, in response to your second question, the a parameter doesn't have storage for the underlying array, nor are the members of that array copied. The only storage allocated is for an int * pointer, and that pointer is stored in a. (That somewhat answers your first question as well.)
So, in your function:
int length = sizeof(a) / sizeof(a[0]) ;
is equivalent to
int length = sizeof(int *) / sizeof(int);
which returns 1 on systems where pointers and ints are the same size. If you run this on 64-bit Linux, you will get 2 instead, since pointers are 64 bits and ints are 32 bits.
Calling sizeof on an array declared as follows
int a[5];
will return the size of the array how you currently think it will (ie the full size in bytes of the array - in this case 20 bytes on my machine). When you pass an array like this to a function, the array will decay to a pointer to its first element. Thus when you call sizeof on your function argument you are actually calling it on a pointer type. Had you declared your function to take an int * argument, the error would be more obvious as the type of the variable that you call sizeof is explicit.
There is no problem with your call, and there is no difference between fun(int a[]) and fun(int *a) (expect that it is more obvious to the reader that you expect an array and not any pointer). Bot arguments are a pointer to an int.
Your problem here is how you try to determine the length of the array. As the square brackets are empty, there is no way for the compiler to know how long the array behind a is. You can for example provide the length of the array as a second argument. Note: When calling the function, sizeof(b) will provide the correct length, because the compiler knows its length.
The sizeof() operator can not be used for getting a dynamically allocated array length.
Here you can find examples of the sizeof() using.
When you try to do sizeof(array_ptr) it is actually gives you size of the pointer.
Thus, you have to pass array length as parameter of the function

How does an array pointer store its size? [duplicate]

This question already has answers here:
Why isn't the size of an array parameter the same as within main?
(13 answers)
Closed 7 years ago.
#include "stdio.h"
#define COUNT(a) (sizeof(a) / sizeof(*(a)))
void test(int b[]) {
printf("2, count:%d\n", COUNT(b));
}
int main(void) {
int a[] = { 1,2,3 };
printf("1, count:%d\n", COUNT(a));
test(a);
return 0;
}
The result is obvious:
1, count:3
2, count:1
My questions:
Where is the length(count/size) info stored when "a" is declared?
Why is the length(count/size) info lost when "a" is passed to the test() function?
There's no such thing as "array pointer" in C language.
The size is not stored anywhere. a is not a pointer, a is an object of type int[3], which is a fact well known to the compiler at compile time. So, when you ask the compiler to calculate sizeof(a) / sizeof(*a) at compile time the compiler knows that the answer is 3.
When you pass your a to the function you are intentionally asking the compiler to convert array type to pointer type (since you declared the function parameter as a pointer). For pointers your sizeof expression produces a completely different result.
Where is the length(count/size) info stored when "a" is declared?
It's not stored anywhere. The sizeof operator (used in the COUNT() macro) returns the size of the entire array when it's given a true array as the operand (as it is in the first printf())
Why is the length(count/size) info lost when "a" is passed to the test() function?
Unfortunately, in C, array parameters to functions are a fiction. Arrays don't get passed to functions; the parameter is treated as a pointer, and the array argument passed in the function call gets 'decayed' into a simple pointer. The sizeof operator returns the size of the pointer, which has no correlation to the size of the array that was used as an argument.
As a side note, in C++ you can have a function parameter be a reference to an array, and in that case the full array type is made available to the function (i.e., the argument doesn't decay into a pointer and sizeof will return the size of the full array). However, in that case the argument must match the array type exactly (including the number of elements), which makes the technique mostly useful only with templates.
For example, the following C++ program will do what you expect:
#include "stdio.h"
#define COUNT(a) (sizeof(a) / sizeof(*(a)))
template <int T>
void test(int (&b)[T]) {
printf("2, count:%d\n", COUNT(b));
}
int main(int argc, char *argv[]) {
int a[] = { 1,2,3 };
printf("1, count:%d\n", COUNT(a));
test(a);
return 0;
}
Nowhere.
Because it wasn't stored in the first place.
When you refer to the array in main(), the actual array declaration definition is visible, so sizeof(a) gives the size of the array in bytes.
When you refer to the array in the function, the parameter is effectively 'void test(int *b), and the size of the pointer divided by the size of the thing it points at happens to be 1 on a 32-bit platform, whereas it would be 2 on a 64-bit platform with LP64 architecture (or, indeed, on an LLP64 platform like Windows-64) because pointers are 8 bytes and int is 4 bytes.
There isn't a universal way to determine the size of an array passed into a function; you have to pass it explicitly and manually.
From the comment:
I still have two questions:
What do you mean by "..the actual declaration is visible.."? [T]he compiler (or OS) could get the length info through sizeof(a) function?
Why the pointer &(a[0]) doesn't contain the length info as the pointer "a"?
I think you learned Java before you learned C, or some other more modern language. Ultimately, it comes down to "because that is the way C is defined". The OS is not involved; this is a purely compiler issue.
sizeof() is an operator, not a function. Unless you are dealing with a VLA (variable length array), it is evaluated at compile time and is a constant value.
Inside main(), the array definition (I misspoke when I said 'declaration') is there, and when the sizeof() operator is applied to the name of an actual array - as opposed to an array parameter to a function - then the size returned is the size of the array in bytes.
Because this is C and not Algol, Pascal, Java, C#, ...
C does not store the size of the array - period. That is a fact of life. And, when an array is passed to a function, the size information is not passed to the function; the array 'decays' to a pointer to the zeroth element of the array - and only that pointer is passed.
1. Where is the length(count/size) info stored when "a" is declared?
It isn't stored. The compiler knows what a is and therefore knows it's size. So the compiler can replace sizeof() with the actual size.
2. Why is the length(count/size) info lost when "a" is passed to the test() function?
In this case, b is declared as a pointer (even though it may point to a). Given a pointer, the compiler does not know the size of the data pointed to.
Array pointer does not store the size. However, the[] type is not actually a pointer. It's a different type. When you say int a[] = {1,2,3}; you define array of 3 elements, and since it is defined so, sizeof(a) gives you the size of the whole array.
When however you declare parameter as int a[], it's pretty much the same as int *a, and sizeof(a) would be the size of the pointer (which coincidentally may be the same as the size of int, but not always).
In C, there's no way to store the size in pointer type, so if you need the size, you'd have to pass it as additional argument or use struct.
Where is the length(count/size) info stored when "a" is declared?
Nowhere. The question doesn't make sense BTW.
Why is the length(count/size) info lost when "a" is passed to the test() function?
Array decays into pointer(to the first element) when passed to a function. So the answer is 'nowhere' and similar to the previous question this one again doesn't make any sense.

Resources