This question already has answers here:
size of array in c
(6 answers)
Closed 9 years ago.
How can I obtain the number of elements present in an integer array in C after the array is passed to a function? The following code doesn't work.
size=sizeof(array)/sizeof(array[0]);
In C, you can only get the size of statically allocated arrays, i.e.
int array[10];
size = sizeof(array) / sizeof(int);
would give 10.
If your array is declared or passed as int* array, there is no way to determine its size, given this pointer only.
You are most likely doing this inside the function to which you pass the array.
The array decays as pointer to first element So You cannot do so inside the called function.
Perform this calculation before calling the function and pass the size as an function argument.
You are going about it in the wrong way. I'll try to explain using a small code example. The explanation is in the code comments:
int array[100];
int size = sizeof(array) / sizeof(array[0]); // size = 100, but we don't know how many has been assigned a value
// When an array is passed as a parameter it is always passed as a pointer.
// it doesn't matter if the parameter is declared as an array or as a pointer.
int getArraySize(int arr[100]) { // This is the same as int getArraySize(int *arr) {
return sizeof(arr) / sizeof(arr[0]); // This will always return 1
}
As you can see from the code above you shouldn't use sizeof to find how many elements there are in an array. The correct way to do it is to have one (or two) variables to keep track of the size.
const int MAXSIZE 100;
int array[MAXSIZE];
int size = 0; // In the beginning the array is empty.
addValue(array, &size, 32); // Add the value 32 to the array
// size is now 1.
void addValue(int *arr, int *size, int value) {
if (size < MAXSIZE) {
arr[*size] = value;
++*size;
} else {
// Error! arr is already full!
}
}
Related
This program is supposed to return the highest number in the array "array". But it only returns the highest number between the first and second numbers. Why?
#include <stdio.h>
#include <stdlib.h>
int HighestNumber(int* array)
{
int highest = INT_MIN;
for(size_t x = 0; x < sizeof(array) / sizeof(array[0]); x++)
if(array[x] > highest)
highest = array[x];
return highest;
}
int main()
{
int *array = (int*)malloc(4*sizeof(int));
array[0] = 66;
array[1] = 552;
array[2] = -17;
array[3] = 1000;
printf("%d", HighestNumber(array));
return 0;
}
The function parameter array has the pointer type int *.
int HighestNumber(int* array);
So the expression sizeof(array) / sizeof(array[0]) is equivalent to expression sizeof( int * ) / sizeof( int ) and yields usually either value 2 or 1 dependent of the sizes of pointers and integers.
You need explicitly to pass the number of elements in the array As for example
int HighestNumber(int* array, size_t n );
Pay attention to that the user can pass 0 for the parameter n. In this case using your approach to the function definition the function can return an invalid value.
The function should be declared and defined the following way. As the function does not change the processed array then the first parameter should have the qualifier const.
size_t HighestNumber( const int *array, size_t n )
{
size_t highest = 0;
for ( size_t i = 1; i < n; i++ )
{
if ( array[highest] < array[i] )
{
highest = i;
}
}
return highest;
}
And the function is called like
printf("%d\n", array[HighestNumber(array, 4 )] );
or
size_t highest = HighestNumber(array, 4 );
printf( "The largest number is %d at the position %zu\n",
array[highest], highest);
As you can see the advantage of such function definition is that you can also determine the position where the highest element is stored in the array.
Pay attention to that you need to free the dynamically allocated memory.
free( array );
The sizeof trick doesn't work on pointers!
If applied to pointers you get the (truncated) ratio between the size of a pointer, which is always the same, no matter how large your array is, and the size of a single element in that array, so in your case with int* most likely either 2 (64-bit system, typically 8-byte pointers, 4-byte int) or 1 (32-bit system, typically 4-byte pointers, 4-byte int), though other systems can yield yet other values, but still not the required one (apart from accidentally matching array size...).
To use sizes on array you need to pass it explicitly by another parameter:
int highestNumber(size_t length, int* array)
{
int highest = INT_MIN;
while(length--)
{
if(*array > highest)
{
highest = *array;
}
++array;
}
return highest;
}
while you can then apply the sizeof trick on the array being passed to:
int array[4];
// assign values to
// array has not yet decayed to pointer, thus you can do:
int highest = highestNumber(sizeof(array)/sizeof(*array), array);
However in your example you use a dynamically allocated array – these only can be stored in pointers, thus there's no way around tracking the size explicitly:
size_t length = 4;
int* array = malloc(length * sizeof(*array));
// assign values
int highest = highestNumber(length, array);
Final note: You might as well use the length/size as second parameter, of course; having it as first would allow for:
int highestNumber(size_t length, int array[length]);
which is fully equivalent, as for the outermost dimension an explicitly specified array size is ignored and the parameter still remains a pointer (note that this does not apply for further dimensions), but this declaration expresses more explicitly what the function actually expects as arguments.
Edit (stealing from Vlad from Moscow's answer):
As you do not (intend to) modify the array within the function it is a good choice to accept a pointer to const – this allows to use both non-const and const arrays while the original function signature excludes the latter without need:
int highestNumber(size_t length, int const* array)
int highestNumber(size_t length, int const array[length]);
The moment you pass array to the function HighestNumber(), you lose the size information of the array. This is called an array-to-pointer decay.
To the function HighestNumber() it only sees a pointer, without knowing anything about the array.
Consider pass the array size as the second parameter to the function, such as
int HighestNumber(int* array, size_t num) {
// ..
}
An array decays to a pointer in function parameters. sizeof on a pointer then returns the size of the pointer, and not the pointed to data.
Possible solution:
Pass the size of the array as the second argument.
int HighestNumber(int* array, size_t size) {
//...
}
This question already has answers here:
Can you define the size of an array at runtime in C
(10 answers)
C dynamically growing array
(10 answers)
Closed 2 years ago.
I am trying to create an array of arrays but the the number of subarrays is unknown.
Jagged array is array of arrays such that member arrays can be of different sizes, i.e., we can create a 2-D array but with a variable number of columns in each row.
Static Jagged Array:
int kk0[4] = { 1, 2, 3, 4 };
int kk1[2] = { 5, 6 };
int* jagged[2] = { kk0, kk1 };
Dynamic Jagged Array:
int* jagged[2];
jagged[0] = malloc(sizeof(int) * 1);
jagged[1] = malloc(sizeof(int) * 3);
Reference : https://en.wikipedia.org/wiki/Jagged_array
If the number of sub arrays is not known then the array must be expandable when there are more sub arrays than you thought.
int **myArrays; // the array of arrays
int nSubArrays= 0; // its current size
int nUsed= 0; // how many have been used
#define INCREMENT 5 // increment for alocation
myArrays= malloc(sizeof(int *) * INCREMENT);
nSubArrays= INCREMENT;
nUsed= 0;
now fill the array(s):
myArrays[nUsed]= fillSubArray();
nUsed++;
and expand the array when it becomes full:
if (nUsed==nSubArrays) {
int **tmp= realloc(myArrays, sizeof(int *)*(nSubArrays+INCREMENT));
if (!tmp) return 0; // error
myArrays= tmp;
nSubArrays += INCREMENT;
"create an array of arrays but the the number of subarrays is unknown."
If using C99, or a compiler since then that supports variable length arrays (optional since C11), this would provide a way to do this at run-time. A short example:
#define ARRAY_BASE_SIZE 20 //known at compile time
int main()
{
int numSubArrays = 0;
printf("enter a value for number of sub-arrays:\n");
int count = scanf("%d", &numSubArrays);//not known until run-time
if(count == 1)
{
int array[ARRAY_BASE_SIZE][numSubArrays];
memset(array, 0, sizeof(array));
}
return 0;
}
How about this, its just an attempt to give a start point, not the complete answer, but we can build on this.
Also we need to keep track of size of each subarray to access valid locations, am sure that can be done easily by some kind of book keeping.
#include <stdio.h>
#include <stdlib.h>
#define BASE_SIZE 3
int main()
{
int** dyn_array = NULL;
int countSubArray = 0;
int count = 0;
int size = 0;
dyn_array = malloc(sizeof (int* ) * BASE_SIZE);
if ( dyn_array ) {
printf("enter number of subarrays:");
scanf("%d", &countSubArray);
while( count < countSubArray) {
printf("enter sizeof %d subarray", count+1);
scanf("%d", &size);
if ( dyn_array[count] = malloc(sizeof (int) * size) )
{
printf("Allocated sub array %d at %p\n",count+1, (void*) dyn_array[count]);
}
count++;
}
}
return 0;
}
In C it is very common practice to declare a pointer and reference it as an array. In C an array will decay to a pointer when the reference of the array is assigned to the pointer. To reference an array of arrays, it is common to declare a pointer-to-pointer, assign it to the reference of a 2-D array, and later index it like a 2-D array.
The following are all equivalent. argv is an array of array of char. Using [] makes your intention of using indexing a pointer as an array clear to other programmers who might be reading your code.
char **argv;
char *argv[];
char argv[][]; (this is wrong)
The size of the array is usually communicated separately. In fact, the parameters of the main function does just that. When you see
int main(int argc, char *argv[]);
The char *argv[] is an array of array of characters (aka array of strings) passed from the command line. The argument argc represents the number of arrays in argv. To index the first element in the array, use argv[0], whose type is will be char* (aka char[]).
This question already has answers here:
What does impossibility to return arrays actually mean in C?
(5 answers)
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 2 years ago.
I somehow can not return a int[] from my function I wrote in the code below. Can anybody explain why I am doing it wrong, instead of only posting a code solution .
Why can't I square all values and set arr = square_all(arr)?
#include <stdio.h>
void print(int arr[])
{
for(int i = 0; i <= sizeof(arr) / sizeof(int); i++)
{
printf("%i", arr[i]);
}
}
int* square_all(int arr[])
{
for(int i = 0; i <= sizeof(arr) / sizeof(int); i++)
{
arr[i] = arr[i] * arr[i];
}
return arr;
}
int main()
{
int arr[] = {1, 2, 3};
print(arr);
arr = square_all(arr);
return 0;
}
The problem isn't the returning, but rather the assignment to arr in the main function.
You can't assign to an array, only to its individual elements. You can also copy to an array.
However, in this case there's no need for an assignment (or a copy), since you modify the array in-place. So all you really need is:
square_all(arr); // No assignment
A larger problem is your use of sizeof in the functions. Because you don't pass an array to the functions, you pass a pointer. And the size of a pointer is the size of a pointer is the size of the actual pointer itself and not what it might point to.
See Why isn't the size of an array parameter the same as within main?
Furthermore, since array indexes are zero-based, an array of X elements will have indexes from 0 to X - 1, inclusive. That means a loop-condition like i <= X will include X as an index, and that's out of bounds. Use i < X as a loop condition instead.
My guess is that you misunderstood how arrays are passed to functions, that arrays are copied for the function calls, which they are not. A function argument declaration like int arr[] is actually translated by the compiler as int *arr. And when you call the function, you only pass a pointer to its first element (e.g. print(arr) is really equal to print(&arr[0])).
This question already has answers here:
"sizeof" to know the size of an array doesn't work in a function in C [duplicate]
(2 answers)
Closed 6 years ago.
When I print the (size of the array/size of the the first element), I get the right answer, but when I do the same thing in the function, I get the size of the array to be four and the size of the first element of the array to be four hence the division is always one.
#include<stdio.h>
int sizer(int *);
int main()
{
int num;
printf("Please an index: ");
scanf("%d",&num);
int array[num];
int size = sizer(array); //function to calculate array length
/*answer is always 4*/
printf("%d\n", size);
/*answer is correct*/
printf("%d\n", sizeof(array) / sizeof(array[0]));
return 0;
}
/*function to calculate array length*/
int sizer(int *array)
{
return sizeof(array) / sizeof(array[0]);
}
sizeof is not a function called at runtime, even though it looks like one. It is a feature of the compiler. It looks at a data object and replaces the sizeof() expression with a constant.
int arr[10];
int size = sizeof(arr)/sizeof(int);
This works because the compielr can see how big arr is. arr is a statically sized array here. Both sizeof expressions are replaced with the appropriate values.
int arr[10];
int size = sizer(arr);
....
int sizer(int array[]) {
return (sizeof(array)/sizeof(int));
}
This doesn't work. In sizer, array looks like an array but arrays passed in as parameters are actually just pointers to the array type. So sizeof(array) is equivalent to sizeof(int *)
scanf("%d",&num);
int arr[num];
int size1 = sizeof(arr)/sizeof(int);
int size2 = sizer(arr);
....
int sizer(int array[]) {
return (sizeof(array)/sizeof(int));
}
Here, size1 works but size2 doesn't. The creation of arr is actually allocated like this:
int arr_sizeof = sizeof(int)*num;
int *arr = alloca(arr_sizeof);
Then later on, sizeof(arr) is quietly replaced with arr_sizeof. But the compiler can only do this in the same scope that arr is created, because when arr is passed to sizer it's just converted to an int * again, so the size information is not carried over. sizer fails for thet same reason, arrays in function parameters are just passed along as simple pointers.
When you pass an array to a function you are really just passing a pointer to the first element, so in the body of sizer, the parameter array is just a pointer to int. Your function correctly returns sizeof(int*)/sizeof(int) (which is 2 rather than 4 on my machine), though this is probably not what you want. There really isn't any way for a function in C to compute the length of a passed array, which is why it is standard in C to pass the number of elements in an array as one of the parameters in any function which takes an array parameter.
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)
When a function has a specific-size array parameter, why is it replaced with a pointer?
(3 answers)
Closed 9 years ago.
I have the following code in c:
void getNumber(int numberArray[])
{
printf("The size of the array is %u", sizeof(numberArray));
}
void main()
{
int array[6] = {1,2,3,4,5,6};
getNumber(array);
}
but why the The size of the array is 4? And how to get the size of whole array?
void getNumber(int numberArray[])
is equivalent to
void getNumber(int* numberArray)
so sizeof(numberArray) is just measuring the size of int*.
If you want to know the length of the array, you either need to pass its length as a separate argument
void getNumber(int* numberArray, int len)
getNumber(array, sizeof(array)/sizeof(array[0]));
or arrange for the array to end with a known sentinel value
int array[] = {1,2,3,4,5,6,-1}; // assumes -1 is not a valid value
int arrayLength(int* numberArray)
{
int len=0;
while (*numberArray++ != -1) {
len++;
}
return len;
}
This is not possible, except if you're using C99 and the array is a variable-length array.
In general an array is very much like a pointer in C, and even more so when being passed to a function.
In case of getnumber(array) your array name array decays to pointer and is giving its size 4. In case of sizeof, an array name doesn't decays to pointer and hence giving the size of entire array.