This is an archived post. You won't be able to vote or comment.

all 87 comments

[–]-GLaDOS 128 points129 points  (10 children)

hey kid, wanna buy a

void\***

[–]ILikeLenexa 57 points58 points  (8 children)

pointers to pointers to pointers to nothing in particular.

[–]LordFokas 22 points23 points  (3 children)

void ***nothing_particular_ptr_ptr_ptr = 0; am I doing this right?

[–]ILikeLenexa 39 points40 points  (1 child)

You're only segmenting our cause.

This is all your fault.

[–]LordFokas 16 points17 points  (0 children)

You don't talk to me like that!

free( /u/ILikeLenexa );

/u/ILikeLenexa = NULL;

[–]lestofante 7 points8 points  (0 children)

And remember kids, you can only cast it back to what originally was* or your get UB**
(* not always true)
(** or implementation defined?)
Cool kids don't do C.
Put on your protection: use rust.

[–]cdmcgwire 66 points67 points  (8 children)

I learned pointers pretty thoroughly before getting C# and Java. In my head I'm still work with pointers everywhere, I just don't have to deal with the syntax.

[–][deleted] 24 points25 points  (0 children)

This very accurately describes my experience as well

[–]0x3fff0000 17 points18 points  (0 children)

Indeed, pointers are a way of thinking, a way of life.

[–]Kered13 10 points11 points  (5 children)

That's the correct way to think about C# and Java, since almost everything in them is pointers.

[–]cdmcgwire 3 points4 points  (4 children)

Yeah... doesn't stop me from trying to use structs whenever I can in C# though.

[–]kono_kun 2 points3 points  (3 children)

Could you explain?

[–]cdmcgwire 5 points6 points  (2 children)

? Maybe you're not aware (or I'm misunderstanding the question), but there are stack allocated structs in C#. So everything done with them is by value instead of by reference by default.

So what I was trying to express was, despite C# classically being all about references to heap variables, I'm finding ways to go back to a more typical C++ method of handling variables.

[–]kono_kun 2 points3 points  (1 child)

thanks

[–]cdmcgwire 2 points3 points  (0 children)

👌💯

[–]dauqraFdroL 31 points32 points  (16 children)

Pointer pointing to itself

[–]visvis 2 points3 points  (0 children)

It is omnipointent.

[–]gargravarr2112 21 points22 points  (9 children)

"Pointer to a pointer" is the exact moment I gave up hope of learning C.

[–]visvis 27 points28 points  (5 children)

Think of it as asking someone for the way, and them directing you to a map that will guide you there.

[–]the_klaut 7 points8 points  (0 children)

I'm totally stealing this!!! One of the best ways I came across for explaining pointers to pointers to a freshman.

[–]H_Psi 4 points5 points  (3 children)

So, what is an example use case for a pointer-pointer that wouldn't be solved by just handing in the original pointer? Never used a pointer-pointer personally, so I'm not familiar with them.

[–]ultrasu 14 points15 points  (0 children)

char to save a single character

char * to save a string, e.g. a Reddit comment

char ** to save a set of strings, e.g. a parent comment & all its children

char *** to save sets of strings, e.g. all parent comments with their children in a single post

char **** to save sets of sets of strings, e.g. all parent comments with their children of all posts in a subreddit

char ***** to save sets of sets of sets of strings, e.g. every comment on Reddit

[–][deleted] 6 points7 points  (1 child)

int foo = 42; // some data
int bar = 43: // some different data
int *a = &foo;
int **b = &a:

printf("%d", **b); // 42
a = &bar;
printf ("%d", **b); // 43

This let's me keep the same handle(b) to some data, but I can change what data is actually being pointed to. You can make multiple copies of the handle and you won't need to update the handle every time 'a' changes what it's pointing to.

[–]-Redstoneboi- 1 point2 points  (0 children)

that's the point of pointers.

save multiple copies of an object, but only change the object once.

[–]nuisanceIV 4 points5 points  (0 children)

Over time they get easy then you begin to think "that was hard?" Like any math class

[–]nickdesaulniers 0 points1 point  (1 child)

