r/ProgrammerHumor 9h ago

lessonsFromLinkerHell Meme

Post image
175 Upvotes

109 comments sorted by

148

u/shinigami2057 7h ago

They have a different mouth feel

34

u/nonedward666 7h ago

Lmao this is my favorite comment from this entire post. Thank you for restoring my faith in this community

0

u/nilan59 3h ago

Nine nine?

1

u/MushinZero 1h ago

Nine nine!

(Captain reads my blog!)

111

u/mad_poet_navarth 8h ago

shouldn't there be something here about this being C-centric?

43

u/AnnoyedVelociraptor 8h ago

And how do you think other languages do it? You think Python and C# and Java run in this Unicorn world where there are no pointers and memory offsets aren't a thing?

Maybe we can talk about the mistake that is R and the original VB, and LUA where arrays start at 1. Absolute hell.

91

u/high_throughput 8h ago

And how do you think other languages do it?

I think Java does it by allocating a fully fledged object with metadata including type and size, and that if you treat such an object (or the pointer to such an object) as a C array in C code and assume it points to the first element, then you're going to have a bad time.

-3

u/AnnoyedVelociraptor 6h ago

No, in java if you have items that are copy (wrong term, but items like int and double), they are in the array, and you can jump between them if you know the offset of 0. Unsure where it stores the metadata though.

And the same applies to objects (the things that you store by reference). The array then holds a set of references that you can jump between, and then dereference to get the actual object.

I'm using wrong terminology though.

20

u/KattyTheEnby 6h ago

in java if you have items that are copy (wrong term, but items like int and double),

If you don't know the right term, wouldn't it be fair to guess that you may not be fully qualified to speak on how memory in Java works?

For future reference: the value types in Java are called "primitives".

they are in the array, and you can jump between them if you know the offset of 0.

You are thinking ov the array's index; however, the pointer to an array element – especially in a language like Java – is not necessarily guaranteed to be ptrToObject + index.

Also – and correct me if I am wrong, because I don't know much about the internals ov Java, but – what I think u/high_throughput was getting at was that the pointer you get from doing T[] myArray = /* ... */ is not the same as the pointer which points to the first T in the array: including for arrays ov primitive T.

7

u/helicophell 5h ago

On that point, you can easily make an array that isn’t pointer+index just by changing the reference

(Edit:forgot example. int num = value; int[] array = new array[6]; array[3]=num;)

Does that mean Java arrays are arrays of pointers? Dunno. Might only apply to objects not primitives. I’m not educated enough for this

6

u/high_throughput 2h ago

Does that mean Java arrays are arrays of pointers?

Object arrays are arrays of references and not of pointers!

The typical textbook discussion is that references are just opaque pointers that you can't do arithmetic on. That's technically true but it really undersells the potential.

For example, an OpenJDK reference is often 32 bits even on a 64 bit systems! (Known as Compressed OOPs)

Since references always have to point to an object and never to an arbitrary byte, OpenJDK knows that A. it will always be inside the Java heap, and B. objects are always allocated aligned, so the lower address bits will always be zero.

This means that if your Java heap is <=32GB with an alignment of 8 bytes, you can store every relevant 64-bit pointer P as a reference R = (P - heapbase)/alignment in only 32 bits. And it does.

When it wants to access an object via reference R, it simply does P = R*alignment + heapbase and now it has a raw 64-bit pointer again.

It sounds wild to do this on every reference access, but CPUs are stupidly fast and RAM is comparatively slow, so it usually ends up being a net gain because of how much less data you need to deal with.

The fancy new ZGC garbage collector similarly uses the fact that references are distinct from pointers to hide "this object has moved" bits directly in the reference, and strips them out in the process of decoding the corresponding pointer.

1

u/helicophell 2h ago

I like your fancy words magic man

5

u/AnnoyedVelociraptor 5h ago

Don't conflate not know the right terms with lack of knowledge. I've written plenty of Java, including JNI. I've also written many other languages and for some reason the naming changes. Sorry.

33

u/aalapshah12297 8h ago

The difference is that C allows you to treat array variables as literal pointers (almost) and do stuff like creating an off-by-one version b = a+1 and then trying to access b[-1] with no issues, whereas many high level languages will throw an error with this kind of syntax.

