1

I was going through the topics of constexpr and consteval and found the below,

  1. We can have pointers that are of type CONSTEXPR
  2. A CONSTEVAL function can return a pointer of a CONSTEXPR variable

and my question here is that, how is the above 2 possible?

The above 2 questions because, as far as I am aware, all the variables are created in the memory during runtime and pointer is the address of that memory.

So, how can pointer of type CONSTEXPR exist (since CONSTEXPR variables have to be initialized at compile time)? and how can a CONSTEVAL function return a pointer of CONSTEXPR variable during the compile time?

   #include <iostream> 

   constexpr int a{1};

   consteval const int* aptrfunc()  //How can this function return a pointer at compile time
   {
       return &a;
   }

   int main()
   {
        constexpr const int* aptr{&a};   //How can this exist at compiletime?
        std::cout<<aptr<<'\n';           //Prints address of a
        std::cout<<aptrfunc()<<'\n';     //Prints address of a
        return 0;
    }
5
  • 2
    I'm pretty sure the compiler deals with compile time pointers symbolically. If you check, you'll see that there is no way of obtaining the numerical value of the pointer at compile time. Commented Nov 1, 2023 at 4:55
  • constexpr-ness isn't a part of the type, it's a separate property of a variable (or function or something else). Commented Nov 1, 2023 at 4:56
  • Basically global objects(objects defined outside any function) have "fixed address" and so a constexpr pointer can point to it. Commented Nov 1, 2023 at 5:04
  • @PasserBy he exact pointer addresses must not necessarily be known at compile-time, but the compiler can at least distinguish whether constexpr can be used for an expression involving pointers if the pointers and their values can be determined at compile-time. It's all about compile-time versus runtime determinability of values and addresses, and the compiler's ability to evaluate expressions at compile-time based on that determinability. Commented Nov 1, 2023 at 5:05
  • Lifetime of variables was an important part of C education and became even more pronounced in C++. If you have read your books, you must've known what storage class means. constexpr objects have static storage class, meaning they have static duration. That is, their address is determined at compile-time. Before costexper keyword, having to waste cpu cycles at run-time for such information that is available at compile-time was really annoying. If only you had experience with assembler, you'd know there's a .data section or something. Commented Nov 1, 2023 at 7:50

2 Answers 2

0

The above 2 questions because, as far as I am aware, all the variables are created in the memory during runtime

Yes but not all of them have a fixed address.

As far as the standard is concerned, a constexpr pointer is allowed to point to an object that remains at a fixed address. And an object defined outside any function(global object) have a fixed address and so it's address can be used to initialize a constexpr pointer.

As in your example, a is a global int and hence remains at fixed address, so a constexpr pointer can be made to point to it.

An implementation/compiler might deal with such(constexpr) pointers symbolically but that is an implementation detail.

Sign up to request clarification or add additional context in comments.

Comments

0

pointer is the address of that memory

Well, not exactly. The phrasing used by cppreference.com is "represents the address". It is more important for a pointer to allow the program to access what it points to than for a pointer to have a certain value or bit pattern. You are getting hung up on knowing the certain value.

There is a lot you can do with pointers without knowing exact addresses, if you think abstractly. You can, for example, determine if two pointers point to the same address. You might not know the exact address, just that they are the same. In practice, the addresses that are valid for constexpr values are known at compile time up to an offset that is supplied by the operating system at runtime, and that is fixed for the entire execution. This is enough to determine whether or not two pointers are equal. Similarly, in places where a constant expression is required, "up to an offset" is sufficient for the compiler to do what it needs to do.

Interestingly, one place where a constant expression is not required is an operand to the streaming operator. That is, in the expression std::cout<<aptr, it is not required that the compiler be able to determine exactly which characters will be displayed. Instead, the output characters can be determined at runtime. In this respect, it is not possible to view the value of aptr until the program executes. However, at compile time, despite not being able to display an exact value, it is known that the expression aptr represents the address of a, and that is good enough for all (legal) compile-time processing.

4 Comments

"values are known at compile time up to an offset" they're not. Each TU is compiled independently and there's no way the compiler gets to know where an extern or inline variable gets placed.
@PasserBy When contrasting "compile time" with "run time", it is traditional to include the linker as part of the compiler. The linker does know where the variables end up within the program. (Is there a better term to use here than "compile time"?)
In practice, the linker doesn't know anything about constexpr. The compiler has to resolve the constexpr pointer in isolation. For example static_assert(aptr != aptrfunc()); will fire and it will have nothing to do with the linker.
@PasserBy As I said in the question, there is enough information available for the compiler to do what it needs to do, and one should not get hung up on the exact values being used. I do not believe that diving deeper into the details adds value to this answer. Take it as a homework exercise to figure out how one can take one "symbol for the linker representing the address of a" and another "symbol for the linker representing the address of a" and conclude that they are equal without the linker getting involved.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.