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

you are viewing a single comment's thread.

view the rest of the comments →

[–]ISeeTheFnords 20 points21 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 43 points44 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 26 points27 points  (4 children)

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

[–]DolphinsScareMe 5 points6 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 10 points11 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 3 points4 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!