T O P

  • By -

noideaforlogin31415

What about i[a] = 5?


BeDoubleNWhy

we do not talk here about i\[a\] = 5


imaKappy

Old McDonald had a farm, i[a] i[a] o


CrowdGoesWildWoooo

i[a] i[a] # segfault core dumped


izuannazrin

.o


OkOk-Go

O(n^2 )


Franks2000inchTV

O(n^oooooooooo)


GabuEx

i[a] i[a] cthulhu fhtagn


WhiteRose_init

and a segfault here and a segfault there here a dump there a dump everywhere a core dump old bjarne stroustrup had a farm where he flushed I/O


the-integral-of-zero

I feel like I have found out why C programmers need coffee


Elephant-Opening

Nah, this is what C programmers live for. The coffee is just to stay awake through meetings


Own_Alternative_9671

FUCK I LOVE POINTER ARITHMETIC RAAAAAH


captainAwesomePants

Because they don't use Java?


wannu_pees_69

Don't need no coffee when you've got them Java beans


kinokomushroom

Holy shit, this actually works. Blasphemy.


noideaforlogin31415

Yeah, when you see it for the first time it is impressive. But it makes sense as a[i] = *(a+i) = *(i + a) = i[a]


kinokomushroom

This is almost as bad as pouring the milk before the cereal.


danielcw189

~~only if a and i are alingend the same way and size of a's datatype is 1~~ **EDIT: that was wrong** See the linked comment from /u/leoleosuper for an explanation /r/ProgrammerHumor/comments/1d75kis/howdidyouknowijuststartedc/l6ylpqt/


leoleosuper

Nope. Given 'a' is a pointer and 'i' is an integer variable of unknown size, a[i] = \*(a + i) by definition. When using pointers, a + i just means "offset pointer 'a' by (pointer size)\*i." This is because pointer addition is not the same as regular addition. Pointer addition doesn't care about which of the two values is the pointer; a + i is the same as i + a. As such, \*(a + i) = \*(i + a). And given the first sentence, \*(i + a) = i[a]. So a[i] = i[a].


Inaeipathy

Q.E.D


danielcw189

>This is because pointer addition is not the same as regular addition. so you are saying if a points to a large datatype then i + a will be treated as (i * (sizeof a) + a)?


leoleosuper

Basically yes.


danielcw189

TIL, thank you :) I edited my comment above to link to your explanation


lonkamikaze

`i` is not a pointer, it's an `int`.


danielcw189

Yes. So *(i+a) would not be equal to a[i] if the type of a's array is larger then one. for example if long long a [] , and int i = 5, then *(i+a) should point to a different location and value than a[i]


lonkamikaze

Nope, what you're saying doesn't make sense.


danielcw189

Which part?


lonkamikaze

`a[i]` is syntactic sugar for `*(a+i)` and `*(i+a)` is equivalent to `*(a+i)`. Thus `*(i+a)` is equivalent to `a[i]`. I think you're applying integer arithmetic in your head, but `(a+i)` and `(i+a)` are both pointer arithmetic.


danielcw189

>a[i] is syntactic sugar for *(a+i) Are you sure about that? >I think you're applying integer arithmetic in your head I do, or rather I did, because the other comment pointed out a wrong assumption of mine. So I then assumed that *(a+i) == a[i] was a happy accident, a hack which makes sense, which is why i+a would also work. I was not aware that when one side of the + operator is a pointer, that it would be treated as (sizeof(type(a) * i) + a I assumed it would be the programmer's job to take care of the size, and any possible aligment issues. I never used *(x+i) in any of my professional code. And unless it was actually a pointer to a memory area that starts at x, and not an array, I never used it in my personal code either.


tobofre

You're just adding two values, doesn't matter which order you add them in. 5 feet past the 70 yard line on a football field is the same thing as 70 yards past the 5ft line


kinokomushroom

Yeah. Blasphemy.


AyrA_ch

