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)
Sizeof array through function in C [duplicate]
(2 answers)
Closed 4 months ago.
#include <stdio.h>
int avg(int []);
void main(){
int average;
int marks[5]={10,15,20,30,45};
printf("%d\n",sizeof(marks)); // answer is 20(as expected)
avg(marks);
}
int avg(int marks[]){
int sum=0;
printf("%d\n",sizeof(marks)); // answer is 8(why???)
}
In this code, I was trying to print the sizeof the integer pointer marks. When I print the sizeof the marks inside the main method it gives 20 as the result as we expected. But the same object passes to the avg function and prints the sizeof marks it shows the result as 8. I couldn't understand why that was happening.
Can anyone please clarify this?
Any help would be appreciated.
In the C programming language, arrays "decay" into pointers when passed to functions.
This means that in the scope where an array is declared, sizeof will be able to tell you how many bytes it takes up, but once it is passed to another function, sizeof can only tell you the size of a pointer to the type of the array. Effectively, when an array is passed as a parameter, you lose all length-of-array related information. All that is preserved is the memory-address where the array starts, and its type, so in your case, sizeof marks in main() is equivalent to sizeof(int[5]) and sizeof marks in avg() is equivalent to sizeof(int*).
The consequences of this are that if you are going to be passing arrays of different lengths to a function, then you either have to send a separate length parameter, or give the function some way to infer the length of the array.
For instance, C strings are implemented as arrays of char, such that the last character of the array is the null-terminator byte, '\0'. This allows a function that expects a C-standard string parameter to keep reading byte after byte from the string without stopping until it finds the '\0', but this is controversial, as it is a rather significant source of bugs and security concerns, because if this assumption fails, and there is no '\0' at the end of the string, then the function could very well blindly access memory it has no business messing with.
If you need to pass an array pointer to a function and preserve its length, the best (or perhaps least controversial) solution is to pass the length along with the array, so int avg(int marks[],int numMarks); might be a function prototype that will serve your purposes. You could implement a system, where there is a value of int that is an invalid mark to be averaged, and use it to mark the end of the array, but this is likely a more difficult solution to implement safely.
It is size of the int*, which is 8 on your system.
Related
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
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
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);
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Stack pointer difference for char pointer and array
To illustrate my question:
int main(void){
int myary[20];
int *myaryPtr;
myaryPtr = myary;
sizeof(myary); // Will it return 80? Correct?
sizeof(myaryPtr); // Will it return 4? Correct?
return 0;
}
First off, is my assumption correct?
And then assuming my assumption is correct, what is the detailed explanation? I understand that my 20 element array is 80 bytes, but isn't the name myary merely a pointer to the first element of the array? So shouldn't it also be 4?
Yes, your assumption is correct, assuming an int and a pointer are both 4 bytes long on your machine.
And no, arrays aren't pointers. The array name sometimes decays into a pointer in certain contexts, but they aren't the same thing. There is a whole section of the comp.lang.c FAQ dedicated to this common point of confusion.
The size of the array is not stored in memory in either case, whether you declare it as int myArr[20] or int* myArrPtr.
What happens is that sizeof() is replaced (by the compiler) with a constant value.
Therefore, because myArr was specified with a fixed size prior to compilation, the compiler knows just how big the amount of memory allocated is. With myArrPtr, you could dynamically allocate different array sizes, so only the size of the type is stored.
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.