Since the question is about “smartness”, I would like to add one point. My answer will refer to the C language, but I assume the situation is identical in C++.
The compiler does not need to really be smart in this case, simply because the language does not allow to perform multiplications directly on addresses, so the symbol *
preceding a pointer can always mean only “dereference”, while the symbol *
preceding a non-pointer can only mean “multiplication”.
I will try to explain this with an example.
Let's create a small program and let's call it test.c
. Let's then create within the main()
function the two pointers first
and second
and let the address of first
be 140732806008300
and the address of second
be 140732806008296
.
When we try to sum the two addresses the compiler allows us to peacefully use the +
operand without a previous cast, because in C the sum of pointers is allowed:
#include <stdio.h>
int main () {
int *first, *second, fifteen = 15, twenty = 20;
first = &fifteen; /* Let the address of `first` be 140732806008300 */
second = &twenty; /* Let the address of `second` be 140732806008296 */
printf("first + second is: %llu\n", (long long unsigned int) first + second);
return 0;
}
What we did here was to directly perform a sum of two pointers, getting a new pointer as a result, which then was casted into an unsigned integer for the sake of the prinf()
function. Since this is allowed, we correctly get the string
first + second is: 703664030041496
But if instead we try to multiply the two addresses using the multiplication operand *
…
#include <stdio.h>
int main () {
int *first, *second, fifteen = 15, twenty = 20;
first = &fifteen; /* Let the address of `first` be 140732806008300 */
second = &twenty; /* Let the address of `second` be 140732806008296 */
printf("first * second is: %llu\n", (long long unsigned int) first * second);
return 0;
}
…we get the following error:
test.c: In function ‘main’:
test.c:11:69: error: invalid operands to binary * (have ‘long long unsigned int’ and ‘int *’)
printf("first * second is: %llu\n", (long long unsigned int) first * second);
This is because direct multiplication of addresses is not allowed. Therefore we have to cast the pointers into valid integers before being able to eventually use the symbol *
with the meaning of “multiplication operand”:
#include <stdio.h>
int main () {
int *first, *second, fifteen = 15, twenty = 20;
first = &fifteen; /* Let the address of `first` be 140732806008300 */
second = &twenty; /* Let the address of `second` be 140732806008296 */
printf("first * second is: %llu\n", (long long unsigned int) ((long unsigned int) first) * ((long unsigned int) second));
return 0;
}
…Now we finally have got the symbol *
standing between integers (and not between pointers). And in such context it can only mean “multiplication” (and nothing else), so we finally get the correct result of the operation:
first * second is: 4480243502683625952
I tried to think about examples where the meaning of the symbol *
cannot be disambiguated (by humans as well), but without success.
This means that the symbol *
can unambiguously mean only one thing in a given context – i.e., there are cases where we have to use parentheses to change its meaning, but its meaning is always unambiguous in its context.