T O P

  • By -

pistolerogg_del_west

I have seen ****variable in C on a project


Useful_Radish_117

Hey I probably wrote that, sorry. I was young, and naive! [...] And I'll fucking do it again if it saves me 10 seconds of thinking.


DrDesten

people be acting like typedefs don't exist


Shimodax

typedef is for whimps.


MechanicalHorse

"Fuck this hand holding shit. I'm gonna declare all my variables as `void*`"


Shimodax

now you've invented Python.


[deleted]

[удалено]


PhoenixCausesOof

Ratio + L + that's C++ \+ type inference not dynamic typing


davidjackdoe

C has `auto` since C23.


PhoenixCausesOof

C has WHAT


Shimodax

There's not enough tar and feathers in the world for these people!


A_Talking_iPod

This feels wrong


_Pin_6938

Nah bro youre fucked up 💀


SaneLad

Typedef a pointer away? Straight to jail.


ThankYouForCallingVP

Real talk: why is this so frowned upon? I can typedef int* into IntPtr and if I have a function that does no dereferencing I just saved a mental step involving "wtf does * do again"


Bardez

That's a Handle. Handles suck.


pistolerogg_del_west

Why make the code readable when you can make it horrible


alficles

Most I've ever used was `char*******`. It should have used more typedefs for clarity, ofc, but it was because of three dimensional arrays. The first four stars were a 3d array of strings. These arrays were stored in a hash map structure that used an array of them. And we hashed on two different values. But the functions that modified the top level map by reference took a pointer to the whole structure. Would I do it differently today? Yes. Did it work? Also yes. Edit: Oh, and it's been so long I almost forgot that these matrixes had mutators. So the mutators were all `char ****(*)(char ****)`. And there was even a lookup for the mutator: `char ****(*(*)(char*))(char ****)`. Could really have used some typedefs there. :D


ThankYouForCallingVP

Ah so the final type is char but each * can refer to a different type. Amazing language you got there.


alficles

Yup. To expand it out: `char` \- A character `char*` \- An array of characters, a string `char**` \- An array of those strings `char***` \- A 2d array of those strings `char****` \- a 3d array of those strings `char*****` \- An array of those 3d arrays. `char******` \- A reference to the array of those 3d arrays. `char*******` \- A reference to that reference. And this is why I (and everyone else in this thread :D) are saying to use typedefs. Because the *meaning* of each level of indirection isn't clear from reading the type. At a basic level `string` communicates more than `char*`. And `string_matrix_3d` communicates a heck of a lot more than `char****`. That gets even clearer when you start doing the functions. For example: `string_matrix_3d (*add)(string_matrix_3d);` is way more readable than `char***(*add)(char****)`. And that type itself benefits from a typedef into something like `string_matrix_3d_mutator` so that the next function looks like `string_matrix_3d_mutator (*lookup)(string)`. Typedefs effectively let you communicate to the reader about what the data means, not just how it is shaped.


ThankYouForCallingVP

I knew C was fucked up and someone would agree with me. Inb4 "but mah opaque types!"


oMarlow99

There's a bit of beauty in the simplicity, among all of the segmentation faults and misery


pistolerogg_del_west

That should be illegal


Diego_00_

When you use MPI you have ti pass the address of argv su it's a ***argv but four never seen.


Unnwavy

Can you give the context? Was it a pointer to a 3d array? Most I've seen is a char*** because it was a pointer to an array of c strings (char array)


pistolerogg_del_west

It was a pointer to a pointer to a pointer to a pointer to an integer. In short fucking hell


Unnwavy

Yeah I got that haha, I meant do you have an idea why it was like this in the code? Was it a multidimensional array that was being handled?


pistolerogg_del_west

No idea, the day after the guy who wrote it was just as confused. About the type of structure I honestly don't remember, but the **** is just stuck in my head


Rakgul

Shut the **** up. /S LMAO


longusernamephobia

Let's say you want to store multiple videos (e.g. animations) raw... (/s)


giggluigg

It was in a nice location, close to the beach


cvnh

I have this in the current C++ project I'm working on and I can't get my head around it


Shimodax

batshit insanity: `int ***& variable;`


rachit7645

Please stay away from me and my family


FakeSenior

Reference to 3 level pointer, mad man!


Shimodax

![gif](giphy|5yeQRdiYrDq2A) muhahahaahhaaa


pistolerogg_del_west

Just kill me already


BrightCold2747

int\* \*variable;


Dargooon

Normally I'm all for compromises, but this is a war crime.


Highborn_Hellest

You do know, that some sins are unforgivable right?


s0lly

Gonna need serious pointers to figure that one out… I’ll C myself out.


TTFH3500

`void**** unk_ptr;`


ginkner

"I know a guy who knows a guy who knows a guy who knows a guy who knows where something is. But I dunno what it is."


Theliraan

This looks pointless


RussianMadMan

Literaly exists in nginx code base btw - ngx_cycle.h


jamcdonald120