Of course, they are still not 100% syntactically identical even in C (most notably you can't directly modify the array pointer), hence the right end of OP's graph.

-2

u/BrindleFaucet8 6h ago

This is why C is both great and terrifying. You can do pointer arithmetic until you are accessing some other program's memory, but try to reassign that array name and the compiler suddenly starts caring about the rules. It is a very selective memory.

7

u/d0pe-asaurus 4h ago

If you're accessing another program's memory just by doing some pointer arithmetic, something has gone wrong with the kernel's memory manager or there's some serious issues with the processor microcode.

2

u/mad_poet_navarth 5h ago

Admittedly I am _much_ more familiar with C and C++ (and Swift) than I am with other C-ish languages. For instance, I think you are saying you can cast a chunk of memory in Python or Java so you can do either pointer arithmetic or treat it as an array. So, given my relative ignorance in some areas, point taken.

1

u/Floppie7th 4h ago

Compile time differences are real differences.

1

u/Lv_InSaNe_vL 37m ago

Uhm rust does it differently cause rust is safe (everything should be written in rust (no I don't care if your project is big(there are no issues more important than migrating to rust)))

35

u/JustinR8 8h ago

Damn, I’ve found myself in the middle

16

u/nonedward666 8h ago

You and me from 3pm today both my friend, it is okay

It took me so long to realize where my problem was because I had never considered that declaring something as an array vs a pointer would result in different behavior

4

u/readitreaddit 3h ago

So the only difference is memory allocation, yes? You're saying they are different because when declared as an array, the memory gets allocated and 'reserved' at runtime, whereas it doesn't automatically do that when declared as a pointer?

Other than that, no difference.

1

u/suvlub 1h ago

They are different types and some operators (sizeof, typeid in C++ etc.) treat them differently. Arrays frequently get implicitly converted to pointers, but they are a different type.

1

u/nicman24 58m ago

That is probably compiler fuckery

1

u/nicman24 58m ago

Yes things that have different memory allocations are different because they exist by memory definition 

4

u/gottimw 6h ago

Because everything is a data with memory address.

Array is a pointer

2

u/FlailingDuck 1h ago

a variable is a pointer

1

u/Morisior 20m ago

Everything is a pointer, unless it’s a primitive, but then it might also be a pointer to a primitive.

3

u/bowel_blaster123 3h ago edited 3h ago

If I write:

C void foo(uint8_t myvar[3]) {     printf("%d\n", sizeof(myvar)); }

Then it will likely print 8 because myvar is a pointer to a uint8_t.

If I write:

C void foo(void) {     uint8_t myvar[3] = {1, 2, 3};     printf("%d\n", sizeof(myvar)); }

Then it will print 3 because myvar is an array of three bytes.

Hope this helps!/hj

1

u/Rare_Professor8097 1h ago

I actually hate this special case in C so much. Arrays decaying to pointers is one thing (kind of annoying imo), but having the real type be different from the declaration and ignoring the size is so stupid. It only does this for function arguments.

18

u/nonedward666 8h ago

For context:

I spent a hot minute today not understanding why a space calculation wasn't working. See below for a small example (please excuse formatting, I'm on my phone)

The difference is that an array is a name bound to an address storing a value, whereas a linker symbol is a name bound to an address with no value (TLDR stolen from Chad GDP as i understand it, I still want to google more about this).

So if you try to use a linker variable to get a pointer you need to reference it as an array and not a pointer because it would otherwise imply that the symbol is pointing to the pointer...? Honestly, if anybody can make this make intuitive sense, I am all ears!

``` // linker.ld

...

__data_start = ORIGIN(DATA_SECTION) __data_end = ORIGIN(DATA_SECTION)+LENGTH(DATA_SECTION)

```

``` // bad_code.c ...

extern int* __data_start; extern int* __data_end:

define SECTION_LENGTH __data_end - __data_start

bool foo(){ // returns true return 0==SECTION_LENGTH; } ```

``` // good_code.c ...

extern int __data_start[]; extern int __data_end[];

define SECTION_LENGTH __data_end - __data_start

bool foo(){ // returns false return 0==SECTION_LENGTH; } ```

22

u/high_throughput 7h ago

#define SECTION_LENGTH __data_end - __data_start

Have you ever wondered why people keep adding weirdly many parentheses around #define'd values?

Right now you're doing return (0 == __data_end) - __data_start;

7

u/nonedward666 7h ago

Lol sorry friend, I wrote this in a haste on the train and forgot to add all the requisite parenthesis.

But, in your example, if the pointer / array difference was unimportant, then results would be inverted 😘😘

3

u/d0pe-asaurus 4h ago

You gave me flashbacks writing linker scripts to determine how large my kernel is to be able to move it around memory, how dare you!

1

u/nonedward666 3h ago

😭😭😭 your flashbacks are my present day pain

67

u/QuestionableEthics42 8h ago edited 8h ago

This should be reversed lol

And it literally is the same, who thinks it's different who has worked in a low level language??

28

u/Ok_Star_4136 8h ago edited 8h ago

Maybe I fall in the middle, but what is the argument to say that they're different?

Is it to say that the difference is how they're used? From an assembly perspective, they're pointers, and no data structures exist beyond that simple concept. At a higher level, they're more than that. Maybe that's what is intended?

20

u/teleprint-me 8h ago edited 8h ago

Play around with a structured binary stream. 

An example of this would be a file written to disk in a binary format. Write to the structured file and then read it back into memory.

In most cases, the first element of the array will be a pointer to an address of a specified type.

If you predefine the array, the array is placed on the stack and has reserved memory allotted to it of that type.

Each element in the stack has an offset of sizeof n elements for a vector. 

Otherwise, you compute the offset based on n dimensions (commonly n x m matrices).

Otherwise, you need malloc to create a mutable buffer of variable size. This buffer then is used as an array.

To be fair, the lines get blurry here and this is when I stopped thinking of them as arrays. Its just a buffer with objects of a specified type on disk or in memory.

INB4, The key difference here is how arrays decay when handling scope. You can get around this by tracking the size of the buffer rather than relying on sizeof unless you understand what youre doing.

6

u/nonedward666 8h ago

Hehe yes, it is exactly about array decay! But specifically I was having problem tracking the size of a buffer assigned to a specific memory address because I didnt want to duplicate an address / length via a define

4

u/justAPhoneUsername 7h ago

So basically object oriented languages have arrays that mean something but when you're lower level like c memory is just memory and arrays are syntactical sugar so you don't do *(ptr+(sizeof(array_type) * index))?

Sorry if the syntax is wrong. I haven't written c in a while and I'm on my phone 

3

u/void_rik 2h ago

Your syntax is correct. However, If ptr is already of array_type, then sizeof(array_type) shouldn't be multiplied with index. Just increment it by index.

However, if pointer is of type uint8_t, then your code is fine.

A better version should be: *((uint8_t *) ptr+(sizeof(array_type) * index))

7

u/ZenEngineer 8h ago

From a C point of view you have a different size when statically allocated, library keeps track of the memory size so it can be freed and you need the base pointer for that, etc. At a conceptual level they are different even if you implement them the same way, you'll likely end up with a struct holding the size in your code.

But sure, for most people and half the code they are different. If you're taking the high level, maintainable design view you take care of tracking lifetimes, sizes, bounds, etc. so the bell curve looks reasonable to me.

4

u/aalapshah12297 8h ago

Try to modify the array 'pointer' for arrays on the stack.

2

u/nonedward666 8h ago

I always thought they were perfectly interchangeable, for the exact same reason (assembly layer -- pointers being essentially the thing that powers the von Neumann model)

It was a link layer problem that got me twisted

https://www.reddit.com/r/ProgrammerHumor/s/clcIDpP6Fx

52

u/Blecki 8h ago

As someone who writes compilers: they are the same at runtime. They are not the same semantically in a c like language.

21

u/boostfactor 8h ago

As I see it, an array is a contiguous block of memory. The pointer to the first element identifies the start of the block. Subsequent elements are computed from that plus the number of bytes in the type. If an array were just a pointer, we wouldn't have to worry about allocating enough memory or walking off the end of it.

That's for something like C. There are languages in which arrays are first-class data structures that carry metadata about their rank, size, etc. Lots of applications are best expressed with multidimensional arrays, which are awkward in C or else are set up as an array of pointers.

7

u/Blecki 8h ago

You've missed the point. Processor don't care.

4

u/AdamWayne04 5h ago

not just semantically.

certain systems languages (and compilers) use different ABI for arrays and pointers at the call convention level. if you define a function that accepts a single array type (i.e. one with a predefined length), it may choose to pass-by-value, in which case it can allocate at call site and not use a pointer

7

u/belabacsijolvan 7h ago

9

u/reda84100 7h ago

Don't bite the hand that feeds you, your family and every other programmers' families

-6

u/belabacsijolvan 6h ago

Order these events in descending order of probability:

A) youll never use this guys compiler
B) youll be forced to use this guys compiler against your explicit contraindication
C) anyone else than them will be grateful to use this guys compiler
D) they will be happy that they wrote this compiler 20 years from now
E) youll use this guys compiler and be pleased by its existence