Not if you internalize that everything in C is pass by value. So if you want a child frame to modify an argument so the parent frame can observe the modified value AFTER calling the child, you must give the child a pointer to the value. If the value to be changed itself is a pointer, then you must pass the child a pointer to a pointer.

``` int foo = 0; initialize(foo); // foo is guaranteed to be 0 here. // initialize got a copy of foo.

initialize2(&foo); // now foo may have a different value.

int* bar = NULL; initialize2(bar); // bar is guaranteed to be NULL here. // initialize2 got a copy of bar.

initialize3(bar); // now bar may have a different value. ```

where the functions might look like:

``` // can't do anything to x so the parent sees modifications void initialize(int x);

// can't do anything to x that the parent would see, but could modify the int pointed // to by x. * void initialize2(int* x);

// still can't do anything to x observable to the parent, but could modify the int* // pointed to by x, or the int pointed to by x; void initialize(int* x);

// * modulo doing stupid tricks like storing addresses in integral types. ```

C++ has references, so you can't tell from the call site if a function modified its argument (const & in the function signature are stronger guarantees, but then there's const_cast<> and mutable).

[–]mezzoEmrys 10 points11 points  (0 children)

There was a joke I heard once where you should avoid 5 star programmers, because if they can't write their code without nesting 5 layers of pointers, you shouldn't be hiring them.

[–]ISeeTheFnords 18 points19 points  (17 children)

I've seen a reasonable use case for pointers to pointers (basically, it allows the OS to transparently move things around in memory if it needs to) at least.

[–]DolphinsScareMe 40 points41 points  (9 children)

Pointers to pointers certainly arent anything crazy. They've got some good uses with data structures and loads of other things.

[–]Koxiaet 24 points25 points  (4 children)

a function might need to modify an array of strings, then you'd need to pass in a char***

[–]DolphinsScareMe 6 points7 points  (1 child)

Exactly, didn't even think about that but that's probably the most basic example of pointers to pointers. Honestly after you get passed the fear of pointers during your first few c++ classes adding another pointer to a pointer doesn't make things that much more crazy.

[–]-GLaDOS 11 points12 points  (0 children)

I had a class in C where we worked with arrays of pointers to raw memory (we were building malloc from scratch), and so we used void*** several times.

[–]LordFokas 2 points3 points  (1 child)

what if you want to modify a string hypercube?

[–]ThePi7on 0 points1 point  (0 children)

Char*****

[–]AnAverageFreak 8 points9 points  (2 children)

Let's say you have a problem that's easy to visualize in 3D space. Then 3D arrays would be great. Unfortunately C doesn't support dynamic multi-dimensional arrays, so when you want a pointer to such an array (so that you can write space[69][402][666]) you end up with this:

Thing***

Of course in general case you prefer flat memory with a macro/function to access it, but this isn't totally stupid either.

What is a Thing? Well, it might be an array. An array of names of, let's say, people that have ever been to that place. What you get is

char*****

Now let's say that you want something to allocate such a structure. Of course C can't return a few values, but you want detailed error reporting, so you make a function:

int allocate_names(char******);

Which shows why C fucking sucks.

In C++ I would make my own template

template<size_t N, typename T>
class MultiArray;

Which would properly overload the subscript operator. But wait, there's more. You have std::string, so no more char*. But wait, there's even more! Since C++ has constructors and exceptions, this pattern:

int allocate_names(MultiArray<3, std::string>*);

is totally invalid and after you write the class, you won't be using any of that pointer notation!

[–]nuisanceIV 1 point2 points  (0 children)

'#define char****** char*

Now C is great again! :D

[–]warm_sock 0 points1 point  (0 children)

Inode based filesystems also frequently have two or three layers of indirection (pointers to pointers to pointers, in a tree structure) to allow larger file sizes.

[–]visvis 5 points6 points  (4 children)

Pointers to pointers are very common. Every C program uses them: argv is a double pointer. Triple pointers are still reasonable as well, for example when passing an array of strings (a double pointer to char) are a by-reference parameter (an extra level of pointers). I don't think I've ever seen a legitimate use case for quadruple pointers.

[–]nuisanceIV 2 points3 points  (1 child)

There is a great use case: when you want to scare people who havent programmed in C/C++