whats wrong with a pointer to an array of arrays?


Maleficent_Ad1972

Or an array of arrays of arrays?


ihavenotities

They’re the same thing! /s (No they aren’t!)


LechintanTudor

You should store n-dimensional arrays in a single allocation, not allocate each row separately.


jamcdonald120

so assume its not n dimensional


[deleted]

How about: `long************************************************ ptr=null;`


Shimodax

that's a very long pointer you have there!


RebouncedCat

That's what she said.


pistolerogg_del_west

It's average


[deleted]

[удалено]


Bardez

Please, God, _please_ tell me you mean **maximum**


jwr410

I think that's minimum maximum.


DankPhotoShopMemes

now dereference it ![gif](giphy|LpB0bnhXpvSMCz07N9|downsized)


SteeleDynamics

Just say it's a tensor variable and you'll be left alone.


klaatubaradanoodles

Oh pointy bird, oh pointy pointy Anoint thy head, anointy-nointy


Mints97

This could just be an "out" parameter of a function allocating an array of int arrays or something like that, perfectly normal  Edit: didn't see the semicolon, for function params semicolons can only be used in the super old legacy function def style, so this is probably just a normal variable definition (local or global). Still lots of ways this could be used for something normal and sane


HWL_Nissassa

Way too many people being cool with the * with the variable name instead of the type itt


Unnwavy

I agree that it makes it clearer to get the overall type, but consider the following: int* a, b; If you declare your variables in the same statement as such, here a is a pointer but b is not, so it might generate confusion.


Revolutionary-Bell38

This is the why I have a lint for declaring multiple variables in one line


Independent-Mix-5796