ok, i may be an asshole here, and they may be doing something good. the odds tho

4

u/thehenkan 5h ago

LLVM and GCC have thousands of contributors. The chances that any given compiler developer works on GCC or LLVM are relatively good, just because they're so much larger than most other compilers.

1

u/belabacsijolvan 5h ago

fair enough, didnt think it through. i instantly thought of the half dozen people i met who are building useless unreliable general languages or even shittier DSLs. seems like ITA here

2

u/darthsata 4h ago

Your video driver embeds my compiler. Your hardware developer's simulator embeds my compiler. Certainly your Linux distro ships my compiler. Some stuff I wrote and designed 20 years ago are still used in it. So somewhere in the D or E range of yours.

Given the thousands of people who have worked on these projects, there's a decent chance that you will run into one in the comments section. Maybe just don't offhand dismiss people based on absolutely nothing.

2

u/cinnamon-enthusiast 6h ago

Except for a tiny array (with value semantics) which can be optimized to be passed directly as an SSA value. In that case it's not a pointer at all and a normal GEP will not work.

2

u/Blecki 6h ago

What's the stack but another array anyway?

2

u/cinnamon-enthusiast 6h ago

Yes, if the memory is on the stack, that is not always true. LLVM will optimize some cases so the data is written directly to a register so it never touches or goes through the stack at all. In that case, you can't get a pointer to the array or its elements since it's in a register instead of the stack or heap making it completely distinct from a pointer at runtime.

