Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do we use "type * var" instead of "type & var" when defining a pointer?

Tags:

c++

syntax

I'm relatively new to C++ (about one year of experience, on and off). I'm curious about what led to the decision of type * name as the syntax for defining pointers. It seems to me that the syntax should be type & name as the & symbol is used everywhere else in code to refer to the variable's memory address. So, to use the traditional example of int pointers:

int a = 1;
int * b = &a;

would become

int a = 1;
int & b = &a

I'm sure there's some reason for this that I'm just not seeing, and I'd love to hear some input from C++ veterans.

Thanks, -S

like image 229
spencewah Avatar asked Jun 30 '09 01:06

spencewah


People also ask

Is there any reason to use var instead of let?

var and let are both used for variable declaration in javascript but the difference between them is that var is function scoped and let is block scoped. Variable declared by let cannot be redeclared and must be declared before use whereas variables declared with var keyword are hoisted.

Why do we use var keyword?

var is a keyword, it is used to declare an implicit type variable, that specifies the type of a variable based on initial value.

Should I use var type in Java?

In Java, var can be used only where type inference is desired; it cannot be used where a type is declared explicitly. If val were added, it too could be used only where type inference is used. The use of var or val in Java could not be used to control immutability if the type were declared explicitly.

Is it good to use VAR in Dart?

var is an easy way to initialise variables as you don't have to explicitly state the type. Dart just infers the type to make it easier for you. If you write int number = 5 it would be the same as var number = 5 as dart would infer that this variable is an integer.


4 Answers

C++ adopts the C syntax. As revealed in "The Development of the C Language" (by Dennis Ritchie) C uses * for pointers in type declarations because it was decided that type syntax should follow use.

For each object of [a compound type], there was already a way to mention the underlying object: index the array, call the function, use the indirection operator [*] on the pointer. Analogical reasoning led to a declaration syntax for names mirroring that of the expression syntax in which the names typically appear. Thus,

int i, *pi, **ppi;

declare an integer, a pointer to an integer, a pointer to a pointer to an integer. The syntax of these declarations reflects the observation that i, *pi, and **ppi all yield an int type when used in an expression.

Here's a more complex example:

int *(*foo)[4][];

This declaration means an expression *(*foo)[4][0] has type int, and from that (and that [] has higher precedence than unary *) you can decode the type: foo is a pointer to an array of size 4 of array of pointers to ints.

This syntax was adopted in C++ for compatibility with C. Also, don't forget that C++ has a use for & in declarations.

int & b = a;

The above line means a reference variable refering to another variable of type int. The difference between a reference and pointer roughly is that references are initialized only, and you can not change where they point, and finally they are always dereferenced automatically.

int x = 5, y = 10;
int& r = x;

int sum = r + y; // you do not need to say '*r' automatically dereferenced.

r = y; // WRONG, 'r' can only have one thing pointing at during its life, only at its infancy ;)
like image 96
Khaled Alshaya Avatar answered Nov 13 '22 22:11

Khaled Alshaya


I think that Dennis Ritchie answered this in The Development of the C Language:

For each object of such a composed type, there was already a way to mention the underlying object: index the array, call the function, use the indirection operator on the pointer. Analogical reasoning led to a declaration syntax for names mirroring that of the expression syntax in which the names typically appear. Thus,

int i, *pi, **ppi;

declare an integer, a pointer to an integer, a pointer to a pointer to an integer. The syntax of these declarations reflects the observation that i, *pi, and **ppi all yield an int type when used in an expression. Similarly,

int f(), *f(), (*f)();

declare a function returning an integer, a function returning a pointer to an integer, a pointer to a function returning an integer;

int *api[10], (*pai)[10];

declare an array of pointers to integers, and a pointer to an array of integers. In all these cases the declaration of a variable resembles its usage in an expression whose type is the one named at the head of the declaration.

So we use type * var to declare a pointer because this allows the declaration to mirror the usage (dereferencing) of the pointer.

In this article, Ritchie also recounts that in "NB", an extended version of the "B" programming language, he used int pointer[] to declare a pointer to an int, as opposed to int array[10] to declare an array of ints.

like image 21
bk1e Avatar answered Nov 13 '22 22:11

bk1e


If you are a visual thinker, it may help to imagine the asterisk as a black hole leading to the data value. Hence, it is a pointer.

The ampersand is the opposite end of the hole, think of it as an unraveled asterisk or a spaceship wobbling about in an erratic course as the pilot gets over the transition coming out of the black hole.

I remember being very confused by C++ overloading the meaning of the ampersand, to give us references. In their desperate attempt to avoid using any more characters, which was justified by the international audience using C and known issues with keyboard limitations, they added a major source of confusion.

One thing that may help in C++ is to think of references as pre-prepared dereferenced pointers. Rather than using &someVariable when you pass in an argument, you've already used the trailing ampersand when you defined someVariable. Then again, that might just confuse you further!

One of my pet hates, which I was unhappy to see promulgated in Apple's Objective-C samples, is the layout style int *someIntPointer instead of int* someIntPointer

IMHO, keeping the asterisk with the variable is an old-fashioned C approach emphasizing the mechanics of how you define the variable, over its data type.

The data type of someIntPointer is literally a pointer to an integer and the declaration should reflect that. This does lead to the requirement that you declare one variable per line, to avoid subtle bugs such as:

int* a, b;  // b is a straight int, was that our intention?

int  *a, *b;  // old-style C declaring two pointers

int* a;
int* b;  // b is another pointer to an int

Whilst people argue that the ability to declare mixed pointers and values on the same line, intentionally, is a powerful feature, I've seen it lead to subtle bugs and confusion.

like image 43
Andy Dent Avatar answered Nov 13 '22 21:11

Andy Dent


Your second example is not valid C code, only C++ code. The difference is that one is a pointer, whereas the other is a reference.

On the right-hand side the '&' always means address-of. In a definition it indicates that the variable is a reference.

On the right-hand side the '*' always means value-at-address. In a definition it indicates that the variable is a pointer.

References and pointers are similar, but not the same. This article addresses the differences.

like image 1
Christopher Avatar answered Nov 13 '22 22:11

Christopher