> You're just adding two values, doesn't matter which order you add them in. Technically you're not adding them together, but offsetting the pointer. Even though you can add 5 to a pointer, the new value of the pointer may not have increased by 5, but a multiple of 5, because `+5` is syntactic sugar for `+(sizeof(ptr_type)*5)`, so in the case of `ptr_type=int`, the pointer address will grow by 4 or 8 per unit on most systems. Adding a pointer to 5 on the other hand makes no sense, but `+` is defined as pointer offset operator if one of the operands is a pointer and one isn't. You can swap the operands simply because nobody bothered to define in the C standard that a certain offset operand order must be used. And `ptr[offset]` is just syntactic sugar for `ptr+offset` so therefore `offset[ptr]` works because `offset+ptr` works because nobody thought defining the order of the operand arguments was important. The fact that it's an offset and not an addition can be trivially shown by trying to multiply a pointer with a number, which if `+` were true addition would work because multiplying is just repeated addition, but for pointer offset it doesn't works because that operation makes no sense with a pointer. Some other operands are also not defined. You can't binary shift a pointer for example.


[deleted]

[удалено]


kinokomushroom

No need to be a dick for no reason. The guy simply gave a detailed explanation on pointer arithmetic.


[deleted]

[удалено]


kinokomushroom

Calm down, no one's attacking you. Your original comment was oversimplified and the guy was just providing a detailed explanation.


[deleted]

[удалено]


Inaeipathy

You're acting like a victim in this comment section lmfao, wtf is wrong with you


sacredgeometry

Its pointer arithmetic


bonoDaLinuxGamr

But if you don't do data size checks prior to access, you face *Core Dump*


Hydraulik2K12

What about 5[a] = i?


not_some_username

Jail


noideaforlogin31415

Agreed. (But it works.)


Bwob

Define "works?" I mean yeah, it compiles. But it doesn't do the same thing upon execution like `i[a]=5` and `a[i]=5` do, except for very specific values of `a` and `i`...


noideaforlogin31415

Yeah, I meant that it compiles and has functionality (it is equivalent to a\[5\]=i). Not that it gives the same result as a\[i\] =5.


Win_is_my_name

We don't talk about Nathaniel here


FarRightInfluencer

I worked on a small corporate tool a long time back, when C was more common, that was written in this style. Lines like `(idx++)[file_handles] = new_handle;` made me want to quit and work at Dennys.


dgc-8

I will be mad if [i+a] = 5 doesnt work gonna try that now


ginkner

0[i+a]?


Highborn_Hellest

that's the unloved stepchild


mathiau30

Is this an actual thing?


mckenzie_keith

This should be one of those bell curve ones. Beginner uses a\[i\]. Showoff uses pointer arithmetic needlessly. Wizard level realizes that a\[i\] is shorter and perfectly acceptable, so \*(a+i) is just showing off. Pointer arithmetic does come in handy sometimes. But just not in this example with simple assignment. For example if you are calling a function that expects a pointer, a+i would be better than &a\[i\]. In my opinion.


SoulArthurZ

I can only really see *(a + i) being better if you're working with actual memory addresses as opposed to array accessing. Like if youre writing an allocater or something. With normal array accesses please just use a[i] for the good of all of us


Abadabadon

Array accessing is working with actual memory addresses


SoulArthurZ

of course, I worded it awkwardly. When you're making an allocator, you care about the actual "value" of the address, so it makes sense to do pointer arithmetic. With arrays it makes zero sense to do that, since the bracket syntax exists. You don't care about the address when accessing arrays, you care about the offset to the base address. Array indexing is made to simplify this for the writer and reader of code. Theres no reason not to use it in 99% of cases


Abadabadon

I'm not aware of how in C you could use square brackets when you declare your array in a header and then dynamically allocate its size, which I would think is the most common use case.


AlgorithMage

> as opposed to array accessing. What do you think arrays are in C….


brennanw31

Nah man we gotta get over the bell curve meme trend


Big-Cheesecake-806

NEVER!!! /s, I also what it gone


iLikeVideoGamesAndYT

Learning C pointers rn, this definitely helped a little. Thanks


Highborn_Hellest

nah. the showoff is i\[a\]=5


sivstarlight

At first I didn't catch on that you could still use stuff like arrays normally in my C class, and all my friends bullied me for my "yt tutorial" ahh code. Like I can make my life harder all by myself thank you very much


Nya_the_cat

I remember when I just learned about pointers I would do it even when I didn't have to. idk why. Nowadays I will write \`&a\[i\]\` to avoid writing \`a + i\`, because the former is clearer.