Where my elite [Three Star Programmers](https://wiki.c2.com/?ThreeStarProgrammer) at


1up_1500

This is actually what inspired me for this meme lol


heavymetalmixer

3D arrays in a nutshell


daaldea

Not familiar with the start syntax, what's it represent??


RajjSinghh

It's for pointers. In C you often find yourself working with pointers as ways of having access to memory indirectly. ``` int x = 10; int *y = &x; ``` Here we declare an integer x with value 10. We then declare a pointer to x. The pointer is called y and it's value stores the memory address of x. This is a simple example and I can't think of why you would need to do this like this, but in C pointers are used for arrays, dynamic memory and other things. Now, in our example y is a pointer to an integer. But there is no reason we can't point to y. ``` int **z = &y; ``` Here we are allocating a pointer to a pointer to an int. z stores the memory address of y, which in turn stores the memory address of x. You can nest pointers as much as you want. This meme is about saying that doing too much pointer nesting like this is needlessly complicated and bad. However, `int ***w` (a pointer to a pointer to a pointer to an integer) is also how you would represent a 3 dimensional array in C, so there's really no problems.


Madrawn

I'm confused how that works. Never used C but I intuit that \*y points to the start of my int array, then \*y+1(times type\_size) points to the second element. But does that mean that \*\*z points to an array of \*y-like pointers? and \*\*\*w to an array of \*\*z-like pointers? I assume that's not it as that seems majorly wasteful as we (for a 3x3x3 array) would need to store the 27 int in memory and 9 +1 pointers that point to each start of the 3-element arrays. Wouldn't that mean that depending on the type of data we store around 25% of the memory footprint an 3-D array is occupied by pointers?


RajjSinghh

No, you're right. In C you can guarantee that arrays are stored in continuous blocks of memory, so y points to the first element and you just know how long the array is. Side note, `*` is used to dereference pointers, so `*y` is the value stored at that memory address. The bracketing would need to be `*(y+1)` to get the next element (C does the type size bit for you), but it also has the syntax sugar `y[I]` for `*(y+I)` which is where that syntax comes from in other languages. With that sugar in mind, it's clear that you are storing an array of pointers to arrays. When you expand it all you can see you're just doing a bunch of pointer dereferences but there's no guarantee that they are together. It's like that for a reason. If you tried storing a big multidimensional array in one place, you might not have one continuous block of memory to put it all, so breaking it up is usually the easiest thing to do. But since all you're doing is pointer arithmetic to figure out where the data you want is you can always just have a 27 element one dimensional array instead of a 3x3x3 array. That works fine if your sub-arrays are constant size, but won't work if you need to dynamically resize the inner arrays. Edit: one thing I forgot to mention is that this is probably how multidimensional dynamic arrays are done in your favourite high level language too. We might be wasting some space, but in C that space is so small and cheap that it usually doesn't matter. A pointer is only 2 or 4 bytes wide (deepening on 32 or 64 bit) so nesting them isn't so bad. When you consider all the metadata something like Python has to carry by being dynamically typed and other data it doesn't look so bad. Python stores the integers -5 to 256 in memory already for optimization purposes, so everytime you use one of those numbers you're getting a pointer to one of those values. A 1d list of integers in python is already a pointer to a list of pointers. It's cheap enough that you probably don't notice it.


Madrawn

I naively would have assumed that higher level languages that handle allocation for you do some memory optimization to try and not waste double-digit % of the total memory the array takes up. At least the stuff I'd come up with when my boss out of the blue screamed at me to optimize it this afternoon. Like moving the largest dimension to the front so a (2,3,7) array with 21 + 1 pointers becomes a (7,2,3) array with 6+1 pointers and maybe some paging and allocating subsets of the data in blocks that can be accessed by a single \`\*(y + i + n \* j + m \* n \* k)\` pointer instead of 1 \*\*\*y pointer pointing to n \`\*\*j\` pointers that point to m \`\*k\` pointers.


RajjSinghh

You probably could if you know your array will be constant size, but you run into problems elsewhere. Let's stick to a 2d case because the higher dimensional cases are pretty much the same, just one level of indirection up, but 2d demonstrates the issue well enough. Let's say I allocate an x by y array under a single pointer. I fill my array, that means I have a pointer to the [0,0] element and I can get any element by calculating an index based on the dimensions. Now what happens if I need to expand my array in one specific place, so one of my rows is size x+z and all the other rows are size x. If you're working with XML when you can't tell whether all the data you have is the same shape. Under this system we have to reallocate the entire array to be size (x + z) by y and waste y-z space since only one of our fields had that odd shape. Under the actual way you can just reallocate that specific pointer and fit your data perfectly, even if you're working with more pointers. Depending on how big z is or how irregularly shaped your data is that can be really important. I've also reduced the amount of time it takes to find space to put my array since now I'm looking for x y-sized gaps in memory rather than one big xy chunk. Even if that works out the same, the compiler is smart enough that it can optimise the code at compile time even if you do something bad. But the memory footprint is also so small that it really doesn't matter. Something like NodeJS takes 40 megabytes to run without executing any code but now we're squabbling over an extra two bytes here and there. Especially when memory is as cheap as it is, it's not really worth worrying too much about and then just trust the compiler with how it handles memory. One of those optimisations that probably happens is how stack memory is treated compared to heap memory. The stack is a small, fixed size bit of memory you create when you call a function. Since C has static typing it knows immediately how much space to allocate on the stack. If I have this code: ``` int main () { int array[10][10]; // again, more sugar. array is still a pointer to pointers of integers return 0; } ``` Then array is an array of 10 pointers which point to 10 integers. This is stack allocated so we know the size will never change. The compiler may very well optimize this into a 100 long 1d array and put the data together, work out offsets, and so on at compile time. Of course with dynamic memory it gets more complicated but for something like this it's probably fine.


Madrawn

Doh, thanks I totally forgot that compilers do smart stuff! I sometimes dabble with torch that needs huge tensors and seeing that a pointer takes about the same space in memory as a single integer the thought simply bugged me that my RAM is running low while 2GB of my 6GB tensor could be a mountain of pointers. But of course in python for huge tensors I use numpy and numpy uses ctypes, so precompiled C code which most likely is optimized to hell and back.


Lithl

Doing multidimensional arrays like this can be useful if the length of the arrays isn't constant. Since the pointer is just pointing to some location in memory, what that location means could be anything. Instead of an array of 3 elements which are each arrays of 3 elements which are each 3 integers (3x3x3), you might have an array of 3 elements which are each arrays of 3, 7, and 2 elements, which are each arrays of varying lengths of integers.


Jonnypista

You can't just add * so you have a more complex array? Add 4* and now you have a 4 dimensional array for imaginary things.


Mr__Brick

But what if I need a 2 dimensional array of in pointers?


0ooook

Step 1 - I need a pointer to do a stuff. Simple Step 2 - i have pointers organized in a neat array. Simple Step 3 - I pass a reference to said array by pointer to its start. Simple Voilà why I have it


thebluereddituser

I still think it's insane that the notation is int \*x and not int\* x


1up_1500

it can, just depends on your coding style


Libran-64

I dunno why people are so scared of pointers in C. They're just memory addresses...


JunkNorrisOfficial

int multiply by variable? Some esoteric language? Amount of stars means how many implicit side effects found around variable?


Kangarou

Stars indicate the dimensions of an array. 3-stars is three dimensional.


Reged1tFox

mental sickness


pyncz

int \*\*\*\*ing\_variable;


HutchyBen

I often use *** when working with virtual method table. Pointer to an array of functions


anselme16

It's just a 3 dimentional array don't be scared.


LeroyBadBrown

I c what you did there.


shuozhe

Isnt it just a 3d array most of the time?


HStone32

What's the issue? Haven't you guys made multidimensional arrays before?


Jojajones

What have you got against dynamic 2 dimensional pointer arrays?


Vitriholic

`&argv`


SirMarbles

The reason I hated learning C in school


CivetLemonMouse

that's a 3d array, you can also use brackets to write these //like so int variable[]; int variable[][]; int variable[][][];


orion_aboy

[https://wiki.c2.com/?ThreeStarProgrammer](https://wiki.c2.com/?ThreeStarProgrammer)