-1

I thought & and * were just syntactical conventions to declare pointers and references, but when trying to declare a reference to an int*, I have to use int*& otherwise I get this error:

error: cannot declare pointer to ‘int&’

Is there any reasoning behind this design? Why is it that we use int* to declare pointers to integers instead of int& and vice versa for references?

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
Kryptic Coconut
  • 159
  • 1
  • 10
  • 6
    Because `int&*` is a pointer to a reference. Read it as-is in the reverse order. – Some programmer dude Jun 14 '23 at 09:34
  • 1
    Do not tag C for C++ questions. – Eric Postpischil Jun 14 '23 at 09:34
  • 2
    Fundamentally the reason is the `*` is prefix operator with right to left associativity. C *declarator* syntax models itself on the expression syntax. So the status of the `*` operator in an expression affects how you use it in a declaration. C++ inherits all this from C, but made a few changes, like introducing `&` for reference declarations. But the right to left order was kept. – john Jun 14 '23 at 09:36
  • 2
    As for your second question: Legacy. C++ started out as a preprocessor generating C code, and inherited a lot of syntax from C. Which declared pointers using the asterisk `*`. – Some programmer dude Jun 14 '23 at 09:36
  • Lots of symbols (eg `*` and `&` etc) in C++ have multiple, context sensitive, meanings see [Punctuation](https://en.cppreference.com/w/cpp/language/punctuators); where you will find `*` has 4 different meanings and `&` has 5 which all depend on the context they are used in. – Richard Critten Jun 14 '23 at 10:02

3 Answers3

4

(1) A reference is not a pointer (although it may be implemented as one internally). For example, you cannot have an uninitialized reference:

int* p; // fine - it can be initialized later
int& r; // compile time error - it needs to be initialized 

(2) The order is important: *& is not the same as &*.

(3) To decode a c/c++ declaration use the "right-left rule". This is how you read your declaration:

enter image description here

(4) There is a site that can help you understand/decode c declarations (not c++, but it is good enough for many cases): cdecl.org

[EDIT, thanks to @Jan Schultke] cdecl+ seems to also handle c++ declarations.

zdf
  • 4,382
  • 3
  • 18
  • 29
  • 2
    I recommend using [cdecl-plus](https://eisenwave.github.io/cdecl-plus/?decl=int&*%20r) instead. It supports a greater subset of C++ and is more responsive – Jan Schultke Jun 14 '23 at 10:58
1

I thought & and * were just semantical conventions to declare pointers and references, but when trying to declare a reference to a int pointer I have to use int*& otherwise it errors out to error: cannot declare pointer to ‘int&’

They are more than conventions; they are rules of the C++ language.

Furthermore why is it that we use int* to declare integer pointers instead of int& and vice versa for references?

Fundamentally, there is no reason why we must use one character versus another to denote any particular concept. We could designate * to stand for addition and } to stand for an elephant. As it happens, * was chosen to use for pointers when C was being developed. I expect it was chosen largely on the basis of what characters were available in the character sets and keyboards in use at the time, as well as what other characters had been assigned other meanings. Possibly . could have been used for a pointer. However * was chosen.

When C++ was developed, & was likely chosen to use for references because it was already associated with addresses due to its use in C for taking the address of an object or function.

So, that is how we ended up with * and & for pointers and references.

Next, why we write int *& for a reference to a pointer arises from how the grammar of declarations was designed. As Kernighan and Ritchie told us in The C Programming Language, a declaration shows a sort of picture of how an identifier will be used. int *x means *x will be used as an int, and therefore x must be a pointer to an int.

The *x part of int *x is called the declarator. A declarator can be complicated, as in int *(*x)[3], which declares a pointer to an array of 3 pointers to int. Because of the notion of the declarator giving us a picture of how the identifier will be used, the declarator gives us the final type of the pictured expression, so we must unwind the declarator—parse it in reverse in a sense—to figure out what the type of the declared identifier is.

In C++, & for references was tacked onto this existing grammatical structure. So, even if we would not write *&x in an expression, we still parse it using the same logic. So & binds more tightly to x. So int *&x tells us that *&x is an int, so &x is a pointer to an int, so x is a reference to a pointer to an int.

If we wrote int &*x, that would mean that &*x is an int, so *x is a reference to an int, so x is a pointer to a reference to an int. However, C++ does not define pointers to references. Grammatically, we can understand what this declaration is telling us, but the type it is telling us that x is is not defined by the C++ standard, so the compiler complains about it.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
0

In C++, the declaration int*& is used to declare a reference to a pointer to an integer, while int&* is not a valid declaration. Let's break down the differences between the two:

int*&: This declares a reference to a pointer to an integer. It means that the reference itself (&) is bound to a pointer (*) that can point to an integer (int). It allows you to modify the pointer itself or the value it points to.