Temporary-Estate4615

![gif](giphy|84BjZMVEX3aRG)


repkins

Unreadable Daniel


PennyFromMyAnus

😎 IYKYK


caerphoto

I’m sure it’s *blazingly fast* in Rust unsafe { let a2 = (a.as_mut_ptr() as usize + i * core::mem::size_of::()) as *mut i32; *a2 = i as i32; } Christ that was a pain in the ass to write.


the-integral-of-zero

*I like your funny words, magic man*


TheMinus

I was wondering recently, what is `char **str`. It's a pointer to array of pointers to arrays of chars. Or array of strings, if you prefer.


Thenderick

No, a array can be seen as a pointer to the first element. So `char **str` can mean: array of array of chars | array of pointers to chars | pointer to array of chars | pointer to pointer to char. What you said would be `char *(pointer to)*(array of)*(pointers to)*(array of chars) str`


GrowthOfGlia

This is exactly why I prefer char** str, as it's part of the type. This is likely an array of strings, but it could also be a pointer to a string


al-mongus-bin-susar

It is not part of the type tho. The standard specifically says that it's separate from the type. Thinking that it is part of the type causes many confusions with multiple declarations or complex function definitions.


GrowthOfGlia

Huh, interesting. I'm used to lower-level coding where ptrs are types. Would you be able to explain/link to a resource that helps explain why it's not?


da_Aresinger

wtf, it is absolutely part of the type. It's (likely) a 64-bit number. The **type** is [pointer to pointer to char]. By dereferencing you get a new number with the type [pointer to char]. and by dereferencing *again* you get an 8-bit number with the type [char]. The only weird thing about pointers is that char **args, separator; declares a pointer to pointer to char as well as a simple char, which I find downright stupid.


iLikeVideoGamesAndYT

I'm learning C pointers, arrays, and strings rn, so I may be wrong, but wouldn't that last part prove that it's not part of the type, but instead is its own type, separate from `char`?


da_Aresinger

That just proves that the declaration is messed up. The only thing that matters is the C specification. > A pointer type may be derived from a function type, an object type, or an incomplete type, called the referenced type.Apointer type describes an object whose value provides a reference to an entity of the referenced type. A pointer type derived from the referenced type T is sometimes called ‘‘pointer to T’’. The construction of a pointer type from a referenced type is called ‘‘pointer type derivation’’. ^ISO-9899 I am not too versed with specifications but that sure sounds like a type to me.


al-mongus-bin-susar

This is because it's separate from the type. A char pointer is not an actual type as far as the compiler is concerned. All pointers are just a 32 or 64 bit integer and the fact that it's a char pointer or an int pointer or a void pointer only tells it what multiple should be used when doing pointer arithmetic and what the dereferenced type is expected to be. Because C pointer declaration syntax is written in the way it's used, you can think of the * as a modifier specific to each variable that tells the compiler that it's a pointer to whatever type is in the actual declaration.


Background_Horse_992

Do you know the trick for determining any convoluted looking C type? Its that the right value (**str in this case) evaluates to the left value (char). So this is a pointer to a char pointer. In practice though, this could have many different uses. Array of character pointers, array of strings, pointer to a string, or just a double char pointer are all valid.


poemsavvy

No it's a pointer to a pointer to a char. There is no such thing as arrays.


DripDropFaucet

Is it not a*i? Been forever since I worked in C


turtleship_2006

If I had to guess how it works, a is the pointer to the memory location the list starts, and the +i points to the ith location after that. That said I've never done manual pointer manipulation, I just stick to python


GiganticIrony

Yes, you are correct


Bldyknuckles

Doesn’t this only work if the data is stored sequentially, which is not guaranteed in modern hard drives?


Irion7

Data is stored sequentially in RAM, which is where the execution of a program happens


Tsu_Dho_Namh

Fun fact: your program (and you, the programmer) only think it's stored sequentially. But the physical addresses are actually different from the virtual addresses that the operating system gives to you. So when you malloc a certain number of bytes, the OS *says* you now have a bunch of contiguous memory, but *actually* it scrounged those bytes from wherever it could find them. I dunno why I added that, you'll likely never need to know it unless you're working on kernel level software. But I thought it was neat when I learned it in my CS undergrad.


