Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lvalue and Rvalue with C++ arrays

Tags:

c++

arrays

I have done some experimentation on array and learning about L-value and R-values,

From my understanding:

L-values are object that has an identifiable memory location, R-values are defined by exclusion, anything that is not a L-value, is a R-value, by exclusion.

Here is my experiment:

int array [] = {8, 7, 6, 5, 4};            
std::cout << array << std::endl;           //0x61fedc
std::cout << &array << std::endl;          //0x61fedc
std::cout << *(&array) << std::endl;       //0x61fedc
std::cout << *array << std::endl;          //8

Line 1 and 2 should come with no surprises, when you evaluate an array, it will return the address of the first element

What is confusing is the results from line 3. *(&array) is saying to me "what is the de-referenced value of the first memory address of the variable array, I was expecting 8, however i got back the first memory address, why is that?

Lastly, line 4 evaluates to 8, which was expected. However, since the dereferencing operator works on the array variable, why can't we conclude that array is a pointer (points to the first element memory address)? I know this can't be truth but they behaves the same?

Thank you

like image 939
Brendon Cheung Avatar asked Oct 21 '25 03:10

Brendon Cheung


1 Answers

I find an example clarifying. Here I have some foo overloads accepting the versions you've used in your code.

#include <iostream>
#include <string>

template<size_t N>
std::string foo(const int(&)[N]) {
    return std::string(" int(&)[") + std::to_string(N) + "]\n";
}

template<size_t N>
std::string foo(const int(*)[N]) {
    return std::string(" int(*)[") + std::to_string(N) + "]\n";
}

std::string foo(const int*) {
    return " int*\n";
}

std::string foo(int) {
    return " int\n";
}

int main() {
    int array [] = {8, 7, 6, 5, 4};
    std::cout << array     << foo(array);
    std::cout << &array    << foo(&array);
    std::cout << *(&array) << foo(*(&array));
    std::cout << *array    << foo(*array);
}

Possible output:

0x7ffeaf43a610 int(&)[5]
0x7ffeaf43a610 int(*)[5]
0x7ffeaf43a610 int(&)[5]
8 int

As you can see, with this combination of overloads, none of the versions decay into an int*.

like image 95
Ted Lyngmo Avatar answered Oct 23 '25 18:10

Ted Lyngmo