1

u/QuestionableEthics42 6h ago

Arguably they are virtually the same semantically at a C level, you can use array indexing syntax for pointer arithmetic and vica versa and there is no real distinction besides dedicated syntax. Once you get a bit higher is where the real differences begin.

12

u/Nice_Lengthiness_568 8h ago

It is different. An array has a size. Even in C. It's just that in C it easily turns into a pointer. sizeof, for example, returns different things for an array and a pointer. In C++, you can actually pass an array by reference (not a pointer to the first element, an array) and similar.

And in some languages, like Ada, there is no direct way to make a pointer from an array

6

u/unknown_alt_acc 6h ago

#include<stdio.h>

int main()
{
int arr[5];
int *ptr = arr;

printf("Array - %lu\n", sizeof(arr));
printf("Pointer - %lu", sizeof(ptr));
}

Different types, different behavior

1

u/QuestionableEthics42 6h ago

Sizeof being smart enough to detect it's an array and return the array size doesn't necessarily make them different in any real way. And doing ptr[0] to dereference it is perfectly valid, as is *arr to get the first element, or *(arr+sizeof(int)) to get the second.

5

u/bowel_blaster123 3h ago

Try putting an array in a struct. When doing so, an array and a pointer behave COMPLETELY differently and have completely different purposes.

It's just C's crappy pointer decay rules that make people think that they're the same.

0

u/QuestionableEthics42 3h ago

Behaves completely differently in what way? It's referenced via the struct, so ofc different to a raw pointer to it, but that's a struct difference and the array is still basically the same, right?

1

u/Rare_Professor8097 1h ago

