Why is this sizeof operator giving error? - c++

In this program, the line int len = sizeof(*a)/sizeof(int); gives the error, however if I write this int len = sizeof(**a)/sizeof(int); or this int len = sizeof(a)/sizeof(int);, it works fine. Why is that? Here a holds the address of 1-D array and when I do this, *a, it gives the address of first element of the array and finally **a gives the element itself. So based on this the line int len = sizeof(*a)/sizeof(int); should work fine, isn't it?
#include <stdio.h>
void func(int (*a)[]){
printf("%d %d\n", sizeof(a), sizeof(int));
int len = sizeof(*a)/sizeof(int); // error
for(int i = 0; i < len; ++i){
printf("%d ", (*a)[i]);
}
}
int main(){
int a[][3] = {
{1, 2, 3},
{4, 5, 6}
};
func(a);
return 0;
}

Parameter a is a pointer to an incomplete type. You cannot use sizeof on it since it is a pointer to an array and the size of the array isn't defined.
You can define it:
void func(int (*a)[10]){
In this case sizeof(*a) will equal to sizeof( int )*10 and sizeof(*a)/sizeof(int); will give the element count of a, which is 10 in this case.
Since you are passing a pointer to an array of size 3 you should use 3 not 10.
You can use forward parameters to have a variable sized argument a.

Standard says:
C11: 6.5.3.4
The sizeof operator shall not be applied to an expression that has function type or an incomplete type [..]
An array type of unknown size is an incomplete type (C11: 6.2.5 Types--p22). *a in func is of incomplete type. You need to specify the length of the array a points to before using it as an operand of sizeof.

Related

Cannot convert int(*)[5] to int*

When i tried to access array elements using pointer I got this error i don't understand how can i access with the help of pointer.
Error: cannot convert ‘int (*)[5]’ to ‘int*’ for argument ‘1’ to ‘void addd(int*, int)
Any guidance on the matter would be greatly appreciated!
#include <iostream>
using namespace std;
void addd(int *ptr,int length)
{
cout<<"The values in the array are: ";
for(int i = 0; i < length; i++) {
cout<< *ptr <<" ";
ptr++;
}
}
int main() {
int arr[5] = {1, 2, 3, 4, 5};
addd(&arr,5);
//int *ptr = &arr[0];
return 0;
}
Your function receives a pointer to int, so you should just pass the address of the first element.
You can do that:
addd(&arr[0],5);
or simply:
addd(arr,5);
You're doing it wrong. &arr means int (*)[5], but you are using int *ptr. So, you've to use like below:
addd(arr, 5); // this is correct
// addd(&arr, 5) // this is wrong
Here, arr is passed as int *
When you pass an array to a function, for example:
addd(arr,5);
then the array is implicitly converted to a pointer to its first element, an int*. Instead of relying on the implicit conversion, you can make it explicit:
addd( &arr[0],5);
// ^- first element
// ^------ address-of first element
However, arrays are not pointers and taking the address of the array yields a pointer to an array:
using pointer_to_array = int (*)[5];
pointer_to_array p = &arr;
arrays and pointers are pretty much inter-related to each other. An array by default points to the address of the first element, that is the element at index 0. So, working with arrays and pointers are pretty much the same thing( not every time ). So, you do not need to pass on the array as
addd(&arr,5);
you should simply do just
addd(arr,5);
Also , i will say,
The statement
addd(&arr[0],5); does the job, but not a good way to proceed.

Why does sizeof(A), for some array A, not work inside a function? [duplicate]

This question already has answers here:
How do I use arrays in C++?
(5 answers)
Closed 8 years ago.
The following
#include <iostream>
void printArraySize ( int * arr )
{
std::cout << sizeof(arr)/sizeof(int);
}
int main ()
{
int arr [] = {1, 2, 3, 69203};
printArraySize(arr);
return 0;
}
outputs 1 (Proof: http://codepad.org/yKG3mZIz). Explain this nonsense. Does an array forget its size once it enters a function? From what I understand, passing in arr, a memory address, a number, just means making a copy of that number. So sizeof(arr)/sizeof(int) should mean the same thing inside and outside of the function.
In main, arr is an array and sizeof yields the size of the array.
In printArraySize, arr is a pointer to int and sizeof yields the size of the pointer to int object.
In C you cannot pass (directly) arrays to functions, you can only pass a pointer to the first element of the array. To get the size of the array in printArraySize you need to pass it explicitly as an argument to the function.
In C++ you can pass C arrays by reference but you shouldn't use C arrays in the first place but use std::array or std::vector instead.
It is because you check sizeof ( int*) which is sizeof pointer to int. This is because arr passed to function in
int arr [] = {1, 2, 3, 69203};
printArraySize(arr);
decays to a pointer to int. It is just a pointer to integer, first element of array.
C
For doing what you would like to achieve there is a macro often used (for static arrays):
#define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
example:
int arr [] = {1, 2, 3, 69203};
printf( "%d", ARRAY_SIZE(arr));
C++
template<class T, size_t n>
size_t array_size( T(&)[n]) {
return n;
}

Finding the size of int [] array

In the following function, how can we find the length of the array
int fnLenghthOfArray(int arry[]){
return sizeof(arry)/sizeof(int); // This always returns 1
}
Here this function always returns 1.
Where as, sizeof(arry)/sizeof(int) gives the actual length of the array, in the function where it is declared.
If we use vector or template like
template<typename T,int N>
int fnLenghthOfArray(T (&arry)[N]){
}
we can get the size. But here I am not allowed to change the function prototype.
Please help me to find this.
Remember, in C when you pass an array as an argument to a function, you're passing a pointer to the array. If you want to pass the size of the array, you should pass it as a separated argument.
The size of a pointer and an int is 4 or 8 or something else - depending on ABI.
In your case, it's 4, so you're getting sizeof(int *)/sizeof int which is 1.
Here is a useful trick
You can store the length of the array in the first element of it:
int myArray[]= {-1, 1, 2, 3, 4, 5};
myArray[0] = sizeof(myArray) / sizeof(myArray[0]) - 1;
//The -1 because.. the first element is only to indicate the size
Now, myArray[0] will contain the size of the array.
In function decalration, array is a pointer:
int fnLenghthOfArray(int arry[])
^
is same as int* array
And in your system sizeof(int*) == sizeof(int).
You function declaration
int fnLenghthOfArray(int arry[]);
is equivalent to
int fnLenghthOfArray(int* arry);
hence your calculation yields 1 (based on the assumption that the size of a pointer to int and size of an int are the same).
Your only option to get the size of the array is to provide an additional parameter
int fnLenghthOfArray(int arry[], std::size_t size);
Alternatively you could use one of the C++ containers like vector or array
int arry[]
is equivalent to
int *arry
and the sizeof() operator returns 4 when applied to arry because it's the size of a pointer (or reference in the case of arry[]), the size of the int is also 4 bytes and that's why it always returns 1.
To solve your problem you must implement the array in a different way. Maybe the first element should always have the size of the array. Otherwise you could use the vector class from STL or list.
int fnLenghthOfArray(int arry[]){
return sizeof(arry)/sizeof(int); // This always returns 1
}
This function returns 1 because is performing a division between the size of a pointer and the size of an integer. In most architectures, the size of a pointer is equal to the size of an integer. For instance, in the x86 architecture both have size 4 bytes.
Where as, sizeof(arry)/sizeof(int) gives the actual length of the
array, in the function where it is declared
Because in this case the compiler knows that arry is an array and its size. Whereas, in the previous function, the compiler knows arry only as a pointer. In fact, when you specify the function prototype, there is not difference between int arry[] and int * arry.
You can't get size of array in C or C++.
Array in this languages is simply pointer to first element. You need to keep size of array by yourself.
Here is code snippet using Maroun's trick.
#include<stdio.h>
void print_array(int *array);
void shift_array_normal(int *array,int arrayLen);
int main(void)
{
int array[]= {-1,32,44,185,28,256,22,50};
array[0] = sizeof(array) / sizeof(array[0]) - 1;
print_array(array);
return 0;
}
void print_array(int *array){
int index,arrayLen = array[0];
//length of array is stored in arrayLen now we can convert array back.
printf("Length of array is : %d\n",arrayLen);
//convert array back to normal.
shift_array_normal(array,arrayLen);
//print int array .
for(index = 0; index < arrayLen; index++)
printf("array[%d] = %d\n",index,array[index]);
}
/*removing length element from array and converting it back to normal array*/
void shift_array_normal(int *array,int arrayLen){
int index;
for(index = 0; index < arrayLen; index++)
array[index] = array[index + 1];
}
#include<iostream>
int main()
{
int array[300];
int d = sizeof(array)/4;
std::cout<<d;
}
Use:
// sizeof(array)/4 for "int" array reserves 4 bits.
// sizeof(array)/4 for "float" array reserves 4 bits.
// sizeof(array) for "char" array reserves 2 bits.
// sizeof(array) for "bool" array reserves 2 bits.
// sizeof(array)/8 for "double" array reserves 8 bits.
// sizeof(array)/16 for "long double" array reserves 16 bits.

reference to an array in c++

Question is make an array of 10 integers that's fine
int array[10];
Now question is
how to make a reference to an array which I have declared above ?
I tried this
int &ra = a;
But it's giving me error...
Please provide me details about this error and how to make reference of an array.
int (&ra)[10] = a;
Alternatively, you can use a typedef to separate this into the type for "array of 10 ints" and having a reference there-to, as in:
typedef int int10[10];
int10& my_ref = a;
The problem with your int &ra = a; is that it tells the compiler to create a reference of type int that refers to an array of 10 ints... they're just not the same thing. Consider that sizeof(int) is a tenth of the size of an array of ten ints - they occupy different amounts of memory. What you've asked for with the reference's type could be satisfied by a particular integer, as in int& ra = a[0];.
I appreciate it's a bit confusing that int* p = a; is allowed - for compatibility with the less type-safe C, pointers can be used to access single elements or arrays, despite not preserving any information about the array size. That's one reason to prefer references - they add a little safety and functionality over pointers.
For examples of increased functionality, you can take sizeof my_ref and get the number of bytes in the int array (10 * sizeof(int)), whereas sizeof p would give you the size of the pointer (sizeof(int*)) and sizeof *p == sizeof(int). And you can have code like this that "captures" the array dimension for use within a function:
template <int N>
void f(int (&x)[N])
{
std::cout << "I know this array has " << N << " elements\n";
}
The reference to array will have type int (&a)[10].
int array[10];
int (&a)[10] = array;
Sometimes it might be useful to simplify things a little bit using typedef
typedef int (&ArrayRef)[10];
...
ArrayRef a = array;
This is a reference to an array of of ints of size 10:
int (&ra)[10];
so
int (&ra)[10] = a;
You can typedef the array type (the type should not be incomplete) as follow:
#define LEN 10
typedef int (array)[LEN];
int main(void)
{
array arr = {1, 2, 3, 4, 5}; //define int arr[10] = {1, 2, 3, 4, 5};
array arr2; //declare int arr[10];
array *arrptr = &arr; // pointer to array: int (*arrptr)[10] = &arr;
array &&arrvef; // declare rvalue reference to array of 10 ints
array &ref = arr; // define reference to arr: int (&ref)[10] = arr;
}

C/C++ Array initializer problem

Can someone explain why I can do:
int x[4] = { 0, 1, 2, 3 };
int *p = x;
But cannot do:
int x[2][2] = { 0, 1, 2, 3 };
int **p = x;
Is there a way to be able to assign to **p the x[][]?
TIA
A pointer to int int * can point at an integer within an array of integers, so that's why the first is OK;
int x[4] = { 0, 1, 2, 3 };
int *p = x;
This makes p point to x[0], the first int in x.
A pointer to a pointer-to-int int ** can point at a pointer-to-int within an array of pointers-to-int. However, your second array is not an array of pointers-to-int; it is an array of arrays. There are no pointers-to-int, so there is nothing sensible to point int **p at. You can solve this in two ways. The first is to change the type of p so that it is a pointer-to-array-of-2-ints:
int x[2][2] = { 0, 1, 2, 3 };
int (*p)[2] = x;
Now p points at x[0], the first int [2] in x.
The alternative is to create some pointers-to-int to point at:
int x[2][2] = { 0, 1, 2, 3 };
int *y[2] = { x[0], x[1] };
int **p = y;
Now p points at y[0], which is the first int * in y. y[0] in turn points at x[0][0], and y[1] points at x[1][0].
Using the pointer notation you can do this
*(p + n) will return back a value in the subscript n which is equivalent of
p[n], a "single dimension array"
*( * (p + i) + j) will return back a value in the subscripts i and j which
is equivalent of p[i][j], a "double dimension array"
This will prove that using array subscripts [] decays into pointers as per the rule - see ANSI C Standard, 6.2.2.1 - "An array name in an expression is treated by the compiler as a pointer to the first element of the array", furthermore, ANSI C Standard 6.3.2.1 - "A subscript is always equivalent to an offset from a pointer", and also ANSI C Standard 6.7.1 - "An array name in the declaration of a function parameter is treated as a pointer to the first element in the array"
If you are not sure in understanding how pointers and arrays work, please see my other answer which will explain how it works...
Please ignore anyone who says arrays and pointers are the same - they are not...
No, there's no way to assign the array to an "int **", because a two-dimensional array is an array of arrays, not an array of pointers.
You could for instance do:
int x1[2] = {0, 1};
int x2[2] = {2, 3};
int *x[2] = {x1, x2};
int **p = x;
... and maybe that would be an acceptable equivalent to what you are trying to do (depending on what exactly that is of course!).
Update: If you must keep x as a two-dimensional array, you could also do: int (*p)[2] = x; which gives you a pointer-to-array-of-int.
There is no way to meaningfully initialize you variable p with x. Why? Well, there's no way to answer your question until you explain how you even came to this idea. The type of p is int **. The type of x is int[2][2]. These are two different types. Where did you get the idea that you should be able to assign one to the other?
If you really need to access elements of your x through a pointer of type int **, you have to do it indirectly. You have to create an additional intermediate array that will hold pointers to first elements of consecutive rows of array x:
int *rows[2] = { x[0], x[1] };
and now you can point your p to the beginning of this intermediate array
int **p = rows;
Now when you assess p[i][j] you get x[i][j].
There's no way to do it directly, without an intermediate array.
If you are really using c++ instead of c, you can get this effect by using std::vector (or some other collection type).
typedef std::vector<std::vector<int> > intmatrix;
intmatrix x;
intmatrix::iterator p = x.begin();
or some such.
It's all about Standard Conversion rule ($4.2)
An lvalue or rvalue of type “array ofN
T” or “array of unknown bound of T”
can be converted to an rvalue of type
“pointer to T.” The result is a
pointer to the first element of the
array.
The type of od and td respectively are
char [3]
char [1][3]
This means that od has type 'array of 3 chars' (N = 3, T = char).
So in accordance with the above quote, it can be converted to 'pointer to char'
Therefore char *p = od; is perfectly well-formed
Similarly the type of od is 'array of 1 array of 3 chars' (N = 1, T = array of 3 chars).
So in accordance with the above quote, it can be converted to 'pointer to array of 3 chars'
Therefore char (*p)[3] = td; is perfectly well-formed
Is there a way to be able to assign to
**p the x[][]?
No. Because type of td[x][y] for valid x and y is char. So what you can really do is char *pc = &td[0][0].