I was trying to make a function for finding number of elements in an array. For this I approached for following code:
#include<iostream>
#include<stdlib>
int no_of_ele(A[]) //function to return size of array
{
return (sizeof(A)/sizeof(A[0]);
}
void main()
{
system("cls");
int arr[5] = {1,2,3,4,5};
cout<<"Number of elements in array are "<<no_of_ele(arr)<<endl;
system("pause");
}
In this approach I got output as follows:
Then, I did this:
cout<<"Size of array is "<<sizeof(arr)<<endl;
cout<<"Size of data type is "<<sizeof(arr[0]);
Now I got absolutely correct output of size as follows:
Why is it?
There are better ways these days, but the closest is:
#include<iostream>
template<std::size_t N>
int no_of_ele(int (&A)[N]){
return sizeof(A)/sizeof(A[0]); // or just return N
}
int main(int argc, char* argv[]){
int arr[5] = {1,2,3,4,5};
std::cout<<"Number of elements in array are "<<no_of_ele(arr)<<std::endl;
return 0;
}
Greetings to 1998. The question is, does Turbo C++ support templates?
See here for more: Is it possible to overload a function that can tell a fixed array from a pointer?
The array decayed to pointer when passed to your function.
sizeof(int)/sizeof(int)... = 1
Reason for this, the parameters are pushed on stack to the function. The compiler as declared by your function declaration will just send the address of your array.
When passing an array as a parameter
int func(int arr[])
Is just as:
int func(int *arr)
Giving an array as a function argument you can't determine its size using the sizeof.
Related
Is it possible to determine the size of an array if it was passed to another function (size isn't passed)? The array is initialized like int array[] = { XXX } ..
I understand that it's not possible to do sizeof since it will return the size of the pointer .. Reason I ask is because I need to run a for loop inside the other function where the array is passed. I tried something like:
for( int i = 0; array[i] != NULL; i++) {
........
}
But I noticed that at the near end of the array, array[i] sometimes contain garbage values like 758433 which is not a value specified in the initialization of the array..
The other answers overlook one feature of c++. You can pass arrays by reference, and use templates:
template <typename T, int N>
void func(T (&a) [N]) {
for (int i = 0; i < N; ++i) a[i] = T(); // reset all elements
}
then you can do this:
int x[10];
func(x);
but note, this only works for arrays, not pointers.
However, as other answers have noted, using std::vector is a better choice.
If it's within your control, use a STL container such as a vector or deque instead of an array.
Nope, it's not possible.
One workaround: place a special value at the last value of the array so you can recognize it.
One obvious solution is to use STL. If it's not a possibility, it's better to pass array length explicitly.
I'm skeptical about use the sentinel value trick, for this particular case. It works
better with arrays of pointers, because NULL is a good value for a sentinel. With
array of integers, it's not that easy - you need to have
a "magic" sentinel value, which is
not good.
Side note: If your array is defined and initalized as
int array[] = { X, Y, Z };
in the same scope as your loop, then
sizeof(array) will return it's real size in bytes, not the size of the pointer. You can get the array length as
sizeof(array) / sizeof(array[0])
However, in general case, if you get array as a pointer, you can't use this trick.
You could add a terminator to your int array then step through the array manually to discover the size within the method.
#include<iostream>
using namespace std;
int howBigIsBareArray(int arr[]){
int counter = 0;
while (arr[counter] != NULL){
counter++;
}
return counter;
}
int main(){
int a1[6] = {1,2,3,4,5,'\0'};
cout << "SizeOfMyArray: " << howBigIsBareArray(a1);
}
This program prints:
SizeOfMyArray: 5
This is an O(n) time complexity operation which is bad. You should never be stepping through an array just to discover its size.
If you can't pass the size, you do need a distinguishable sentinel value at the end (and you need to put it there yourself -- as you've found, you can't trust C++ to do it automagically for you!). There's no way to just have the called function magically divine the size, if that's not passed in and there is no explicit, reliable sentinel in use.
Can you try appending a null character \0 to the array and then send it? That way, you can just check for \0 in the loop.
Actually Chucks listing of
for( int i = 0; array[i] != NULL; i++) {
........
}
A sizeof before each call is wasteful and is needed to know what you get.
Works great if you put a NULL at the end of the arrays.
Why?? With embedded designs passing a sizeof in each routine makes each call very large compared to a NULL with each array. I have a 2K PIC16F684 chip and it takes upto 10 percent of the chip with 12 calls using a passed sizeof along with the array. With just the array and Chucks code with NULLS om each array... I get 4 percent needed.
A true case in point.. thanks chuck good call.
I originally had this as an answer to this other question: When a function has a specific-size array parameter, why is it replaced with a pointer?, but just moved it here instead since it more-directly answers this question.
Building off of #Richard Corden's answer and #sbi's answer, here's a larger example demonstrating the principles of:
Enforcing a given function parameter input array size using a reference to an array of a given size, like this:
void foo2(uint8_t (&array)[100])
{
printf("sizeof(array) = %lu\n", sizeof(array));
}
and:
Allowing a function parameter input array of any size, by using a function template with a reference to an input array of a given template parameter size N, like this:
template<size_t N>
void foo3(uint8_t (&array)[N])
{
printf("sizeof(array) = %lu\n", sizeof(array));
}
Looking at the full example below:
Notice how this function prototype doesn't know the array size at all! (the 100 here is simply a visual hint/reminder to the human user, but has no bearing or influence on the compiler whatsoever!):
void foo(uint8_t array[100]) {}
...this function prototype allows only input arrays of a fixed size of 100:
void foo2(uint8_t (&array)[100]) {}
...and this function template prototype allows arrays of ANY input size AND knows their size statically at compile-time (as that is how templates work):
template<size_t N>
void foo3(uint8_t (&array)[N]) {}
Here's the full example:
You can run it yourself here: https://onlinegdb.com/rkyL_tcBv.
#include <cstdint>
#include <cstdio>
void foo(uint8_t array[100])
{
// is ALWAYS sizeof(uint8_t*), which is 8!
printf("sizeof(array) = %lu\n", sizeof(array));
}
void foo2(uint8_t (&array)[100])
{
printf("sizeof(array) = %lu\n", sizeof(array));
}
template<size_t N>
void foo3(uint8_t (&array)[N])
{
printf("sizeof(array) = %lu\n", sizeof(array));
}
int main()
{
printf("Hello World\n");
printf("\n");
uint8_t a1[10];
uint8_t a2[11];
uint8_t a3[12];
// Is `sizeof(array) = 8` for all of these!
foo(a1);
foo(a2);
foo(a3);
printf("\n");
// Fails to compile for these 3! Sample error:
// > main.cpp:49:12: error: invalid initialization of reference of type ‘uint8_t (&)[100]
// > {aka unsigned char (&)[100]}’ from expression of type ‘uint8_t [10] {aka unsigned char [10]}’
// > foo2(a1);
// > ^
// foo2(a1);
// foo2(a2);
// foo2(a3);
// ------------------
// Works just fine for this one since the array `a4` has the right length!
// Is `sizeof(array) = 100`
uint8_t a4[100];
foo2(a4);
printf("\n");
foo3(a1);
foo3(a2);
foo3(a3);
foo3(a4);
printf("\n");
return 0;
}
Sample output:
(compiler warnings, referring to the sizeof call inside foo()):
main.cpp:26:49: warning: ‘sizeof’ on array function parameter ‘array’ will return size of ‘uint8_t* {aka unsigned char*}’ [-Wsizeof-array-argument]
main.cpp:23:27: note: declared here
(stdout "standard output"):
Hello World
sizeof(array) = 8
sizeof(array) = 8
sizeof(array) = 8
sizeof(array) = 100
sizeof(array) = 10
sizeof(array) = 11
sizeof(array) = 12
sizeof(array) = 100
Shouldn't this work? for things like Arduino(AVR) c++ at least.
//rename func foo to foo_ then
#define foo(A) foo_(A, sizeof(A))
void foo_(char a[],int array_size){
...
}
This question already has answers here:
C sizeof a passed array [duplicate]
(7 answers)
Closed 4 years ago.
In the program below the length of the array ar is correct in main but in temp it shows the length of the pointer to ar which on my computer is 2 (in units of sizeof(int)).
#include <stdio.h>
void temp(int ar[]) // this could also be declared as `int *ar`
{
printf("%d\n", (int) sizeof(ar)/sizeof(int));
}
int main(void)
{
int ar[]={1,2,3};
printf("%d\n", (int) sizeof(ar)/sizeof(int));
temp(ar);
return 0;
}
I wanted to know how I should define the function so the length of the array is read correctly in the function.
There is no 'built-in' way to determine the length inside the function. However you pass arr, sizeof(arr) will always return the pointer size. So the best way is to pass the number of elements as a seperate argument. Alternatively you could have a special value like 0 or -1 that indicates the end (like it is \0 in strings, which are just char []).
But then of course the 'logical' array size was sizeof(arr)/sizeof(int) - 1
Don't use a function, use a macro for this:
//Adapted from K&R, p.135 of edition 2.
#define arrayLength(array) (sizeof((array))/sizeof((array)[0]))
int main(void)
{
int ar[]={1,2,3};
printf("%d\n", arrayLength(ar));
return 0;
}
You still cannot use this macro inside a function like your temp where the array is passed as a parameter for the reasons others have mentioned.
Alternative if you want to pass one data type around is to define a type that has both an array and capacity:
typedef struct
{
int *values;
int capacity;
} intArray;
void temp(intArray array)
{
printf("%d\n", array.capacity);
}
int main(void)
{
int ar[]= {1, 2, 3};
intArray arr;
arr.values = ar;
arr.capacity = arrayLength(ar);
temp(arr);
return 0;
}
This takes longer to set up, but is useful if you find your self passing it around many many functions.
As others have said the obvious solution is to pass the length of array as parameter, also you can store this value at the begin of array
#include <stdio.h>
void temp(int *ar)
{
printf("%d\n", ar[-1]);
}
int main(void)
{
int ar[]= {0, 1, 2, 3};
ar[0] = sizeof(ar) / sizeof(ar[0]) - 1;
printf("%d\n", ar[0]);
temp(ar + 1);
return 0;
}
When you write size(ar) then you're passing a pointer and not an array.
The size of a pointer and an int is 4 or 8 - depending on ABI (Or, as #H2CO3 mentioned - something completely different), so you're getting sizeof(int *)/sizeof int (4/4=1 for 32-bit machines and 8/4=2 for 64-bit machines), which is 1 or 2 (Or.. something different).
Remember, in C when pass an array as an argument to a function, you're passing a pointer to an array.If you want to pass the size of the array, you should pass it as a separated argument.
I don't think you could do this using a function. It will always return length of the pointer rather than the length of the whole array.
You need to wrap the array up into a struct:
#include<stdio.h>
struct foo {int arr[5];};
struct bar {double arr[10];};
void temp(struct foo f, struct bar g)
{
printf("%d\n",(sizeof f.arr)/(sizeof f.arr[0]));
printf("%d\n",(sizeof g.arr)/(sizeof g.arr[0]));
}
void main(void)
{
struct foo tmp1 = {{1,2,3,4,5}};
struct bar tmp2;
temp(tmp1,tmp2);
return;
}
Inside the function ar is a pointer so the sizeof operator will return the length of a pointer. The only way to compute it is to make ar global and or change its name. The easiest way to determine the length is size(array_name)/(size_of(int). The other thing you can do is pass this computation into the function.
I am trying to pass a multidimensional array to a function. When I try to compile I an getting an error saying
[Error] cannot convert 'int (*)[3]' to 'int (*)[2]' for argument '1' to 'void reve(int (*)[2], int)'
What is the problem ? What am I doing wrong? Following is the code I wrote.
#include <iostream>
using namespace std;
const int rows=2;
const int cols=2;
const int n = 3;
void reve(int arr[rows][cols],int n){
int br[3][3],i,j,k,l;
for(i=n-1,k=0;i>=0,k<n;i--,k++){
cout<<endl;
for(j=n-1,l=0;j>=0,l<n;j--,l++)
br[k][l]=arr[i][j];
}
for(i=0;i<n;i++){
for(j=0;j<n;j++)
arr[i][j]=br[i][j];
}
}
int main() {
int i,j,k,l,ar[3][3],br[3][3];
for(i=0;i<3;i++)
for(j=0;j<3;j++)
cin>>ar[i][j];
int n=3;
reve(ar,n);
for(i=0;i<3;i++){
cout<<endl;
for(j=0;j<3;j++)
cout<<ar[i][j];
}
return 0;
}
When you use a 2-d array in a function call, it decays into a pointer type. However, all dimensions but the first one must match exactly.
If the argument type of a function is int (*arg)[2], then, you can't use a variable that is declared as int var[3][3] to call the function. var decays to a pointer whose type is int (*)[3].
It is confusing at first because it seems to work in case of 1-d arrays.
void foo(int arg[10])
{
}
int var[2];
foo(var); // OK
That's because the compiler ignores the size of the first dimension of the array. The above definition of foo is same as:
void foo(int arg[])
{
}
and
void foo(int* arg)
{
}
However, for a multidimensional array, the size of all but the fist dimension must match exactly. Otherwise, they are different types.
The reve() function expects an array of [2][2] but you're passing a [3][3] array.
The ar array in main() is declared as int ar[3][3] while it should have been int ar[rows][cols]
You have reserved 2 blocks in memory. And in your loop, you are taking it from 2 to 0 that makes it 3. Do the following changes.
const int n= 2;
And it should work for your program.
here is some code
class DengkleTryingToSleep{
public:
int minDucks(int ducks[]);
int temp(int ducks[]){
int size=sizeof(ducks);
cout<<"sizeof="<<size<<"\n";
}
};
int main (int argc, const char * argv[])
{
DengkleTryingToSleep dt;
int arr[]={9,3,6,4};
cout<<"sizeof "<<sizeof(arr);
cout<<"\nsizeof from function "<<dt.temp(arr);
return 0;
}
and output of this is
sizeof 16
sizeof from function sizeof=8
and i have no idea how this is working because it returns 16 (as expected when called inside main)
and returns 8 when called from the function
Because arrays decay to pointers when passed to a function. You're getting the size of a pointer in your temp function.
If you need to know the length of an array in a function ... you have to pass that in as well.
Actually this function:
int temp(int ducks[])
is exactly equivalent this function:
int temp(int *ducks)
There is NO DIFFERENCE at all. No difference. So no matter what you pass, whether an array or a pointer, it will become a pointer inside the function.
That means, when you write sizeof(ducks) in your function, it is exactly equivalent to sizeof(int*), which returns 8 on your machine (I guess, your machine has 64-bit OS where the size of pointer is 8 bytes).
If you want to pass an array, and don't it decay into pointer type, then do this:
template<size_t N>
int temp(int (&ducks)[N])
{
int size=sizeof(ducks);
cout<<"sizeof="<<size<<"\n";
}
Now it will print 16. Note that inside the function N represents the count of items in the array. So in your case, it would be 4, as there are 4 elements in the array. It means, if you need the length of the array, you don't need to calculate it as sizeof(bucks)/sizeof(int), as you already know the length of the array which is N.
Also note that there is a limitation in this approach: now you cannot pass dynamically allocated array:
int *a = new int[10];
dt.temp(a); //compilation error
//but you can pass any statically declared array
int b[100], c[200];
dt.temp(b); //ok - N becomes 100
dt.temp(c); //ok - N becomes 200
But in C++, you've a better option here: use std::vector<int>.
int temp(std::vector<int> & ducks)
{
std::cout << ducks.size() << std::endl;
}
//call it as
std::vector<int> v = {1,2,3,4,5,6}; //C++11 only, or else : use .push_back()
dt.temp(v);
Is it possible to determine the size of an array if it was passed to another function (size isn't passed)? The array is initialized like int array[] = { XXX } ..
I understand that it's not possible to do sizeof since it will return the size of the pointer .. Reason I ask is because I need to run a for loop inside the other function where the array is passed. I tried something like:
for( int i = 0; array[i] != NULL; i++) {
........
}
But I noticed that at the near end of the array, array[i] sometimes contain garbage values like 758433 which is not a value specified in the initialization of the array..
The other answers overlook one feature of c++. You can pass arrays by reference, and use templates:
template <typename T, int N>
void func(T (&a) [N]) {
for (int i = 0; i < N; ++i) a[i] = T(); // reset all elements
}
then you can do this:
int x[10];
func(x);
but note, this only works for arrays, not pointers.
However, as other answers have noted, using std::vector is a better choice.
If it's within your control, use a STL container such as a vector or deque instead of an array.
Nope, it's not possible.
One workaround: place a special value at the last value of the array so you can recognize it.
One obvious solution is to use STL. If it's not a possibility, it's better to pass array length explicitly.
I'm skeptical about use the sentinel value trick, for this particular case. It works
better with arrays of pointers, because NULL is a good value for a sentinel. With
array of integers, it's not that easy - you need to have
a "magic" sentinel value, which is
not good.
Side note: If your array is defined and initalized as
int array[] = { X, Y, Z };
in the same scope as your loop, then
sizeof(array) will return it's real size in bytes, not the size of the pointer. You can get the array length as
sizeof(array) / sizeof(array[0])
However, in general case, if you get array as a pointer, you can't use this trick.
You could add a terminator to your int array then step through the array manually to discover the size within the method.
#include<iostream>
using namespace std;
int howBigIsBareArray(int arr[]){
int counter = 0;
while (arr[counter] != NULL){
counter++;
}
return counter;
}
int main(){
int a1[6] = {1,2,3,4,5,'\0'};
cout << "SizeOfMyArray: " << howBigIsBareArray(a1);
}
This program prints:
SizeOfMyArray: 5
This is an O(n) time complexity operation which is bad. You should never be stepping through an array just to discover its size.
If you can't pass the size, you do need a distinguishable sentinel value at the end (and you need to put it there yourself -- as you've found, you can't trust C++ to do it automagically for you!). There's no way to just have the called function magically divine the size, if that's not passed in and there is no explicit, reliable sentinel in use.
Can you try appending a null character \0 to the array and then send it? That way, you can just check for \0 in the loop.
Actually Chucks listing of
for( int i = 0; array[i] != NULL; i++) {
........
}
A sizeof before each call is wasteful and is needed to know what you get.
Works great if you put a NULL at the end of the arrays.
Why?? With embedded designs passing a sizeof in each routine makes each call very large compared to a NULL with each array. I have a 2K PIC16F684 chip and it takes upto 10 percent of the chip with 12 calls using a passed sizeof along with the array. With just the array and Chucks code with NULLS om each array... I get 4 percent needed.
A true case in point.. thanks chuck good call.
I originally had this as an answer to this other question: When a function has a specific-size array parameter, why is it replaced with a pointer?, but just moved it here instead since it more-directly answers this question.
Building off of #Richard Corden's answer and #sbi's answer, here's a larger example demonstrating the principles of:
Enforcing a given function parameter input array size using a reference to an array of a given size, like this:
void foo2(uint8_t (&array)[100])
{
printf("sizeof(array) = %lu\n", sizeof(array));
}
and:
Allowing a function parameter input array of any size, by using a function template with a reference to an input array of a given template parameter size N, like this:
template<size_t N>
void foo3(uint8_t (&array)[N])
{
printf("sizeof(array) = %lu\n", sizeof(array));
}
Looking at the full example below:
Notice how this function prototype doesn't know the array size at all! (the 100 here is simply a visual hint/reminder to the human user, but has no bearing or influence on the compiler whatsoever!):
void foo(uint8_t array[100]) {}
...this function prototype allows only input arrays of a fixed size of 100:
void foo2(uint8_t (&array)[100]) {}
...and this function template prototype allows arrays of ANY input size AND knows their size statically at compile-time (as that is how templates work):
template<size_t N>
void foo3(uint8_t (&array)[N]) {}
Here's the full example:
You can run it yourself here: https://onlinegdb.com/rkyL_tcBv.
#include <cstdint>
#include <cstdio>
void foo(uint8_t array[100])
{
// is ALWAYS sizeof(uint8_t*), which is 8!
printf("sizeof(array) = %lu\n", sizeof(array));
}
void foo2(uint8_t (&array)[100])
{
printf("sizeof(array) = %lu\n", sizeof(array));
}
template<size_t N>
void foo3(uint8_t (&array)[N])
{
printf("sizeof(array) = %lu\n", sizeof(array));
}
int main()
{
printf("Hello World\n");
printf("\n");
uint8_t a1[10];
uint8_t a2[11];
uint8_t a3[12];
// Is `sizeof(array) = 8` for all of these!
foo(a1);
foo(a2);
foo(a3);
printf("\n");
// Fails to compile for these 3! Sample error:
// > main.cpp:49:12: error: invalid initialization of reference of type ‘uint8_t (&)[100]
// > {aka unsigned char (&)[100]}’ from expression of type ‘uint8_t [10] {aka unsigned char [10]}’
// > foo2(a1);
// > ^
// foo2(a1);
// foo2(a2);
// foo2(a3);
// ------------------
// Works just fine for this one since the array `a4` has the right length!
// Is `sizeof(array) = 100`
uint8_t a4[100];
foo2(a4);
printf("\n");
foo3(a1);
foo3(a2);
foo3(a3);
foo3(a4);
printf("\n");
return 0;
}
Sample output:
(compiler warnings, referring to the sizeof call inside foo()):
main.cpp:26:49: warning: ‘sizeof’ on array function parameter ‘array’ will return size of ‘uint8_t* {aka unsigned char*}’ [-Wsizeof-array-argument]
main.cpp:23:27: note: declared here
(stdout "standard output"):
Hello World
sizeof(array) = 8
sizeof(array) = 8
sizeof(array) = 8
sizeof(array) = 100
sizeof(array) = 10
sizeof(array) = 11
sizeof(array) = 12
sizeof(array) = 100
Shouldn't this work? for things like Arduino(AVR) c++ at least.
//rename func foo to foo_ then
#define foo(A) foo_(A, sizeof(A))
void foo_(char a[],int array_size){
...
}