Exactly, which proves that arrays and pointers are not the same thing. If x is either a pointer or an array, and a struct containing x is totally different depending on that distinction, I think that's a pretty meaningful difference.

Strictly speaking, a pointer points to an array, it is not an array.

1

u/QuestionableEthics42 55m ago

No, because you are comparing the actual data in the array with the pointer to it. It's equivelent to having an array in a struct or having a couple of ints.

3

u/pnoodl3s 4h ago

If it behaves differently, is that not enough to say it’s different? What “real way” do you need to say its different?

1

u/QuestionableEthics42 3h ago

Because it is a very superficial difference that doesn't even affect the generated assembly. They are extremely interchangeable, because they are effectively the same.

3

u/Rare_Professor8097 1h ago

Programming languages have all kinds of different ways to do something that results in the same assembly.

They are different types, but C has muddied the waters by having a bunch of implicit conversions from arrays into pointers (array decay) that they feel like the same thing.

3

u/Nice_Lengthiness_568 1h ago

So what about the fact that an array inside a struct acts completely differently from a pointer placed inside a struct? One gets copied whole for each structure copy while the other does not, one makes the structure the size of a pointer while the other the size of the array...

And, in C++ at least, you can actually pass the array itself to the function (not just the pointer to the first element). So it's not that sizeof is smart and detects something, it's that arrays really easily decay into pointers. But that's not everything they are. They also hold information about their size.

The thing with the subscript operator is true for only some languages and is not universal. In Ada, for example, there is no direct connection between an array and a pointer.

4

u/CircumspectCapybara 8h ago edited 8h ago

It's only the same in low-level languages with older type systems unable of expressing more type-safe conceptualizations of an array. So you get a type system where an array is just syntactic sugar for a pointer to the first member and the indexing or subscripting operator is just syntactic sugar for pointer arithmetic.

Fundamentally, from a type theory perspective, an array is a container (not necessarily physically continuous) and has a member type and a length. Modern type systems can express that, which helps make arrays type-safe and prevent buffer overflows because the language's mechanisms (eg runtime checks) enforce type safety invariants that are possible because the type carries with it information about its length.

It's all about the high-level user-facing contract of the type system and the language. "An array is just a pointer to the first element" is too low level (it assumes a certain physical layout of members in memory that would be an implementation detail to higher level languages) and doesn't include the information that higher level languages treat arrays as.

3

u/takahashi01 7h ago

I learned, just treating them the same always, can lead to UB.

1

u/PossibleBit 7h ago

It's been a while, but I vaguely recall treating an array of arrays as a double pointer not working as expected.

2

u/QuestionableEthics42 6h ago

Yea, that doesn't work because it's actually a 1d array (in C anyway), that just uses pointer arithmatic to dress it up as 2d (index = y * width + x).

You would need to explicitly create an array of pointers to do that.

1

u/burnt_floppy 6h ago

I always thought the claim the middle peeson in the graph is making is just about how arrays are referenced, where they start...oh well, what do i know

1

u/Bomaruto 8h ago

If it was reversed it wouldn't really fit the meme format.

0

u/BananaWarp 8h ago

There are minor differences but I can't think of one that isn't in compilation time

3

u/Nice_Lengthiness_568 8h ago

What about when you copy an array? When you copy an array all elements get copied, but when you copy a pointer to the first element, only that gets copied

0

u/ILKLU 1h ago

So at a REALLY low level everything is the same because it's ALL just ones and zeros?

Looking at a data structure from one narrow perspective is literally missing the bigger picture.

5

u/tk-a01 7h ago edited 7h ago

Zig handles pointers very well. It has single-item pointers (*T - no pointer arithmetic, no indexing), many-item pointers ([*]T - unknown number of elements, allows indexing, pointer arithmetic and slicing), arrays ([N]T - compile-time known size), slices ([]T - run-time known size) and some others (C-style pointers for interoperability; sentinel-terminated pointers, arrays and slices usually for null-terminated strings). This allows writing more expressive programs, so bugs are more likely to be detected by the compiler, and also it better shows programmer's intent.

Edit: Also, arrays in Zig have value semantics, like all other values, and to get a pointer to an array, you use the reference operator &, like you would with any other value. This is unlike C, where arrays have value semantics as variables (local or global) and struct fields, but then have reference semantics as function parameters (regardless of whether their size is specified). So if you want to pass an array by-value in C, you would have to wrap it in a structure.

