Top 5 Questions about C/C++ Pointers

This article summarizes top questions asked about C/C++ pointers on stackoverflow.com. Pointers are the most confusing part of C/C++, those questions use simple examples to explain key pointer concepts.

1. Count from 1 to 1000 without using loops

#include <stdio.h>
#include <stdlib.h>
 
void main(int j) {
  printf("%d\n", j);
  (&main + (&exit - &main)*(j/1000))(j+1);
}

The only other method to count 1 to 1000 is using recursion. According to C language, j has ‘1’as its value at the beginning. When 1 <= j < 1000, &main + (&exit - &main)*(j/1000) always evaluated to &main, which is the memory address of main. (&main)(j+1) is the next iteration we want to get, which would print ‘2’ on the screen, etc. The stop condition of this recursion is that When j hits 1000, &main + (&exit - &main)*(j/1000) evaluates to &exit, which will elegantly exit this process, and has the error code 1001 returned to the operating system.

2. Why a[5] == 5[a]?

a[b] means *(a+b) by C standard. a is base address, b is an offset starting from a. a[b] is the value in the address of a+b.

Thus a+5 and 5+a is the same memory address. Their value *(a+5) and *(5+a) is the same. So a[5] == 5[a]

3. How many levels of pointers can we have?

As much as a human can handle. Any c/c++ compiler definitely support more than that.

4. C pointer to array/array of pointers disambiguation

What is the difference between the following declarations:

int* arr1[8];
int (*arr2)[8];
int *(arr3[8]);

By C precedence table, array [], function return () have higher precedence over pointer *.

For int* arr1[8]
arr1 first and foremost is an array no matter what type the element is. After applying pointer *, we know arr1 is an array of int pointers.

For int (*arr2)[8]
By bracket overriding rule, pointer * has higher precedence over array [] in this case. Then arr2 is first and foremost a pointer no matter what it is pointing to. After applying array [], we know arr2 is a pointer to an array of int.

For int *(arr3[8])
Bracket in this case does not change any default precedence, so it is the same as int* arr1[8]

5. What's the point of const pointers?

(1) void foo(int* const ptr);
(2) void foo(int* ptr);

For the caller of foo, value of ptr is copied into foo in both (1) and (2).

(1) and (2) make a difference only for the implementer of foo, not the client of foo.

In (2), implementer may accidentally change the value of ptr which may potentially introduce bugs.

(1) is like implementer say to the compiler before writing the body of foo, “hey, I don’t want to value of ptr, if it is changed in some obscure way, make the compilation fail, let me check on that”

Category >> C/C++ >> Top 10  
  • Hariom Yadav

    i need some more questions..

  • Rob Desbois

    > Why is this code a invalid answer? gcc compile it just fine and it gets the job done. What else do you expect?
    Just because code compiles doesn’t mean it’s valid. There is plenty of code that will compile but yields undefined behaviour – calling main from within your code is explicitly disallowed by the standard.
    The answer is invalid C++ because it calls main directly, and because it relies on j being 1, which isn’t guaranteed. In other words, in different scenarios this code could: work perfectly; count from 10 to 1000; count from 1001 to 1000…the long way around; loop infinitely (due to calling main); call terminate(); explode in a fireball and cause your computer to meltdown. Ok that last one is less likely ;-) but the point is the behaviour is not specified, so the code is potentially unreliable and unportable

    > You are right ‘void main(int)’ is not valid, but ‘int main(int)’ is. It
    is implementation defined according to C standard 5.1.2.2.1; C++
    standard 3.6.1. The two you mentioned are required to be implemented in
    addition to whatever the compiler want to support.
    You’re right too, I must’ve missed that sentence.

    > Knowing [How many levels of pointers we can have] does not help anything except for the compiler/ tool writer.
    Perhaps not, but it’s the answer to the question. Your answer is accurate, but not precise. If I were asking the question then I would expect the answer to give the exact number is. Of course few, if any, C++ developers will find this to be a practical limitation, but that doesn’t stop it from being the precise answer to the question.

  • yuanfang

    That’s sum from 1 to 1000, isn’t it?

  • yuanfang

    *You are right. Some of my wording is not rigorous and precise. “Top 5 Questions about C/C++ Pointers” maybe a better name.

    Wow, in what world is “Count from 1 to 1000 without using loops” a top question about C++ pointers? It’s not a question about pointers at all. The way to achieve it is, as you say, recursion, which is also unrelated to pointers. The only link between the question and pointers is a bizarrely contrived and invalid answer.

    *The question is not about pointers, but the implementation somehow is. At lease, temporal function pointers and pointer arithmetic are used. Of course recursion is not about pointer, but its implementation could be. Why is this code a invalid answer? gcc compile it just fine and it gets the job done. What else do you expect?

    Stating something is true “according to C language” and then assuming it is valid for C++ is a risky business: it may or may not be true, as C++ is not a superset of
    C. Your assertion that it is true in C is incorrect: generally speaking (j == 1) will be true if the program was invoked without arguments, however the standard does allow this argument to be 0.
    The signature of your main() function is not a valid one; the only standard-supported signatures are int(void) and int(int, char*[]).

    *You are right ‘void main(int)’ is not valid, but ‘int main(int)’ is. It is implementation defined according to C standard 5.1.2.2.1; C++ standard 3.6.1. The two you mentioned are required to be implemented in addition to whatever the compiler want to support.

    Most importantly though: the standard requires that ‘the function main shall not be used within a program’, which makes the recursive calling of it undefined behaviour.

    *Good to know. I’ll look into that.

    Just to add to your answer to question 3: the [C++11] standard sets the minimum-acceptable support for number of pointer, array and function declarators modifying a type at 256.

    *Knowing that does not help anything except for the compiler/ tool writer.

    Your answer to question 4 again refers to the C language.

  • Michael

    Count from 1 to 1000 without using loops
    RIGHT answer:
    return (1+1000)*1000/2;
    (no loops, no recursion, no tricky and unreadable code, just rule we all learnt in elementary school)

  • Rob Desbois

    Wow, in what world is “Count from 1 to 1000 without using loops” a top question about C++ pointers? It’s not a question about pointers at all. The way to achieve it is, as you say, recursion, which is also unrelated to pointers. The only link between the question and pointers is a bizarrely contrived and invalid answer.
    Stating something is true “according to C language” and then assuming it is valid for C++ is a risky business: it may or may not be true, as C++ is not a superset of
    C. Your assertion that it is true in C is incorrect: generally speaking (j == 1) will be true if the program was invoked without arguments, however the standard does allow this argument to be 0.
    The signature of your main() function is not a valid one; the only standard-supported signatures are int(void) and int(int, char*[]).
    Most importantly though: the standard requires that ‘the function main shall not be used within a program’, which makes the recursive calling of it undefined behaviour.

    Just to add to your answer to question 3: the [C++11] standard sets the minimum-acceptable support for number of pointer, array and function declarators modifying a type at 256.

    Your answer to question 4 again refers to the C language.