Live data from Hacker News

C array types are weird

anselmschueler.com

101–110 of 148 posts

Re: C array types are weird

#101
post #5
post #2

In practice, the [static n] notation can give you useful warnings and bounds checking. https://godbolt.org/z/PzcjW4zKK And while the (*array_ptr)[3] notation take a moment to get used to, it is very logical. If you have a pointer to an array, you dereference it first and then indx into it. Again, useful for bounds checking: https://godbolt.org/z/ao1so9KP7

What is **int[3][5]

The work of the mythical four star programmer? https://wiki.c2.com/?ThreeStarProgrammer

Re: C array types are weird

#102

Earlier quoted context omitted.

> Array memory is on the stack. Array memory can sit on either the stack or the heap. > The size of that array is actually not known at run time, its only known at compile time, where any reference to that length gets resolved by the compiled. This is also a bit misleading, in two ways. First, it's not clear what you mean by "size" here - the size of the memory block(s), or the shape of the array? Second, many people…

>Array memory can sit on either the stack or the heap. No, if we are using the definition of an array that is like int c[] = ..., that is always going to be on the stack. Heap continuous memory =/= array. You can use the [] operator to access it like an array, but fundamentally, as far as structures in C language are concerned, those 2 are different, because they get treated by compiler differently. >but the size is…

> that is always going to be on the stack.

Unless your C implementation doesn't use a stack for data storage. Which existed, you know: IIRC the C compilers for Cray machines used linked lists to hold activation frames. And of course, there are PIC microcontrollers where you can't really use the hardware stack for anything except return addresses.

Re: C array types are weird

#103
post #87
post #48

Earlier quoted context omitted.

"breaks completely" I rather would say it works nicely in auto-generating the complex indexing operation for n-dimensional arrays which makes it a lot more convenient and less error-prone to write such code. The compiler may also flatten a loop. The array of pointer hack used previously to similate 2d arrays using an array to pointers to arrays should not be used outside of special algorithms, as it is error prone an…

> The compiler may also flatten a loop. http://c2.com/cgi/wiki?SufficientlySmartCompiler In practice, C compilers are still notoriously bad at loop optimizations. Polyhedral optimizations provided some hope, but no compiler managed to adopt it in production.

Maybe, but also irrelevant to the discussion because whether you write mat[b * A + a] by hand or mat[b][a] and let the compiler frontend expand then makes no difference to the optimizer.

Re: C array types are weird

#104

Earlier quoted context omitted.

> Array memory is on the stack. Array memory can sit on either the stack or the heap. > The size of that array is actually not known at run time, its only known at compile time, where any reference to that length gets resolved by the compiled. This is also a bit misleading, in two ways. First, it's not clear what you mean by "size" here - the size of the memory block(s), or the shape of the array? Second, many people…

>Array memory can sit on either the stack or the heap. No, if we are using the definition of an array that is like int c[] = ..., that is always going to be on the stack. Heap continuous memory =/= array. You can use the [] operator to access it like an array, but fundamentally, as far as structures in C language are concerned, those 2 are different, because they get treated by compiler differently. >but the size is…

> No, if we are using the definition of an array that is like int c[] = ..., that is always going to be on the stack. Heap continuous memory =/= array. You can use the [] operator to access it like an array, but fundamentally, as far as structures in C language are concerned, those 2 are different, because they get treated by compiler differently.

Well, not necessarily. For one thing, if we have a function foo(int c[]), it's debatable if c is an array variable or a pointer variable. However, what's not debatable is that you can allocate a struct on the heap, and that struct can have an array member - e.g. `struct foo { int a[10]; }; [...] struct foo *x = malloc(sizeof(struct foo));` would allocate an array on the heap as part of the struct.

> That would only be true if each element in the array was a char.

That's why I said that it depends on what exactly you mean by the size of the array. It's also true that in today's world at least, malloc() will often allocate more memory than you actually ask for, to optimize against fragmentation - and then the internally stored size is the size of the actual allocation, not the logical size that you requested - which may not even fit into a whole number of array elements. So, I was being a little overly simplistic (lying) for dramatic effect.

> For example, a really good practice in C coding that basically solves any double free is a mempool that allocates all the memory up front.