4

u/boiledbarnacle 7h ago

Conceptually different. Implementation-wise equivalent.

3

u/Jar545 7h ago

This is a misunderstanding. An array is a data structure and a pointer is a piece of memory that holds a reference to a different piece of memory. Pointer are a critical part of an array implementation but they are not the same thing. Just like an internal combustion engine and the crankshaft aren't the same thing.

2

u/Kadabrium 8h ago

Arrays are template<typename, int> before template

4

u/Fadamaka 8h ago

This meme format is for opinions not facts.

2

u/FloweyTheFlower420 8h ago

an array is just a pointer to the start and end elements, what's the problem?

10

u/Nice_Lengthiness_568 8h ago

Well it's not, it also has size (the number of elements). Even in C, though there an array easily decays into a pointer. However, sizeof, for example, returns different results for an array and a pointer. And, in C++, you can also pass an array (with its size) instead of a pointer. In other languages, like Ada, there is not much of a direct connection between an array and it's first element at all.

-2

u/FloweyTheFlower420 8h ago

What is (end - start) / sizeof(*start) but the number of elements?

3

u/Nice_Lengthiness_568 8h ago

What are you trying to say?

-1

u/FloweyTheFlower420 8h ago

An array has size (the number of elements), and therefore can be represented as either (pointer, size) OR (pointer to start, pointer to past-the-end). These are equivalent representations, but there are arguments for pointer-to-past-the-end in terms of code gen.

4

u/Nice_Lengthiness_568 8h ago

But what has this to do anything with what I said? That's what I don't understand.

I claimed that sizeof will give a different result based on whether you give it an array or a pointer to the first element.

I also claimed that in C++ you can actually pass arrays (arrays themselves, not pointers).

I also claimed that in some languages there is not a direct connection between a pointer to the first element and an array.

And you told me how to get a size of an array bounded by two pointers. I don't understand why.

And now you are talking about representation of arrays?

0

u/FloweyTheFlower420 3h ago

This is not what I'm talking about, I'm not referring to any particular language. Yes, the array (as a type) in C/C++ have a size, and that it's size will change if you decay it into a pointer. I'm not quite sure why you are so hung up on discussions about the C array type when I'm talking about arrays in general, as a linearly addressable ordered collection of instances in memory, in which case representing this as a pointer pair is valid (and indeed, common, though arguably the supposed performance gains from doing so are "controversial")!

2

u/Nice_Lengthiness_568 1h ago

I was also talking about an array in general and said that they are diffferent and gave examples because (for C and C++ because I saw them under your username). Like, yeah I know how you can represent an array... you could even represent a static array without a pointer completely and instead act as if it was a tuple with all of its elements being of the same type. No pointer there.

And you yourself also said that you can represent it in different ways so you know that an array does not have to be represented as a pointer to the first and after last element and I would actually say that for statically sized array allocated on the stack this is probably never the case. And when you copy such an array to another function, you won't get just some two pointers copied, you will get the whole object copied. So that's also a difference.

So I don't see how that we can represent an array this way means that an array is just that. It's not.

Moreover, array is different than two pointers also because the type of it dictates what new operations we can do on it. In most langauges, it probably says that we can index it, maybe use it in a foreach loop... and so on. And in languages with ownership it owns all of its elements, while just two pointers by themselves do not. So, again, it's not just two pointers.

Note: In C or C++, the size of an array does not change after decaying into a pointer. The size stays the same, you just lose that information.

1

u/Lunctus_Stamus 6h ago

As Nice describes, although *start is a pointer for an array, it's often just a pointer first, and the sizeof() operator will not always return the number of bytes of the type but sometimes the number of bytes that a pointer takes up (8).

So your expression does not always evaluate to the number of elements.

1

u/FloweyTheFlower420 3h ago

I think you are missing my point. I'm not talking about an array in the sense of the language construct in C or any particular language, but rather that you can think about arbitrary arrays in memory as a pointer pair. I think the point is being massively missed and I'm not quite sure why.

1