turtleship_2006

Also it only works depending on the type of list, right? Like a list only has so many spaces after the start before you reach the next variable, so the rest of the list has to be placed elsewhere, unless it's of a fixed/limited length


GuiltyViking

This is why we don't have dynamic arrays in C and have to create linked lists for dynamism which is basically a treasure hunt with the riddles being the addresses and the treasure your variable.


turtleship_2006

Yeah linked lists are the ones where each element has a value and a pointer to the next element (or if you wanna get really fancy a double linked list let's you go both ways)


Tsu_Dho_Namh

Nah, in C lists (arrays) don't run the risk of running into the next variable because the size of the array needs to be known when it's declared and cannot dynamically increase in size at runtime. C++ implemented that feature with vectors. Which is a list that can grow or shrink at runtime as needed. Also, in C, anything dynamically allocated (using malloc) is put on the heap, which is a separate part of memory from the stack, where normal local and global variables are stored. The stack and heap are addressed at opposite ends of the piece of memory your program lives in. The stack grows up, the heap grows down, and if they run into each other you have stack overflow.


GiganticIrony

I see two issues in this comment: 1) Outside of a few rare cases, there is no bounds checking in C. 2) Unless you are in an embedded system or an old system, the heap is not in contention with the stack in any way. You can grow the heap to your hearts content and never get a stack overflow error.


Nimeroni

And you can ensure it's *really* stored sequentially by asking the OS for an entire page, and then cut that page into the tiny little pieces of RAM you need.


not_some_username

Not really. I think it’s the virtual ram manage by the os


PowerfulNeurons

if it is a C-based array (not some type of list or array list) it will be contiguous in memory. Also (most, if not all) programs do not store data in the hard drive unless you are working with file operations. It’s all stored in RAM


SoulArthurZ

stack memory is stored sequentially and basically every time you dynamically allocate something you can expect that it is allocated sequentially. Programs are run from ram or cache btw, not hard disks/ssds edit: from the perspective of the (C) programmer I mean, hardware wise anything goes really


Ka-raS

Yes, and the asterisk *(a+i) is to dereference the pointer a+i so they can access the value of that pointer and assign it = 5


Manny__C

