Enzos
Enzos

Reputation: 361

A little confused about constexpr functions

Consider the following code:

constexpr const int* address(const int& r)
{
   return &r;
}


int main()
{
   int x = 10;
   constexpr const int* p = address(x); //error

   _getch();
   return 0;
}

This is an error: "function call must have a constant value in a constant expression". Ok.

Two questions:

  1. If 'x' is declared static, there are no errors. Why?

  2. How is it possible to get a variable address during the compilation process? Aren't they allocated at run-time?

Upvotes: 12

Views: 1098

Answers (5)

Helmut Zeisel
Helmut Zeisel

Reputation: 406

To question 2: "How is it possible to get a variable address during the compilation process? Aren't they allocated at run-time?"

x is placed on the stack, and it has a different address when the stack changes. This may happen if x is not declared in main(), but in some other function, which is called from different places. For example, try

#include <iostream>
constexpr const int* address(const int& r)
{
   return &r;
}


int f()
{
   int x = 10;

   const int* p = address(x);
   std::cout << "p=" << p << std::endl;
}

int g()
{
    int data[1000];
    f();
}

main()
{
   f();
   g();
   return 0;
}

Upvotes: 0

pepsiman
pepsiman

Reputation: 76

The address of a variable with static storage duration is not known at compile time. It is only known at link time. A pointer to a variable with static storage duration can be used at compile time because the exact value of the address does not matter - pointer comparisons and casts are not allowed at compile time.

Upvotes: 3

Victor Dyachenko
Victor Dyachenko

Reputation: 1401

Because address of variable with static storage duration (global or local static) is known at compile time and doesn't change during program execution. Also there is exactly one object in the whole process.

Nothing of what has been said above is true for local variable. It is allocated in the stack frame, address of which differs. Also there can be several such frames at the same moment.

Upvotes: 0

Bathsheba
Bathsheba

Reputation: 234635

A pointer to a variable with static storage duration is a constexpr. You can see this in the following program:

int main() {
    static int x;
    int y;
    constexpr int* px = &x; // Compilation is successful
    constexpr int* py = &y; // Compilation will fail
}

See https://ideone.com/lc9u3E

px is an address constant expression. Here's a standard reference:

[5.19p3]:

An address constant expression is a prvalue core constant expression of pointer type that evaluates to the address of an object with static storage duration, to the address of a function, or to a null pointer value, or a prvalue core constant expression of type std::nullptr_t.

Upvotes: 6

Caleth
Caleth

Reputation: 62531

If 'x' is declared static, there are no errors. Why?

This is because there is always exactly one x in the program. It has an address (somewhere in the .data segment under normal conditions).

Confusingly, both static and extern keywords specify the storage duration as static (they differ in linkage)

How is it possible to get a variable address during the compilation process? Aren't they allocated at run-time?

Variables with automatic, dynamic or thread storage durations are allocated at runtime. Static duration variables are allocated by the compiler. (The linker and OS can change the location, but they know how to fix all the references when they do)

Upvotes: 11

Related Questions