9

In C, I know we can do this with pointers:

int *p;          /* an int pointer (ptr to an int) */
int **pp;        /* a pointer to an int pointer (ptr to a ptr to an int) */

And even:

int **app[];            /* an array of pointers to int pointers */
int (**ppa)[];          /* a pointer to a pointer to an array of ints */
int (**ppf)();          /* a pointer to a pointer to a function returning an int */
int *(*pap)[];          /* a pointer to an array of int pointers */
int **fpp();            /* a function returning a pointer to an int pointer */

But can we do something like three pointers to limitless? e.g.:

int ***ppp;             /* a pointer to a pointer to an int pointer */
int ****pppp;           /* a pointer to a pointer to a pointer to an int pointer */

...and so on till infinity.

Is there any upper limits to the numbers of pointers to a pointer we can have? If so, what is the upper limit?

pasignature
  • 577
  • 1
  • 6
  • 13
  • 4
    Theoretically there is no limit. Practically a compiler _could_ have a limit which would probably be far above what is ever needed. Also more than three indirections such as `int ***foo` is rarely (if not never) useful. Also read [this](https://stackoverflow.com/questions/21488544/triple-pointers-in-c-is-it-a-matter-of-style) – Jabberwocky Mar 12 '20 at 09:37
  • @RobertSsupportsMonicaCellio great suggestion...that I will do. – pasignature Mar 12 '20 at 11:17
  • 2
    This is a fun question, and I have up clicked it, but it has been [asked and answered already](https://stackoverflow.com/questions/10087113/how-many-levels-of-pointers-can-we-have) – ryyker Mar 12 '20 at 12:04
  • 1
    @ryyker Yeah, I was wondering too if I didn´t saw it anywhere else but was busy thinking about it and too less inspired to search for and while I´ve found it, you were faster ;-). – RobertS supports Monica Cellio Mar 12 '20 at 12:08

2 Answers2

13

The standard does not impose any upper limit. What it does say is that a compiler needs to support at least 12.

In practical code it can be considered infinite. Only if you write programs that writes programs that no human should ever read could this be relevant. Most coders would say that you should take three stars as a warning. Don't go beyond two without a really good reason.

I tried with 10000 on gcc and it worked. I'm now trying with 100000. One interesting thing is that it takes extremely long time to compile. It took several minutes to compile, and the only statement was a pointer declaration with 10000 stars.

Code to generate a C file:

// gen.c
#include <stdio.h>

int main()
{
    const size_t n = 10000;
    printf("int main(){int ");
    for(size_t i=0; i<n; i++)
        printf("*");
    printf("p;}\n");
}

Run:

$ gcc gen.c -c gen
$ ./gen > stars.c
$ gcc stars.c

Answer to comments:

This was a fun experiment, but I will not investigate this further.

klutt
  • 30,332
  • 17
  • 55
  • 95
  • hmmmm....interesting klutt. looks like it also depends on compiler being used...in which case I am sure there will never be a compiler to handle unlimited pointers or maybe So if there is a limit, the limit is with the compiler in use and not the ability to use unlimited numbers of pointers...right? – pasignature Mar 12 '20 at 10:44
  • Is it possible to fully derefence this pointer or could that lead to undefined behaviour? – Danish Mar 12 '20 at 10:55
  • @RobertSsupportsMonicaCellio what am trying to do is instead of using one pointer to go through a very large text file, which seems slow to me, am trying to improve speed if possible by adding more pointers. Three is looking good so far....but I'm not even sure if using three is a good practice let alone adding more.... – pasignature Mar 12 '20 at 10:57
  • @klutt I'm concerned about speed...does the compile time affect the speed at runtime? I guess it should not else my quest to use more pointers is defeated. – pasignature Mar 12 '20 at 11:02
  • 1
    @Danish Since you can declare that amount of pointers without any UB, you can also *use* and with that *dereference* them but you have to be carefully with the right typography by assignment and accessing of the pointed content. – RobertS supports Monica Cellio Mar 12 '20 at 11:04
  • @pasignature Consider the future reader of your code or even yourself after a few years or just months or even when working in a team. Would you prefer to develop such hard to understand code or is the *possible* performance improvement really that important that it weighs more? – RobertS supports Monica Cellio Mar 12 '20 at 11:11
  • @pasignature You also could provide the respective code in another question and ask for simplification or speed improvement. Maybe you don´t even need to use this kind of coding and can achieve the speed improvement by something else. – RobertS supports Monica Cellio Mar 12 '20 at 11:12
  • @RobertSsupportsMonicaCellio I clearly understand ur pain in reading the code but I'm trying to solve the speed issue and then go back to reformat properly. – pasignature Mar 12 '20 at 11:13
  • @pasignature Consider my second comment. – RobertS supports Monica Cellio Mar 12 '20 at 11:13
  • @pasignature: Adding more levels of pointers to some piece of code is not a technique for improving the speed of processing a text file. If the processing of some text file is too slow, you should ask about that, not about adding levels of indirection. – Eric Postpischil Mar 12 '20 at 11:36
  • Time to switch compilers. Clang compiles `char *…*x;` with 100,000 asterisks in .04 seconds on a 2.9 GHz Intel Core i7 MacBook Pro (Apple Clang 11.0.0). – Eric Postpischil Mar 12 '20 at 11:42
  • 1
    *"This was a fun experiment, but I will not investigate this further."* - +1 – RobertS supports Monica Cellio Mar 12 '20 at 11:56
  • @EricPostpischil For the same code as klutt´s one? Can´t imagine that there is such a huge difference between gcc and clang but if it would be, this is kind of interesting. – RobertS supports Monica Cellio Mar 12 '20 at 12:15
  • @pasignature - _...in which case I am sure there will never be a compiler to handle unlimited pointers_ Actually, the 2nd score in the duplicate question I link under your question provides a simple example of how [One or two static levels are common. Triple indirection is rare. But infinite is very common.](https://stackoverflow.com/a/10091962/645128). IMO that is a fascinating answer and worth taking a look at.... – ryyker Mar 12 '20 at 12:18
  • ...klutt, Your's is too. +1, but the example provided in the link I posted in the comment above counters the humorous statement you make: _Only if you write programs that writes programs that no human should ever read could this be relevant._ – ryyker Mar 12 '20 at 12:19
  • @RobertSsupportsMonicaCellio: I was using a single external declaration of `char *…*x;`, but I tested with klutt’s as well, and the time for that is .05 seconds. – Eric Postpischil Mar 12 '20 at 12:54
  • @ryyker I also like [this](https://stackoverflow.com/questions/10087113/how-many-levels-of-pointers-can-we-have/10091962#comment12917583_10087113) one under the question: "*You can keep adding levels of pointers until your brain explodes or the compiler melts - whichever happens soonest.*" - or the more behave and top-of-the-point [one](https://stackoverflow.com/questions/10087113/how-many-levels-of-pointers-can-we-have/10091962#comment12917273_10087113): "*If that ever becomes a real issue for you, you are doing something very wrong.*" – RobertS supports Monica Cellio Mar 12 '20 at 13:02
  • @ryyker I have objections against interpreting that at infinite indirection, but atm I don't have time nor energy to go into detail about it. :) – klutt Mar 12 '20 at 13:07
11

The C 11 standard imposes no maximum limits and in fact states "Implementations should avoid imposing fixed translation limits whenever possible." in a footnote.

The minimum limits are given by 5.2.4 Environmental limits:

The implementation shall be able to translate and execute at least one program that contains at least one instance of every one of the following limits:18)

  • 127 nesting levels of blocks
  • 63 nesting levels of conditional inclusion
  • 12 pointer, array, and function declarators (in any combinations) modifying an arithmetic, structure, union, or void type in a declaration
  • 63 nesting levels of parenthesized declarators within a full declarator
  • 63 nesting levels of parenthesized expressions within a full expression
  • 63 significant initial characters in an internal identifier or a macro name (each universal character name or extended source character is considered a single character)
  • 31 significant initial characters in an external identifier (each universal character name specifying a short identifier of 0000FFFF or less is considered 6 characters, each universal character name specifying a short identifier of 00010000 or more is considered 10 characters, and each extended source character is considered the same number of characters as the corresponding universal character name, if any)
  • 4095 external identifiers in one translation unit
  • 511 identifiers with block scope declared in one block
  • 4095 macro identifiers simultaneously defined in one preprocessing translation unit
  • 127 parameters in one function definition
  • 127 arguments in one function call
  • 127 parameters in one macro definition
  • 127 arguments in one macro invocation
  • 4095 characters in a logical source line
  • 4095 characters in a string literal (after concatenation)
  • 65535 bytes in an object (in a hosted environment only)
  • 15 nesting levels for #included files
  • 1023 case labels for a switch statement (excluding those for any nested switch statements)
  • 1023 members in a single structure or union
  • 1023 enumeration constants in a single enumeration
  • 63 levels of nested structure or union definitions in a single struct-declaration-list

A conforming C compiler would provide at least 12 levels of pointer indirection.

Community
  • 1
  • 1
Andrew Henle
  • 32,625
  • 3
  • 24
  • 56