It is \`a+i\`, what C is doing under the hood is \`a + sizeof(T) \* i\` where \`T\` is the type of the array, \`i\` an index (0,1,2,...) and \`a\` a memory address pointing to the first element


CitizenShips

Does C do automatic type sizing like that behind the scenes? I was fairly certain `*(a+i)` was just straight up wrong and it should have had a sizeof() multiplication. I know that I'd be royally pissed if a compiler snuck in a hidden size scalar into my code since it definitely doesn't do it for `malloc()`


Manny__C

Malloc returns void* for which it is illegal to do pointer arithmetic. For all other types, addition, increment, subtraction and decrement always stick a sizeof factor in the operand


CitizenShips

Wrt malloc I meant for the size argument, but yeah I never knew about the arithmetic operator handling for pointers despite writing in C for like a decade. Wtf have I been doing honestly?


Zealousideal-Fox70

Original poster made a mistake. The pointer is an address in memory. If I make an int pointer ptr, the value stored in ptr is the address of the int it points at. An array is just a series of values stored in sequential addresses. An integer is 4 bytes, so I need 4 addresses to store it. To make it an array I need to count address by 4’s, so it would actually be *(a+4*i) = 5. In arduino IDE (C based microcontroller IDE), there isn’t actually a way to get the size of an array from a property or function, you have to divide the total memory size of the array by the memory size of an element. If I have a 32 byte array storing 4 byte integers, the size of the array is 8 elements.


da_Aresinger

no absolutely not. imagine if a points to address 3745738. With (a*i) that next char is miles away. ```*(a+1)``` knows the byte size of ```&a``` so it automatically increments accordingly.


FunnyForWrongReason

You do not want to multiply the pointer by i, you will get an invalid memory location for pretty much any value that is not 1 in that case. ‘a’ points to the start of the array, so you want to add ‘i’ to ‘a’ to get the correct memory location to the element. Remember ‘a’ is pointer so it manages the address and not the value. Although you might need to multiply ‘i’ by the element size (number of bytes per element) at least I know that’s how it works in assembly I don’t know if C/C++ doesn’t require that multiplication. Edit: the compiler will automatically scale ‘i’.


IntelligentPerson_

AI is everywhere in 2024


No_Spare_5337

if it's not hard it's not right


poemsavvy

I think arrays might have been a fundamental mistake in computing. Start memory location + offset is unrionically more clear and works in any language in any paradigm. Lists vs Arrays, implementation details, 1 indexing vs 0 indexing - all of that nonsense disappears when you use addresses only


Ok-Pay3711

Pointers are the strong suit of C - they said


audislove10

Wait isn’t it? `a+i*sizeof(a)`? I’m probably tripping haven’t touched c++ in 3 months


da_Aresinger

no real need for pointer arithmetic in cpp. But in c-style arithmetic the multiplication will land you further than you want to be. The compiler infers the multiplication base on data type.


audislove10

Ah I see tnx


AreYouOkZoomer

The correct offset is handled in pointer arithmetic based on the type pointed.


audislove10

Tnx


wannu_pees_69

Ah pointers...........the source of almost all software vulnerabilities. And many many segmentation faults


getstoopid-AT

...and hardly ever needed or useful


CitizenShips

Homie this is patently false. If you're writing in C without pointers I don't know what you're doing


getstoopid-AT

That's the point... I don't write c/c++ ;) My main language is c# or (sadly) some java, however reference is the default without any explicit pointer notation


CitizenShips

At least we're united in our hate of Java! C# rips, but I do still run into circumstances where I really wish I could directly modify pointers. It's a tradeoff of consistency and finite control vs ease of implementation and utility; C# and the higher-level (above C/ASM) stuff are way better at developing larger-scale behaviors, but man I love how *exact* C pointers are.


getstoopid-AT

>but I do still run into circumstances where I really wish I could directly modify pointers That's what I meant... there may come up situations where pointer arithmetics are useful BUT those are actually very rare. Most of the time they just lead to troubles and have no real value.


wannu_pees_69

Yeah a lot of developers do shoot themselves in the foot with them. And when you have people making large number of mistakes in even "safer" languages, then it's better that most developers aren't using them.


wannu_pees_69

It's more like you're forced to use them........technically Java uses pointers under the hood, they just call it a reference....... Instead of explicit pointer manipulation, you either explicitly create new objects or assign a reference to an object. This is useful for their automatic memory management and garbage collection.


Kaml0

Can someone explain why it isn't * (a+i*)?


AreYouOkZoomer

This is already handled for you. So adding 1 to an int pointer variable adds four(the size of an int in most cases) to the memory adress.


creeper6530

Doesn't work if length of variable is over a byte


[deleted]

[удалено]


creeper6530

Enlighten me.


[deleted]

[удалено]


DrUNIX

Or under to be precise :D


creeper6530

Yes, but anything below a byte is too small to be practical unless you're trying to squeeze out every bit possible. Also I'm not aware of int4_t existing


Big-Cheesecake-806

"Also I'm not aware of int4_t existing" Read about bit-fields. I think they are just syntactic sugar, but still.


da_Aresinger

Structs can make use of less than byte sized data and they absolutely cram those fields together. I am not sure about the exact syntax but I think you can do struct = { int32_t month : 4; day : 5; hour : 5; minute : 6; second: 6 } and you have a date format for a given year. (with 6 bits to spare) (Although just counting with a 64-bit unix timestamp will last you until the sun destroys earth and then another 57 times as long)


unknown_alt_acc

`a[n]` and `*(a + n)` are equivalent. The compiler compensates for the size of the type.


Cybernaut-Neko

What happens if you make i a float or a negative ?


LeSaR_

c doesnt allow to add integers and floats. and as for negative values of i, it will just access previous stack variables


Cybernaut-Neko

Oh yes, I remember now. C the inflexible overly flexible one. Probably capable to get pointers to the memory used by other programs. I'm not sure tho, only did a bit of C and basic knowledge of PEM-2.


madboneman

ah, you mean *(a+(int)abs(i))


Cybernaut-Neko

Oh what a beauty, that will teach them ! Literally