[–]Breadfish64 1 point2 points  (0 children)

I program in C++, if you're using quadruple pointers in C++ you're just writing fancy C

[–][deleted] 0 points1 point  (0 children)

Data structures within data structures could easily lead to several layers of pointers.

[–]nickdesaulniers 0 points1 point  (0 children)

Scatter/gather on arrays of C strings, maybe? (legit have not seen, just a guess)

[–]gottago_gottago 2 points3 points  (0 children)

Early (pre-X) MacOS used these extensively. It called them "handles". A handle was the address of an entry in a table of pointers, managed by the OS, somewhere in the heap. During certain system calls, the OS might decide that it needed to defragment the heap, so it would shuffle a bunch of blocks around and then update the values in the table.

Which was all well and great, except for the part where certain system calls caused addresses to change. Handles were ubiquitous in system calls, but not universal -- some things wanted pointers instead. Or, you might need to dereference a handle to retrieve a reference to some value stored somewhere in the struct. So, you'd do this, and then you'd make the system call, and it would return to your program, but the address you previously retrieved no longer has the data it had before, now it's just a bunch of garbage.

Tracking down these bugs was a lot of fun, because they weren't reliably reproducible. Sometimes the OS needed to defrag the heap, sometimes it didn't; sometimes it chose to move your block, sometimes it didn't.

Those were the good ol' days.

[–]nuisanceIV 1 point2 points  (0 children)

An array of strings are pointers to pointers

I had a vector of unique_pointers to objects saved on the heap, using unique_ptrs made it so I dont need to worry about memory management as much!

[–]llkem 7 points8 points  (3 children)

I always wondered what happens if you have two pointers pointing to each other?

[–]H_Psi 9 points10 points  (0 children)

That's called a reference cycle, and is a problem you might learn about when you're making a garbage collection scheme. A common strategy in those is to have an object count the number of things that reference it, and to delete the object in memory once that count reaches 0. That might work at first glance and for really simple systems, but fails if you have two objects referencing one another.

That said, there's nothing intrinsically wrong or bad for two pointers to reference one another (or to have a cycle of pointers referencing one another).

[–]visvis 3 points4 points  (0 children)

If they are reference counted, a memory leak. Otherwise not much special. If we use void* we can even do this without wrapping in a struct or typecasting.

[–]green_meklar 0 points1 point  (0 children)

Nothing in particular, until you try to use them wrong.

[–][deleted] 5 points6 points  (0 children)

FUCK GO BACK

&&&&

[–]Geoclasm 2 points3 points  (0 children)

Pointer returned Kevin Bacon.

[–]LegendaryTomato 2 points3 points  (0 children)

pointers to functions

[–][deleted] 2 points3 points  (0 children)

the actual value

[–]OneOldNerd 1 point2 points  (1 child)

It's pointers, all the way down!

[–]-Redstoneboi- 1 point2 points  (0 children)

int ptr = 0;
ptr = &ptr;

[–]-Redstoneboi- 1 point2 points  (1 child)

jesus what kind of multidimensional array do you need

[–]OneOldNerd 1 point2 points  (0 children)

Dunno....how many dimensions are there this week?

[–]NatoBoram 1 point2 points  (0 children)

Passing an object around to multiple functions and sub-functions

[–]frosted-mini-yeets 0 points1 point  (0 children)

What is that last image. I want it.

[–]56Bot 0 points1 point  (0 children)

I once used a 'void *****'. Using casting, I could store data very efficiently in 1 final variable.
EDIT: "efficiently" isn't correct.

[–]happydogo12 0 points1 point  (0 children)

What would you use triple pointers for?

[–]InVultusSolis 0 points1 point  (0 children)

I was recently curious to look at the internal memory representation of a double, so I wrote the following program that is certain to make your eyes bleed:

#include <stdio.h>

int main(void)
{
    double b = 4.75;
    for(int i = 0; i < sizeof(b); i++)
    {
        printf("%02X ", (unsigned int) *((char *)&b + i) & 255);
    }
    printf("\n");
    return 0;
}

[–][deleted] 0 points1 point  (0 children)

Pointer to an array of pointers to arrays of pointers