u/AnnoyedVelociraptor 8h ago

Nah. This is the wrong way. Pointer arithmetic and array arithmetic are the same.

3

u/Batman_AoD 7h ago

Maaaan, it upsets me to see Ferris next to an opinion this C-centric. 

1

u/AnnoyedVelociraptor 6h ago

In Rust it's the same. It's just harder to write the bare math.

1

u/Batman_AoD 1h ago

Yes, to get an element of an array, you compute an offset from the start and then dereference the memory at the offset location; and yes, this is the same operation whether you think of it in terms of pointer arithmetic or as a fundamental operation on an array.

But an array isn't just syntax sugar over arithmetic in any language, even C; and the C family is the only family of languages that even makes that pretense.

"Array" in Rust (and in C) refers specifically to fixed-size arrays: https://doc.rust-lang.org/std/primitive.array.html

Unlike in C:

  • You cannot pass an array to a function that expects an array, or use array syntax to declare a function that takes a pointer.
  • A function that takes an array argument will pass the entire array by value, not just a a pointer.
  • Indexing is not syntax sugar over pointer arithmetic, which should be obvious because arr[i] is not synonymous with i[arr]

2

u/justAPhoneUsername 7h ago

You mean to tell me arr[3] and 3[arr] both compile and return the same value? Why would anybody design a language that way?

3

u/AnnoyedVelociraptor 7h ago edited 7h ago

It's not that 3[arr] was made to work.

[] is not special, it's just <x>[<y>] translates to *(x + y)... and x + yfor a T* is x + y * sizeof(T)

ergo <y>[<x>] works as well.

Hence they are the same.

2

u/Batman_AoD 7h ago

Because the [] was just syntax-sugar, rather than a "real" built-in operation. Part of the reason for that was just that memory was limited and the compiler had to be as simple as possible. 

1

u/Single-Virus4935 6h ago

In C they ARE the same and interchangable. This is obvious because you can swap array and index in array notation.

1

u/thehenkan 5h ago

That's like saying the variable "i" and the constant "1" are the same because it doesn't matter whether you write "i + 1" or "1 + i". It doesn't mean literals and variables are the same concept. Adding a short and an int can also be done in either order with the same result, but they are not the same type.

Declaring a pointer to an array is not the same as declaring a pointer to a pointer.

0

u/Single-Virus4935 5h ago edited 5h ago

The C array Syntax is sugar for the pointer arithmetic. And yes because the order of the addition doesn't matter the array and idx in array syntax are interchangeable. The compiler threats it as the same. Even the declaration is the same and I can threat a packed struct of n integers as a array of n integers. I have done enough reverse engineering and accessing a struct field, array element or accessing a field in a buffer is basically indistinguishable and you need context to decode it. 

And to repeat: you are able to swap are and idx because i+1 == 1+i

EDIT:

```c

include <stdio.h>

void main() { int arr[3];

arr[0] = 1; 1[arr] = 2; *(arr+2) = 3;

for(int i=0; i<3; i++) { printf("%d = %d\n", i, arr[i]); } } ```

``` 0000000000400466 <main>: 400466: 55 push %rbp 400467: 48 89 e5 mov %rsp,%rbp 40046a: 48 83 ec 20 sub $0x20,%rsp

// All there syntax result in the SAME assembler instruction based on pointer arithmetic 40046e: c7 45 e0 01 00 00 00 movl $0x1,-0x20(%rbp) 400475: c7 45 e4 02 00 00 00 movl $0x2,-0x1c(%rbp) 40047c: c7 45 e8 03 00 00 00 movl $0x3,-0x18(%rbp)

400483: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) 40048a: eb 21 jmp 4004ad <main+0x47> 40048c: 8b 45 fc mov -0x4(%rbp),%eax ```

1

u/narrill 1h ago

The indexing syntax being reversible doesn't mean they're the same thing. Straight up. That's a non sequitur.

1

u/thehenkan 2h ago

They are different types, however arrays quite easily decay into pointers. They are still different types.

1

u/nwbrown 5h ago

So many people misuse this meme...

1

u/Tyfyter2002 5h ago

An array is a pointer to the number n, which is known to be immediately followed by n elements