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;
}
Related
I am wondering how come the # number1 code not working
as I am trying to use increment operator to display the next following element in the array.
But the # number2 code works , and it was the same code but in a function
//# number 1 code
using namespace std;
int main(){
int arrays[5]={2,4,6,8,10};
for(int x=0;x<5;x++){
cout<<*arrays<<endl;
arrays++; //error: lvalue required as increment operand
}
}
//# number 2 code
using namespace std;
void display(int *arr,int size){
for(int x=0; x<5;x++){
cout<<*arr<<endl;
arr++; //This time no error!!!
}
}
int main(){
int arrays[5]={2,4,6,8,10};
display(arrays,5);
return 0;
}
That's because you cannot change the address of an array.
In # number 1 code when you do array++, you are actually trying to operate directly on the variable which is storing the base address of the array.
What you can try instead is something like below:
int *p = array;
p++;
Whereas in the case when you are calling a function passing the array's base address # number 2, you are implicitly doing what has been shown in the above code snippet.
This is a common problem for beginners. Arrays are not pointers!. Arrays are implicitly converted to pointers. That is where the confusion lies. Consider this:
int array[] = {1, 2, 3};
std::cout << *array << '\n';
What do you think is happening when we do *array. Does it really make sense to dereference an array? The array is being implicitly converted to a int * and then dereferenced. What about this:
int array[] = {1, 2, 3};
array++;
std::cout << *array << '\n';
This doesn't compile (as you found out for yourself). In this statement array++, the array is not implicitly converted to a pointer.
Arrays are converted to pointers when you pass them to functions that accept pointers. That makes it possible to do this:
int array[3] = {1, 2, 3};
display(array, 3);
An array is a sequence of objects stored on the stack. You access this sequence of objects as a pointer to the first object. Both arrays and pointers can be subscripted. They share many similarities but are fundamentally different.
To make your first example compile, subscript the array with x:
for (int x = 0; x < 5; x++) {
std::cout << arrays[x] << '\n';
}
Use :
int *arr = arrays;
arr++;
in code #1. It will work. This is because you need first to create a pointer to the base of the array which you can increment as in the second code, you have the pointer in the form of the passed argument to the function.
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.
I was brushing up on my C++ (using eclipse and cygwin) by writing functions over arrays.
I have the following code:
int getArraySize(int a[]){
int size = sizeof(a)/sizeof(a[0]);
return size;
}
int main(void) {
int arr[5] = {0, 1, 2, 3, 4};
string s = "size of array: ";
cout << s << getArraySize(arr) << endl;
cout << s << sizeof(arr)/sizeof(arr[0]) << endl;
return EXIT_SUCCESS;
}
I expect to get this output:
size of array: 5
size of array: 5
but instead I get this:
size of array: 2
size of array: 5
I've tried this program with other sizes of arrays, and the function getArraySize()
always returns 2. Anyone know what's up?
This looks like an array declaration, but it is not:
int getArraySize(int a[]){
This is just a pointer-to-int. Therefore sizeof(a) / sizeof(a[0]) will just give you the ratio between the size of a pointer and the size of the pointed-to thing. The situation does not change if you put a number between the brackets, like this:
int getArraySize(int a[5]){
To the C++ compiler, that is the same as int getArraySize(int *a). C++ does not pass arrays by value. It passes a pointer to the first element of the array. When you give an array argument, the argument decays to a pointer.
The sizeof() operator will give you the total number of bytes in an array when you pass it an actual array variable, as in this:
int arr[5] = {0, 1, 2, 3, 4};
int arr_size = sizeof(arr) / sizeof(arr[0]);
Unfortunately the C++ syntax here is a bit misleading.
You cannot pass an array to a C++ function, you can only pass a pointer to the first element.
In C++ the declaration
void foo(int x[])
is EXACTLY the same as
void foo(int *x)
Even if you put a size between brackets as in
void foo(int x[10])
the number 10 is not a syntax error but will be completely ignored.
You however infer an array size from a template function, using a somewhat weird syntax:
template<typename T, size_t N>
size_t ArraySize(T (&)[N])
{
return N;
}
The sizeof(x)/sizeof(x[0]) trick works only if used in a macro... it cannot be placed in a function.
You are taking the size of int a[] which is really a pointer
it looks like you are on a 64 bit machine so:
sizeof(64 bit pointer) = 8
sizeof (int) = 4
8/4 = 2
On a 32 bit machine you would get a 1
The problem is that you are not getting the size of arr and there really isn't a way to do that until c++11 where you can use a std::array instead
I think your problem is that c++ passes arrays by reference hence you are simply dividing the size of addresses.
I want to do something like this below:
int main() {
int a[10];
int *d = generateArrayOfSize(10) // This generates an array of size 10 on the heap
a = d;
print(a); // Prints the first 10 elements of array.
}
However above code gives compilation error (incompatible types in assignment of ‘int*’ to ‘int [10]’).
What can I do to make the above code to work?
Arrays are non-assignable and non-copyable, so you'd have to copy each element by hand (in a loop), or using std::copy.
If you're using C++, then use C++ arrays rather than C style arrays and pointers. Here's an example
#include <array>
#include <iostream>
template<size_t N>
std::array<int, N> generateArrayOfSize(void)
{
std::array<int, N> a;
for (int n=0; n<N; ++n)
a[n] = n;
return a;
}
template<size_t N>
void print(std::array<int, N> const &a)
{
for (auto num : a)
std::cout << num << " ";
}
int main() {
std::array<int, 10> a;
std::array<int, 10> d = generateArrayOfSize<10>();
a = d;
print(a); // Prints the first 10 elements of array.
}
which outputs 0 1 2 3 4 5 6 7 8 9
Arrays are not pointers.
You can't do :
int a[10];
int *d;
a = d;
Change it to :
int *a;
int *d;
a = d;
Main differences between arrays and pointers in C programming :
Pointer | Array
-------------------------------------------|-------------------------------------------
A pointer is a place in memory that keeps | An array is a single, pre allocated chunk
address of another place inside | of contiguous elements (all of the same
| type), fixed in size and location.
-------------------------------------------|-------------------------------------------
A pointer can point to a dynamically | They are static in nature. Once memory is
allocated memory. In this case, the memory | allocated , it cannot be resized or freed
allocation can be resized or freed later. | dynamically.
-------------------------------------------|-------------------------------------------
You have a quite good explanation here : https://stackoverflow.com/a/7725410/1394283
An array is not a pointer (although a name of an array often decays to a pointer to its first element).
To make the above code to work, you can declare a as a pointer: int *a;. The print function takes an int* (or a decayed array) anyway.
If you really want to have two arrays and copy contents from one array to another, you should copy the data in a loop.
This will print in this way when you assign a string reference to a pointer you have to use *ptr to print the value of a pointer otherwise in your case print(d) that is like cout< in c++ it will only print the location of the d[0].
int ary[5]={1,2,3,4,5};
int *d;
d=ary;
for(int i=0;i<5;i++)
cout<<*(d+i);
Because array names are non-modifiable. So you can't do
a = d;
Declare it as a pointer like this:
int *a;
Little rusty with my C++ but try something like this.
int main() {
int *a;
int *d = generateArrayOfSize(10) // This generates an array of size 10 on the heap
a = d;
print(a); // Prints the first 10 elements of array.
}
In C, it was always true when Thing X[10]; was declared, X was the constant address of the first element(i.e. &X[0]). So you could then say:
Thing *Y = X; // Equivalent to (Thing *Y = &X[0];)
But in C++, the compiler "remembers" that the Thing array X has 10 elements, and some C++ imposed type checking rules break. Imagine we add Thing Z[20]; to the discussion.
Thing *Y = X; and Thing *Y = Z; if both allowed, would imply that a single variable could be set to Thing Arrays of length 10 and 20, which are very different (ahem) "things", as a quick look at a 2D array will reveal. This sort of justifies why the C language assumed equivalent of X and &X[0] is broken in C++.
Well, at least for some versions of C++. So best not to assume it, and use
Thing *Y = &x[0]; and Thing *Y = &Z[0] instead;
This approach has two advantages. It does what is wanted, and it actually compiles. :-)
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);