Point to specific rows of 2-D arrays - c++

I wrote the following code to point to first row of a 2-dimensional array. However, when I do
arrayPtr = & array[0];
I end up getting
error: cannot convert double (*)[1] to double* in assignment
arrayPtr = & array[0];
My program is:
#include <iostream>
int main(int argc, char **argv)
{
double array[2][1];
array[0][1] = 1.0;
array[1][1] = 2.0;
double* arrayPtr;
arrayPtr = &array[0];
return 0;
}
Can someone help me understand as to where am I going wrong?

Instead of arrayPtr = & array[0], you can write
arrayPtr = array[0];
to make use of array decay property.
Related,
Quoting C11, chapter §6.3.2.1, Lvalues, arrays, and function designators
Except when it is the operand of the sizeof operator, the _Alignof 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. [...]
Quoting C++14, chapter §5.3.3
The lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conversions are not
applied to the operand of sizeof.
and, for chapter 4.2,
An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue
of type “pointer to T”. The result is a pointer to the first element of the array.
So, while used as the RHS operand of the assignment operator, array[0] decays to the pointer to the first element of the array, i.e, produces a type double* which is the same as the LHS.
Otherwise, the use of & operator prevents the array decay for array[0] which is an array of type double [1].
Thus, &array[0] returns a type which is a pointer to an array of double [1], or, double (*) [1] which is not compatible with the type of the variable supplied in LHS of the assignment, a double *.

In your code:
array is of type double (*)[1];
array[0] is of type double[1]
&array[0] (this equals to array) is of type double (*)[1] (i.e. pointer to double[1])
Note 1: T[] can decay to T*. So in your example double[] can decay to double *.
Note 2: a[b] == *(a + b), so in your example &array[0] equals to & (*(array + 0)) which is simplified to array itself.

double array[2][1];
double* arrayPtr;
arrayPtr = & array[0];
arrayPtr has the type
POINTER (DOUBLE)
while array has the type
POINTER(POINTER(DOUBLE))
&array[0] has the type
POINTER(POINTER(DOUBLE))
You try to assign
POINTER (DOUBLE) <= POINTER(POINTER(DOUBLE))
The correct way to do it is
arrayPtr = array[0];
or
arrayPtr = *array;

Related

Assigning char array to pointer

I am trying to understand pointers in C++, but I am currently confused with the following:
char input_line[] = "hi?";
char* p;
p = &input_line;
while (*p)
{
cout << *p << endl;
*p++;
}
I must be confused here because I would think this says assign the address of a 1d array to the pointer; however, when I try to compile this, I get an error: error: cannot convert char (*)[4]' to 'char*' in assignment p = &input_line;
It looks like I should be doing this:
const char input[] = "test?";
int quest_count = 0;
const char *i = input;
while(*i){
cout << *i << endl;
*i++;
}
This doesn't make sense to me because you are assigning a char array to a char pointer which stores an address.
The error in this line of code:
p = &input_line;
Can be resolved by changing it with:
p = input_line;
That's because your're assigning the memory direction of the array.
Its value is a pointer to a char pointer. That's why the error is
raised. Remember, the operator & gives to you the variables memory
direction.
A pointer stores a memory direction of an object. An array is a sequence of objects by a certain type that are located in consecutives reserved amount of space in memory.
Each index of an array is a number composed of the digits from 0 to 9. Each element of an array is an object that you can take the address of, like a pointer to an object memory location. In an array the objects are located in consecutive memory locations. When you assign an array to a pointer, you're assigning the pointer to the arrays first element, it's array[0].
When you increase by 1 the pointer value, the pointer will point to the next object in a memory location. So, arrays and pointers have similar behavior. If you assign to a pointer an array and then you increase by 1 the pointer value, it will point now to the object in the array.
This is not only for char type, it's for every type in C++. In this page you can get more information about pointers and array. You must note that the pointer and the array must contain or point to the same variable type.
Here's an example from this page:
int* ptr;
int a[5];
ptr = &a[2]; // &a[2] is the address of third element of a[5].
An output example from the example in this page is:
Displaying address using arrays:
&arr[0] = 0x7fff5fbff880
&arr[1] = 0x7fff5fbff884
&arr[2] = 0x7fff5fbff888
&arr[3] = 0x7fff5fbff88c
&arr[4] = 0x7fff5fbff890
Displaying address using pointers:
ptr + 0 = 0x7fff5fbff880
ptr + 1 = 0x7fff5fbff884
ptr + 2 = 0x7fff5fbff888
ptr + 3 = 0x7fff5fbff88c
ptr + 4 = 0x7fff5fbff890
As you can note in the output example, both are pointing to the same memory location, so you can access the objects from both methods.
Formally, in the C++ 11 standard is mentioned that:
Array-to-pointer conversion:
An lvalue or rvalue of type “array of N T” or “array of
unknown bound of T” can be converted to a prvalue of type “pointer
to T”. The result is a pointer to the first element of the array.
You can see those pages for more information about this theme:
C++ Pointer to an Array.
C++ Pointers and Arrays.
C++ Pointer to an Array.
C++11 Standard Library Extensions
From the C++11 standard (emphasis mine):
An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The result is a pointer to the first element of the array.
This conversion, conversion of an array to a pointer to the first element of the array, is commonly know as "an array decays to a pointer to the first element of the array".
This conversion applies to all types, not just char.
int array_1[10] = {};
int* ptr1 = array_1; // ptr1 is a pointer to the first element of array_1
double array_2[10] = {};
double* ptr2 = array_2; // ptr2 is a pointer to the first element of array_2

