4 ms·
> Arrays are first-class things, not hacks on top of pointers, and can't alias each other. "Hacks" feels like the wrong term to use here. Comparing managed obj
by MisterTea 2y ago
> Arrays are first-class things, not hacks on top of pointers, and can't alias each other.
"Hacks" feels like the wrong term to use here. Comparing managed objects surrounded by runtime to memory isn't a fair comparison.
- nine_k 2y agoThere's no language-level difference between int[] and int* in C. Indexing is just pointer arithmetics. No support for (non-jagged) multidimensional arrays either. A proper array would at least know its length. It does not require a lot of runtime to do, and most C code require libc anyway for basic stuff like malloc().
- jjmarr 2y agoThis isn't true. int[] decays into an int* but is a different type. An array member of a struct will have its data allocated contiguously with other struct members (subject to compiler padding). An int* would point outside the struct. This is possible even with variable length arrays. Specifically, you can declare the final member of a struct as an int[] which makes it a "flexible array member". Then you have to malloc the struct to be the sizeof the struct + whatever size you want the array to be. https://en.wikipedia.org/wiki/Flexible_array_member https://en.wikipedia.org/wiki/Flexible_array_member This is used in struct sockaddr for generic APIs where the actual struct can be of different sizes. https://lwn.net/Articles/997094/ https://lwn.net/Articles/997094/ This is rather pedantic but the memory model for arrays is important here. If you're iterating over multiple struct members that are arrays, the fact the arrays are stored contiguously in memory is going to matter to SIMD.
- nine_k 2y agoThis is fair, thanks!
- Gibbon1 2y agoThe C language spec isn't what important here it's the ABI doesn't know the difference.
- jjmarr 2y agoif using an int* over an int[] changes the memory layout of a struct, that necessarily implies a difference in the ABI. As an example, C++'s std::array can be implemented as a struct containing a fixed-size C-style array. This can be passed-by-value. This means that returning a std::array can be more performant than returning a std::vector (which might be implemented as an int* that is reallocated when you add too many elements), because a std::array is returned on the stack while a std::vector is returned on the heap. I was bit by this once when returning a std::unordered_map because I was doing a heap-allocation in a performance-critical section.
- Gibbon1 2y agoThe memory layout is the ABI not the language spec.
- jjmarr 2y agoThe language spec for C constrains the memory layout of a struct. From 6.7.3.2.7 of the draft spec: > a structure is a type consisting of a sequence of members, whose storage is allocated in an ordered sequence, (emphasis added) https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf
- charleslmunger 2y ago>Then you have to malloc the struct to be the sizeof the struct + whatever size you want the array to be. Ultra pedantic, but you actually do not need to alloc struct+size; you want something like: // A flexible array member may have lower alignment requirements than the struct // overall - in that case, it can overlap with the trailing padding of the rest // of the struct, and a naive sizeof(base) + sizeof(flex) * count calculation // will not take into account that overlap, and allocate more than is required. #define SIZEOF_FLEX(type, member, count) MAX(sizeof(type), offsetof(type, member[count])) I'm sure there's a more elegant way to calculate this, but I am no macro master.
- MisterTea 2y ago> There's no language-level difference between int[] and int* in C sizeof(int[n]) vs sizeof(int*). Then there's: 'int getint(int *I){return *I;}' which wont let me pass '&int[n]' but I can 'int* = int[n]' then pass &int*. It's not so much a hack but a very primitive implementation on top of pointers (alright maybe it is a bit hacky.) > A proper array would at least know its length. It does not require a lot of runtime to do, and most C code require libc anyway for basic stuff like malloc(). Something like a fat pointer 'typedef struct {long len, void *data} MyArray;' then make a libMyArray to operate on MyArray objects. But now you have a libMyArray dependency. You also loose type information unless you add fields to MyArray with an enum or have a MyArray for each type which gets messy. Then you cant do shit like just use an identifier in a conditional e.g. 'while(MyArray[n++])' unless you change how C works which makes it notC (uh, maybe pick another name.) I feel that C is fine as it's an old machine oriented language. Leave it alone. I would look to reach for another tool when the primitive design of C makes life difficult.
- MisterTea 2y agoOh crap, markdown strikes again and ate the extra asterisk in getint(**I)
- pjmlp 2y agoFortran is not a managed language, and has a runtime as big a C.