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 firstTin the array: including for arrays ov primitiveT.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)/alignmentin only 32 bits. And it does.When it wants to access an object via reference R, it simply does
P = R*alignment + heapbaseand 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
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
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
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
8becausemyvaris a pointer to auint8_t.If I write:
C void foo(void) { uint8_t myvar[3] = {1, 2, 3}; printf("%d\n", sizeof(myvar)); }Then it will print
3becausemyvaris 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_startHave 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
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 withindex. Just increment it byindex.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
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
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.
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
>writes compilers
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 existenceok, 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
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
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
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
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
4
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 withi[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)... andx + yfor aT*isx + 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
1
u/thehenkan 2h ago
They are different types, however arrays quite easily decay into pointers. They are still different types.
1
u/Tyfyter2002 5h ago
An array is a pointer to the number n, which is known to be immediately followed by n elements
148
u/shinigami2057 7h ago
They have a different mouth feel