passing pointers (the name of array) into function in C/C++

Lets say we create an array like:
int a[4]={1,2,3,4};
Now a is the name of this array and also the pointer points to the first element a[0]. So when I want to call the elements in the array, I can use a[ i ] or *(a+i).
Now I have a function:
void print_array(int* array, int arraySize){
for(int i=0; i<arraySize; i++){
cout<<*(array+i)<<endl;
cout<<array[i]<<endl;
}
}
When I pass a[4]={1,2,3,4} into this function using print_array(a,4), for the first line of cout, I fully understand because I use *(a+i) method to access data and a is the pointer I passed.
What I can't understand is: since I pass a pointer a into function, why can I use a in the format of a[i] like the second line of cout? Isn't a a pointer? If a is a pointer why does a[i] work?
This has confused me for a whole day. Any help will be much appreciated!
a is an array, not a pointer. They are not the same things. However, the name a can be implicitly converted to a pointer (with the value &a[0]).
For example;
int main()
{
int a[] = {1,2,3,4};
int *p = a; // p now has the value &a[0]
Now, after this partial code snippet, assuming i is an integral value, rules of the language amount to;
a[i] is equivalent to *(a + i) which is equivalent to *(&a[0] + i)
p[i] is equivalent to *(p + i)
Now, since p is equal to &a[0] this means that a[i], *(a + i), p[i], and *(p + i) are all equivalent.
When calling print_arrat(a, 4) where a is the name of an array, then a is ALWAYS converted to a pointer. This means print_arrat() is always passed a pointer. And this means *(array + i) inside print_arrat() is the same as a[i] in the caller.
This quote from the C++ Standard will make the point clear (5.2.1 Subscripting)
1 A postfix expression followed by an expression in square brackets is
a postfix expression. One of the expressions shall have the type
“array of T” or “pointer to T” and the other shall have unscoped
enumeration or integral type. The result is of type “T.” The type “T”
shall be a completely-defined object type.64 The expression E1[E2] is
identical (by definition) to *((E1)+(E2)) [Note: see 5.3 and 5.7 for
details of * and + and 8.3.4 for details of arrays. —end note], except
that in the case of an array operand, the result is an lvalue if that
operand is an lvalue and an xvalue otherwise.
Because in effect, while the subscript operator is defined on arrays, what happens is that they decay into pointers for the arithmetic to occur.
Meaning if a is an array, semantically what happens is:
int b = a[i]; => int *__tmp = a; int b = *(__tmp + i);
However, once operator overloading comes into play, then it is no longer true that a[i] == *(a + i). The right hand side may not even be defined.
What I can't understand is: since I pass a pointer "a" into function, why can I use "a" in the format of a[i] like the second line of "cout"?
Because subscript operator a[i] is defined for arrays and it is equivalent to *(a+i) by definition.
In the line with cout, you use array[i] however, where array is a pointer. This is also allowed, because the subscript operator is also defined for pointers.
Isn't "a" a pointer?
No. a is an array. array is a pointer.

Passing array to function in c++ somewhat confused with pointers [duplicate]

#include <iostream>
using namespace std;
void printarray (int arg[], int length) {
for (int n = 0; n < length; n++) {
cout << arg[n] << " ";
cout << "\n";
}
}
int main ()
{
int firstarray[] = {5, 10, 15};
int secondarray[] = {2, 4, 6, 8, 10};
printarray(firstarray, 3);
printarray(secondarray, 5);
return 0;
}
This code works, but I want to understand how is the array being passed.
When a call is made to the printarray function from the main function, the name of the array is being passed. The name of the array refers to the address of the first element of the array. How does this equate to int arg[]?
The syntaxes
int[]
and
int[X] // Where X is a compile-time positive integer
are exactly the same as
int*
when in a function parameter list (I left out the optional names).
Additionally, an array name decays to a pointer to the first element when passed to a function (and not passed by reference) so both int firstarray[3] and int secondarray[5] decay to int*s.
It also happens that both an array dereference and a pointer dereference with subscript syntax (subscript syntax is x[y]) yield an lvalue to the same element when you use the same index.
These three rules combine to make the code legal and work how you expect; it just passes pointers to the function, along with the length of the arrays which you cannot know after the arrays decay to pointers.
I just wanna add this, when you access the position of the array like
arg[n]
is the same as
*(arg + n)
than means an offset of n starting from de arg address.
so arg[0] will be *arg
The question has already been answered, but I thought I'd add an answer with more precise terminology and references to the C++ standard.
Two things are going on here, array parameters being adjusted to pointer parameters, and array arguments being converted to pointer arguments. These are two quite different mechanisms, the first is an adjustment to the actual type of the parameter, whereas the other is a standard conversion which introduces a temporary pointer to the first element.
Adjustments to your function declaration:
dcl.fct#5:
After determining the type of each parameter, any parameter of type “array of T” (...) is adjusted to be “pointer to T”.
So int arg[] is adjusted to be int* arg.
Conversion of your function argument:
conv.array#1
An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The temporary materialization conversion is applied. The result is a pointer to the first element of the array.
So in printarray(firstarray, 3);, the lvalue firstarray of type "array of 3 int" is converted to a prvalue (temporary) of type "pointer to int", pointing to the first element.
firstarray and secondarray are converted to a pointer to int, when passed to printarray().
printarray(int arg[], ...) is equivalent to printarray(int *arg, ...)
However, this is not specific to C++. C has the same rules for passing array names to a function.
The simple answer is that arrays are ALWAYS passed by reference and the int arg[] simply lets the compiler know to expect an array

When are arrays converted to pointers?

Consider the following simple example computing lenght of an array:
#include <iostream>
int a[] = {1, 2, 4};
int main(){ std::cout << sizeof(a)/sizeof(a[0]) << std::endl; }
DEMO
The Standard N4296::8.3.4/7 [dcl.array]
If E is an n-dimensional array of rank i×j×. . .×k, then E appearing
in an expression that is subject to the array-to-pointer conversion
(4.2) is converted to a pointer to an (n−1)-dimensional array with
rank j ×. . .×k.
N4296::4.2/1 [conv.array]
An lvalue or rvalue of type “array of N T” or “array of unknown bound
of T” can be converted to a prvalue of type “pointer to T”. The result
is a pointer to the first element of the array.
So what is the expressions which are the subject of the convertion? Looks like unevaluated operands are not the subject.
http://coliru.stacked-crooked.com/a/36a1d02c7feff41c
I know of the following expressions in which an array is not converted/decayed to a pointer.
When used in a sizeof operator: sizeof(array)
When used in an addressof operator: &array
When used to bind a reference to an array: int (&ref)[3] = array;.
When deducing the typename to be used for instantiating templates.
When used in decltype: decltype(array)
I don't know if anyone can name all the rules off the top of their head, so a community wiki may be appropriate.
The array to pointer conversion occurs in the following contexts. All references are to the C++11 standard.
As part of an implicit conversion sequence selected by overload resolution1
As part of a standard conversion sequence, in contexts where one is allowed
When initializing an object of non-class type from an array ([dcl.init]/16)2
When assigning to an lvalue of non-class type from an array ([expr.ass]/3)
When a prvalue of pointer type is required as the operand to a built-in operator ([expr]/8)
When subscripting into the array ([expr.sub]/1)
When dereferencing a pointer ([expr.unary.op]/1)
With the unary + operator ([expr.unary.op]/7)
With the binary + operator ([expr.add]/1)
With the binary - operator ([expr.add]/2)
With the relational operators ([expr.rel]/1)
With the equality operators ([expr.eq]/1)
When calling a function, if an argument has array type and is passed to an ellipsis ([expr.call]/7)
When converting from a pointer to base class to a pointer to derived class ([expr.static.cast]/11)
In a reinterpret cast to a non-reference type ([expr.reinterpret.cast]/1)
In a const cast to a non-reference type ([expr.const.cast]/1)
In the second or third operand of the conditional operator, under certain circumstances ([expr.cond])
In a template argument, if the corresponding (non-type) template parameter has pointer to object type ([temp.arg.nontype]/5)
The array to pointer conversion does not occur in the following contexts:
Where an lvalue (or glvalue) is required
By the unary & operator ([expr.unary.op]/3)
In a static cast to reference type ([expr.static.cast]/2, [expr.static.cast]/3)
In a reinterpret cast to reference type ([expr.reinterpret.cast]/11)
In a const cast to reference type ([expr.const.cast]/4)
When binding to a reference to the same array type
In a discarded-value expression ([expr]/10)
In the operand to sizeof ([expr.sizeof]/4)
When the second and third operands to the conditional operator have the same array type and are both glvalues of the same value category
In either operand to the built-in comma operator
1 This includes the case where an array of T is passed to a function expecting cv T*, cv void*, or bool, when a user-defined conversion requires one of those types, etc.
2 This includes contextual conversions to bool as they occur in if statements and the like.
The rule of thumb I work by is "in any part of an expression that produces a value result that can be stored in a pointer but cannot be stored in an array".
So, for example;
The expression array + 0 converts array to a pointer before doing the addition, and gives a result that is a pointer.
f(array) converts array to a pointer before calling the function f() that accepts a pointer or an array (not a reference).
array[0] is not required to convert array to a pointer (but the
compiler is free to, since it makes no difference on the result of that expression).
sizeof array does not convert array to a pointer (since it doesn't
evaluate array at all, just its size)
The expression p = array converts array to a pointer and that value
is stored in p
I'm sure there are some cases I've missed, but that simple rule works reasonably well. Of course, it is based on an understanding of what an expression is.....
In your example code, a[0] is identical to *(a + 0), and is thus subject to array-to-pointer conversion. See the Built-in subscript operator section here.

Passing Arrays to Function in C++

#include <iostream>
using namespace std;
void printarray (int arg[], int length) {
for (int n = 0; n < length; n++) {
cout << arg[n] << " ";
cout << "\n";
}
}
int main ()
{
int firstarray[] = {5, 10, 15};
int secondarray[] = {2, 4, 6, 8, 10};
printarray(firstarray, 3);
printarray(secondarray, 5);
return 0;
}
This code works, but I want to understand how is the array being passed.
When a call is made to the printarray function from the main function, the name of the array is being passed. The name of the array refers to the address of the first element of the array. How does this equate to int arg[]?
The syntaxes
int[]
and
int[X] // Where X is a compile-time positive integer
are exactly the same as
int*
when in a function parameter list (I left out the optional names).
Additionally, an array name decays to a pointer to the first element when passed to a function (and not passed by reference) so both int firstarray[3] and int secondarray[5] decay to int*s.
It also happens that both an array dereference and a pointer dereference with subscript syntax (subscript syntax is x[y]) yield an lvalue to the same element when you use the same index.
These three rules combine to make the code legal and work how you expect; it just passes pointers to the function, along with the length of the arrays which you cannot know after the arrays decay to pointers.
I just wanna add this, when you access the position of the array like
arg[n]
is the same as
*(arg + n)
than means an offset of n starting from de arg address.
so arg[0] will be *arg
The question has already been answered, but I thought I'd add an answer with more precise terminology and references to the C++ standard.
Two things are going on here, array parameters being adjusted to pointer parameters, and array arguments being converted to pointer arguments. These are two quite different mechanisms, the first is an adjustment to the actual type of the parameter, whereas the other is a standard conversion which introduces a temporary pointer to the first element.
Adjustments to your function declaration:
dcl.fct#5:
After determining the type of each parameter, any parameter of type “array of T” (...) is adjusted to be “pointer to T”.
So int arg[] is adjusted to be int* arg.
Conversion of your function argument:
conv.array#1
An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The temporary materialization conversion is applied. The result is a pointer to the first element of the array.
So in printarray(firstarray, 3);, the lvalue firstarray of type "array of 3 int" is converted to a prvalue (temporary) of type "pointer to int", pointing to the first element.
firstarray and secondarray are converted to a pointer to int, when passed to printarray().
printarray(int arg[], ...) is equivalent to printarray(int *arg, ...)
However, this is not specific to C++. C has the same rules for passing array names to a function.
The simple answer is that arrays are ALWAYS passed by reference and the int arg[] simply lets the compiler know to expect an array