12 ms·
Because you can't do that and still call the resulting language C. It would be a different language incompatible will _all_ existing C code. Pointer decay is a
by elteto 2y ago
Because you can't do that and still call the resulting language C. It would be a different language incompatible will _all_ existing C code.
Pointer decay is a fundamental mechanic in C. If you use arrays in C, and you pass said arrays as an argument to a function, then you are dealing with pointer decay.
- lisper 2y ago> Because you can't do that and still call the resulting language C. Says who? Non-backwards-compatible changes are made to language standards all the time. It's not pain-free, but neither is the status quo. Besides, who cares what the language is called? Change the name if that's what it takes, but stop conflating pointers and arrays. The cost of that has been literally billions of dollars in losses due to buffer overflows over the decades.
- usrnm 2y ago> The cost of that has been literally billions of dollars in losses due to buffer overflows over the decades. How much, do you think, would rewriting all existing C code cost?
- junon 2y agoNothing, if new standards are opted in via a #pragma.
- lisper 2y agoWhy do you think that would be necessary?
- usrnm 2y agoIt's the only way to really solve the problem. Simply creating a safer alternative won't help, they already exist. The real problem is the vast ocean of already existing critical unsafe code
- candiodari 2y agoThe whole reason C code is used is that it can be used for free. In other words, infinitely more than they're spending now. More than even the CCP is willing to spend to protect state secrets.
- colonwqbang 2y agoThere are many good "better C" alternatives already. Rust, zig, D. They address other common types of bug like resource leaks, overflows, use after free. If you're ok with rewriting code, you have terrific options. And of course there is C++, the most famous attempt to fix C in a somewhat compatible way by adding more features. It is debatable whether this effort resulted in a better language. C++ has all the bits needed to check array bounds by default but chooses not to do so... The problem is that the huge existing stock of C code is written in C and not rust, zig, D, etc. The same would be true for your proposed "better C" language and any other incompatible iteration of C. If you can come up with a way to add these guarantees to C without needing significant rewriting, I can assure you that most C programmers would be very interested.
- lisper 2y ago> There are many good "better C" alternatives already. Rust, zig, D. All of these are very different from C. What I'm proposing is just one small change to the existing C language. > If you can come up with a way to add these guarantees to C without needing significant rewriting, I can assure you that most C programmers would be very interested. I can pretty much guarantee that they would not because this is easy: phase in the changes. Start by turning array-pointer conflation into a mandatory warning rather than undefined behavior or whatever it is now. Then wait a few years. Then turn it into an error that you can muffle using -C2024 or whatever. I actually don't know whether array-pointer conflation is required by the standard or if it's undefined behavior (I'm pretty sure it's one or the other). But if it's the latter then you don't actually have to change the standard to make this happen, all you need to do is write a compiler that does the Right Thing. AFAIK no such compiler exists. But there is just no excuse for this: % gcc -v Apple clang version 14.0.0 (clang-1400.0.29.202) ... % more test.c int main () { int x[10]; return *(x+20); } % gcc -Wall test.c %
- retrac 2y agoIn assembly, arrays and structs reduce to base address, plus offset times scaling factor. C provides a thin veneer over that. Scaling derived from size of type. Offset is the array index. The basic programming model of C is to view memory as an array.
- mhh__ 2y agoI don't know how much C code actually uses it tbh. Most things just take a pointer. Wouldn't be easy by any means but it could be done at the scale of the Linux kernel if anyone cared enough.
- elteto 2y agoIf you use arrays in C you are using pointers and pointer decay. There’s not a lot of useful C code that doesn’t use arrays.
- mhh__ 2y agoThat's true but this is mostly the easy case where things decay in relatively trivial fashion as opposed to the "they're different but actually the same" aspect which is genuinely a bitch of change.
- LeFantome 2y agoI think that is part of his point. Most functions take a pointer, even if they are expecting an array.
- eru 2y agoThe Linux kernel already uses not standard C, but a dialect of C defined by the GCC flags they use. But if you are willing to use something-like-C-but-not-shackled-by-backwards-compatibility, then why stop at arrays and pointers? Just move all the way to D or Zig (or even Rust). These are all languages designed (partially) so that you can port an existing C system bit-by-bit over into them. Many people who can afford that, are doing that, of course. And that's why you don't really hear much about backwards incompatible developments for C. What would be the point?
- nine_k 2y agoOK, don't call it C, call it C[*]. It will accept any existing C program unmodified. With a per-file switch, say, #define __FEATURE_WEAK_ARRAYS, it will start to discriminate T* and T[], make it an error to mix them in assignments, or to pass one instead of the other if both the function definition and the function call are in files with this feature on. It will not complain about functions defined elsewhere. Then, say, #define __FEATURE_STRICT_ARRAYS the compiler will complain about mixing arrays and pointers as function arguments, no matter where the function is defined. It would require updated stdlib headers, for instance. Additionally, #define __FEATURE_MULTI_ARRAYS would enable syntax for fixed-size multidimensional arrays, Fortran-style. Now uint8[3][2][10] foo; would allocate 60 elements, and access to foo[1][2][3] would involve one memory dereference, not three. More support would be needed: sizeof, support for slices, safe array copies and length checks. Nothing extraordinary. Having this implemented would make a terrific master's degree work.
- pklausler 2y agoWhy do you think that foo[1][2][3] requires more than one memory reference?
- nine_k 2y agoAFAIK in regular C a T[][][] foo would be a the same as T ** foo, so it gets implemented as a pointer to an array of pointers to arrays of pointers, each pointing to contiguous allocations of multiple Ts, each not necessarily near the other. So you need three dereferences to get to an element. T value = foo[1][2][3]; // becomes: foo -> (T **) (T **) -> (T *) (T **) (T *) ... (T *) -> (T) (T *) (T) ... (T) (T) <-- This one! This allows for jagged arrays, yay! So useful. This is in stark contrast to a Fortran-style array, which is allocated as one contiguous piece, all dimensions folded up for linear access with one dereference.
- deleted 2y ago[deleted]
- 2y ago
- skissane 2y ago> Because you can't do that and still call the resulting language C You could if you introduced a new type of "safe array". e.g. int[] is a traditional C array which decays to int* int[@] is a "safe C array" which is syntactic sugar for struct { size_t __count; int* __items; }, and as such can't decay int[] and int[@] would not be directly interoperable, except by converting both to int* – maybe casting an int[@] to int* would automatically extract the __items member. (The [@] syntax was chosen at random, if you don't like it, pick something else.)
- pif 2y agoYou can define such a struct yourself. You do not need to modify the language.
- SpaghettiCthulu 2y agoBut your struct cannot provide an indexing operator (right?)
- adrianN 2y agoBy having it defined at the language level you increase the chances that your dependencies use the same struct.
- orf 2y agoSo why do we have so many issues with arrays then, since everyone can individually fix it themselves? Hmm…