While this is a very valid technique for certain purposes, especially when dynamic allocation is needed in very high performance code, it's very much not a valid solution for memory safety - quite the contrary, it's a terrible practice for that. In particular, this is almost exactly the issue that caused the infamous HeartBleed vulnerability in OpenSSL to stay hidden for so long: the use of a memory pool for the buffers used to store TLS packets was hiding the buffer overflow from UBSan and valgrind and similar tools, since the reads were perfectly valid from a language perspective (they were never reading from free()d/unallocated memory, only from memory that had been released to the memory pool).

Re: C array types are weird

#105
post #50

Earlier quoted context omitted.

It is a struggle though to get the improvements through the committee. Especially the C++ folks from the Clang side fight very hard against it, this is - for example - why we not have forward declarations where I already had weak consensus, but the clang area team made it clear they will never implement it.

But C and C++ do have forward declarations [1]... can you elaborate on what exactly you were trying to promote that was rejected? [1] : https://en.wikipedia.org/wiki/Forward_declaration

I assume he's referring to: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3207.pdf

Re: C array types are weird

#106

Earlier quoted context omitted.

> Compared to what? ...for somewhat recent languages: Rust, Zig, Odin... (with differing intensity, but they all want to nudge the programmer into a certain direction of how to do things). > Anyway I find it hard to believe enabling suicide is a good thing "War is peace, Freedom is slavery, Ignorance is strength" ;) Seriously, if people want to write their programs in assembly code or whatever weird kink, just let th…

[flagged]

> How fucking stupid do you think we are.

Well in your case specifically, I'm really not sure tbh.

> You think the authors of unix would have used c if they could have bootstrapped rust instead?

Considering that Ken Thompson later helped building Go, which is pretty much an anti-Rust, I do indeed think that they wouldn't have gone with an overengineered boondoggle like Rust if they had the choice.

Apparently Brian Kernighan also isn't a big fan of Rust, quote:

"I have written only one Rust program, so you should take all of this with a giant grain of salt,” he said. “And I found it a — pain… I just couldn’t grok the mechanisms that were required to do memory safety, in a program where memory wasn’t even an issue!"

Re: C array types are weird

#107
post #26

C array types are weird because C doesn't really need arrays. It's not what C was about. But if you designed a language in the era where Fortran, THE array language, reigned supreme, nobody would use your language. The mindshare Fortran had is difficult to convey now, half a century later. Think of it like making a chatbot today and not mentioning AI or LLMs, that's what making a language without arrays would have fe…

People who do HPC in C actually wish C had proper arrays like Fortran. If your function takes two pointers as inputs instead of two arrays they can alias the same memory and in fact they may alias any other pointer of the same type. Writing into one of them invalidates all the values you have in registers so you have to load them again. The "restrict" keyword was invented to solve this but it still has weaker semanti…

Sometimes you have to use C but really they should be doing HPC in fortran. It has C FFI, it can compile to static programs and to dynamic libraries, it has C-like performance, etc.

(It's not as portable as C though, and the compilers have more bugs.)

Re: C array types are weird

#108

It's still weird to me that you can declare an array with the register keyword. Then it (understandably) becomes UB to attempt to get the pointer. (It also probably isn't stored in a register, since the keyword is just asking the compiler nicely.)

The meaning of the 'register' keyword has changed over time to just "it's illegal to take the address of this item": https://www.godbolt.org/z/TKq9rWzP1 Don't know what's the idea behind not allowing to take the address of a value though.

It matters in single-pass compilers. You can't allocate a variable in a register if its address is ever taken, but by the time a single-pass compiler knows that information it has already spit out all of the assembly for the function.

Re: C array types are weird

#109
post #2

In practice, the [static n] notation can give you useful warnings and bounds checking. https://godbolt.org/z/PzcjW4zKK And while the (*array_ptr)[3] notation take a moment to get used to, it is very logical. If you have a pointer to an array, you dereference it first and then indx into it. Again, useful for bounds checking: https://godbolt.org/z/ao1so9KP7

The parentheses in (*parray)[i] would be unnecessary if dereferencing used postfix notation. Current: All postfix *ptr[3] ptr[3]* // indexed access, then deref (*ptr)[3] ptr*[3] // deref, then indexed access*

Dereferencing does have a postfix notation, so you can try it (sort of):

    #define $ [0]
then you can say ptr $[0] or ptr[0]$ and see if it's really better...
Post reply on HN