16 ms·
C – Preliminary C2x Charter
- grabcocque 11y ago(f) Make support for safety and security demonstrable "Demonstrable" seems to be a bit of weasel-wording there, but for the life of me I don't see how you make C demonstrably safe and secure without ending up with something that is almost, but not quite, entirely unlike C.
- pcwalton 11y agoWell, "safe" and "secure" can be relative terms, and C definitely could be safer. For example, null pointers could be defined to trap and -fwrapv could be blessed by the Standard as a mode that all compilers must support. I agree with you of course that C will never be memory-safe either in theory or in practice while still remaining C. (The same goes for C++, despite popular belief.)
- fweespee_ch 11y agoI'm sorry but open-std is a terrible, terrible name.
- unwind 11y agoThis is cool! I'm a pretty hardcore C programmer (been using it as my absolute main and favorite language for over 20 years), yet I find it hard to come up with some wishes for what I'd like to see. Not sure how to interpret that, perhaps it's just indicative of a certain ... conservatism common in old people? :) Scary thought! To be brutally concrete, I sometimes wish I could write someting like this: do { const bool flag = do_something(); ... ... } while(!flag); That'd be very useful, but of course in current standards it's not possible since 'flag' isn't valid outside the scope it's declared in. So now we have to pre-declare 'flag' before the loop, breaking const-cleanliness too of course. This is obviously not a show-stopper, it's a minute thing. But it would be so nice! :) Some support for automatic type inference would be nice, since most right-hand-side expressions have a type anyway it would be cool to be able to write auto x = 3; and have the type of 'x' be 'int' since that is the type of the literal '3'. Of course re-using "auto" like this would break their guiding principle, but it would look great (and, I think, somewhat mimic what C++ has done to that keyword). Does anyone have some better ideas?
- alexhutcheson 11y agoFor your first case, why not: do { } while(!do_something()); Not trying to be snarky, I'd just like to understand :)
- mikeash 11y agoBecause it's often either like this: do { const bool flag = do_something(); do_something_else(); } while(!flag); Or like this: do { int whatever = get_some_data(); const bool flag = do_something(whatever); } while(!flag);
- p1esk 11y agoSomeone mentioned this instead: while (true) { const bool flag = do_something(); if (!flag) break; } Is it not what grandparent wanted?
- mikeash 11y agoYes, that would do it. It would just be nice to have it be better supported in the language rather than working around it like this. Any time you introduce break or continue into a loop you're making it more difficult to follow what's going on, since suddenly the exit condition can be anywhere. Not a big deal, especially if there's only one and it's right at the end, but mildly annoying that it can't be expressed more naturally.
- dalailambda 11y agoWhile some might claim this goes against the spirit of C, I think minor support for generics(enough to implement a type safe dynamic array e.g. vector) would be really useful. And if this did monomorphisation, then performance would still be great.
- adrusi 11y agoHow about just type parameters that let you implicitly get sizeof parameters and pass function pointers without having to unportably cast them.
- TerryADavis 11y agoI made God's official language, HolyC. God says... dissonant Tehran inexpert offshoot Hapsburg's Elizabethan's confidants eunuch smattering tousling rubles replacement's patios surging grisly tremor's passive's Urban's symphonic severing Colbert's numeric inability's biofeedback conceptualize lotions champed icebreaker weal's trestle's antivirals symbolizing
- adrianN 11y agoIt would be nice if they incorporated some suggestions from the Cerberus project to make it clearer what is defined and undefined behavior. https://www.cl.cam.ac.uk/~pes20/cerberus/ https://www.cl.cam.ac.uk/~pes20/cerberus/
- cremno 11y agohttp://www.open-std.org/jtc1/sc22/wg14/www/docs/PreLondon2016.htm http://www.open-std.org/jtc1/sc22/wg14/www/docs/PreLondon201... >N2012 2016/03/10 Sewell, Clarifying the C Memory Object Model >N2013 2016/03/10 Sewell, C Memory Object and Value Semantics: The Space of de facto and ISO Standards >N2014 2016/03/10 Sewell, What is C in Practice? (Cerberus Survey v2): Analysis of Response >N2015 2016/03/10 Sewell, What is C in practice? (Cerberus survey v2): Analysis of Responses - with Comments
- comex 11y agoMy #1 desired feature for a future C standard is statement expressions, like the GNU extension. They make it much easier to avoid issues like multiple evaluation when writing macros. Typeof would be nice too - combined with statement expressions, it adds some capability for type generic macros without having to explicitly list all the types ala _Generic (which was standardized in C11 but which nobody uses). More broadly, while I'm not sure if it really fits in C, it would be cool to see some kind of lambda function support, along the lines of Apple's "blocks" extension.
- JoshTriplett 11y agoAgreed on both statement expressions and typeof; those seem like they could and should be standardized exactly as currently implemented. I'd like to see blocks/lambdas standardized, but I'd want to see a second implementation first. I also hope for better properties than those of the Apple blocks extension; I realize C does manual resource management, but the lifetime issues in blocks seem particularly worse even by C standards.
- noobermin 11y agoHow about continuations? Or is that too far...
- jeremycw 11y agoI don't understand why these committees are so dead set on maintaining backwards compatibility with existing code when most compilers will support flags for compiling with old standards anyway. As long as you don't break binary compatibility I really don't see the issue.
- EFruit 11y agoIf I could change C, I would look closely at Go. To be more precise, I would - Quit separating definition and implementation (.h & .c vs. the singular .go) - Implement multiple returns - Replace #include with something a bit closer to Go's import (Package name and in-body identifier are decoupled) - Methods on any user-defined type - Finally, something namespace-like because library_thing_return_t *library_thing_doing_something_else(libraty_thing_param_t *in) seems unsustainable to me.
- coliveira 11y agoPeople who want to program in Go are writing code in Go. People who want to program in C++ are writing code in C++. The C standard should improve the language we have, not try to emulate some other existing language.
- EFruit 11y agoNote that I didn't say I want to use Go, nor are all my points taken from Go (namely the namespace feature). I did not mention automatic memory management, I did not say the standard library needs to handle XML, and I still did not advocate that the syntax be so strict.
- cyphar 11y ago.h and .c separation is important for shared libraries (you know, that thing that you can't really do in Go). I would like it if headers had some stronger requirements (since you can put any code in a header, which is quite bad).
- pcwalton 11y ago> .h and .c separation is important for shared libraries (you know, that thing that you can't really do in Go). Why are header files necessary for dynamic linking? To name one of dozens of examples, Java has dynamic linking and has no header files.
- xenadu02 11y ago> .h and .c separation is important for shared libraries No it isn't. That's a completely orthogonal issue. The compiler is perfectly capable of generating the equivalent of a public header if the implementation has a way to specify visibility.
- groovy2shoes 11y agoAll I really want is C89 with stdint.h and safe(r) string handling routines (strncpy, snprinf, etc.). Hold the VLAs and the stdbool.h and the what-have-you.
- GFK_of_xmaspast 11y ago(a) https://randomascii.wordpress.com/2013/04/03/stop-using-strncpy-already/ https://randomascii.wordpress.com/2013/04/03/stop-using-strn... (b) Can't you just use the parts of c99 that you want.
- groovy2shoes 11y ago(a) I'm aware, but thanks. (b) Use? yes, but only when I'm not using a library that relies on the parts I don't want. Implement? not really, since users expect their compilers to conform to the standards. Rely on for portable code? no, since not all compilers support C99 and many of those that do actually only support some subset. For now, I'm using C89 with my own safe string routines and a configure script to generate the bits of stdint.h that I need.
- TickleSteve 11y agowhich compilers aren't supporting C99 now? I keep hearing this argument but I haven't had that issue at all in recent years.
- groovy2shoes 11y agoMSVC and a lot of embedded compilers. Not to mention, I still have to support systems that are using rather old compilers.
- TickleSteve 11y agoI've got 25+ years experience in realtime/embedded work and I have to disagree with you there. all compilers I can think of have been C99 compliant for a number of years now. MSVC is compliant now also.
- cbsmith 11y agoThe part where I see that after 1999 events have finally unfolded such that internationalization is only NOW considered important is... disappointing.
- TorKlingberg 11y agoThat principle was added in 1994.
- cbsmith 11y agoJeez... I totally misread that.
- kps 11y agoInternationalization was considered important for C89… which yielded regrettable inventions like trigraphs and wchar_t.
- cbsmith 11y agoUmm... wchar_t was not part of C89. It was added later. I think it was a supplement rolled out half way between C89 & C99, mostly as a consequence of a lot of platforms embracing native unicode interfaces (I seem to recall it was released just as Unicode 2.0 was coming out and making it so fixed width glyphs were no longer a thing). ...and digraphs & trigraphs had to do with different terminals/text editors that didn't have keys/characters for certain language symbols. Last I checked it wasn't really about internationalization, but rather the rather insane variance of character sets just for english (like EBCDIC).
- kps 11y agoReally? I'll have to check my paper copy at home, but Wikipedia seems to agree, with a quote from the standard: https://en.wikipedia.org/wiki/Wide_character#C.2FC.2B.2B https://en.wikipedia.org/wiki/Wide_character#C.2FC.2B.2B Maybe it was in C90 (ISO) but not C89 (ANSI)? For trigraphs see the Rationale at http://www.lysator.liu.se/c/rat/b.html#2-2-1-1 http://www.lysator.liu.se/c/rat/b.html#2-2-1-1
- rwmj 11y ago__attribute__((cleanup)) please. It's used by systemd now and is supported by gcc and clang. It makes a real difference to code, avoiding masses of cleanup along error paths.
- JoshTriplett 11y agoAgreed. __attribute__((cleanup)) provides a way to do block-scoped cleanup of each variable and eliminate the "tear down in reverse order in each error path" or "tear down in reverse order with goto labels" pattern.
- haberman 11y agoI have never seen this before but was just reading about it. It appears to run unconditionally when the scope is exited though: how do you prevent it from tearing down even in the success case?
- rwmj 11y agoTearing down in the success case is a feature, not a bug! If you don't want cleanup along the success path (eg if you're returning an allocated string), don't use cleanup on the returned variable. However that does point to the one problem with attribute((cleanup)). If you consider code like this (using the systemd macros): int f (void) { _cleanup_free char *s1; _cleanup_free char *s2; s1 = strdup ("foo"); if (!s1) return -1; /* crash */ s2 = strdup ("bar"); if (!s2) return -1; // ... return 0; } If strdup fails, it'll crash at the place I marked because it will try to free the uninitialized pointer s2. To get around that you have to initialize everything to NULL (since free(NULL) is legal). The problem then becomes that you end up "over-initializing" and "over-freeing". It would be nice to have a version of attribute((cleanup)) that would eliminate the call to the cleanup function if the pointer is NULL (or uninitialized?). But then you're relying on the compiler to do some kind of dataflow analysis, which is difficult in a standard (excludes simple compiler implementations), and may not even be possible because of the halting problem. This is basically the reason why you wouldn't want to use cleanups in kernel code, because performance is paramount there and unnecessary cleanup calls wouldn't be welcome.
- _kst_ 11y agoOld-style (non-prototype) function declarations and definitions have been officially "obsolescent" since 1989. Perhaps C2x can finally get rid of them.
- _wmd 11y agoThis would break the mandate of allowing C90 programs to run "largely unchanged" (see text)
- _kst_ 11y agoTrue, but none of the 14 listed principles is absolute. C2x compilers probably would (and could be encouraged to) accept old-style declarations and definitions in some non-conforming mode. They could even be accepted in conforming mode as long as the compiler warns about it (only a diagnostic is required).
- dallbee 11y agoI'd just like something better than _Generic and (void *) as our only ways to do generics. That's my one feature. Too bad that's not likely to happen, ever.
- dzdt 11y agoC needs to cut down on the instances of undefined behavior. Mostly these should become implementation-defined with some restrictions that the implementation should do one of the expected things. For instance, if you overflow an integer, the compiler should not be allowed to assume that code branch is unreachable, or to conjure nasal demons. Instead the result should be an implementation-defined integer or a jump to an implementation-defined exception handling routine. C should be predictable!
- pcwalton 11y ago> C needs to cut down on the instances of undefined behavior As someone who's worked on compilers a good bit, I disagree (and this is my favorite meme to argue against lately). You need that undefined behavior for performance. > For instance, if you overflow an integer, the compiler should not be allowed to assume that code branch is unreachable, or to conjure nasal demons. You need to be careful to not destroy loop trip count detection. > Instead the result should be an implementation-defined integer Not good enough. Loop trip count detection destroyed. > jump to an implementation-defined exception handling routine. Unacceptable for performance. Probably a 3x loss.
- microcolonel 11y agoI think that the reason people want this stuff is that they don't understand how much effort it takes to prove that underlying UB is not triggered in a branch and optimize out checks. Code size would explode, too; decimating the usefulness of embedded platforms, and eviscerating instruction caches. In that way, it would also be an ecological disaster.
- regehr 11y agoMeanwhile, Java runs pretty fast.
- pcwalton 11y agoJava doesn't suffer from these a bunch of these limitations, though, especially around aliasing. That makes a big difference. (Though signed indexing is still an issue in Java, unfortunately…)
- loeg 11y agoRemove VLAs from the language. They were a mistake.
- codys 11y agoVLAs provide a very useful way to avoid making temporary allocations using malloc()/free(), allowing (generally) better speed & avoiding leaks. Why do you believe they are a mistake?
- pascal_cuoq 11y agoBecause malloc() can signal failure to allocate by returning a null pointer. VLAs make it impossible to handle a failure to allocate: there is no interface to indicate what the program should do when it happens. You can only follow the declaration of a VLA with code that assumes that the allocation succeeded.
- yongjik 11y agoBut you can say the same about function calls: it may trigger stack overflow, but there's no interface to tell what to do in that case.
- uxcn 11y agoThis is why I avoid allocating large VLAs, and using them in deep call stacks in general. There's a diminishing return for allocating on the stack beyond a certain point anyway (roughly around a page). Having a mechanism to abstract this might be nice, but these are things people should hopefully be aware of before using VLAs. std::dynarray has been a bit polarizing though.
- _kst_ 11y agoExactly the same thing applies to fixed-size arrays. If you define a local array of N elements, there's no defined way to signal an allocation failure whether N is a compile-time constant or not.
- 11y ago
- richard_todd 11y agoI was curious about this statement: > The Standard is currently written in troff, which is subject to increasing bit rot as the tools for formatting it evolve. What exactly is bit-rotting? There are multiple maintained troff's out there, and if they are breaking backward compatibility regularly it's news to me.
- 21 11y agoUsing formats which became less popular and well supported can be considered bit-rotting. For example, having .PCX files in some project today instead of .PNG could be considered a form of bit rotting, because less and less tools support .PCX
- uxcn 11y agoOne minor thing that should hopefully be considered... a %b/%B conversion for printf et al. It's useful to print binary representations of things (debugging, conversion, etc...). A number of libc implementations support it as an extension. Forcing people to re-implement it outside of printf is a bit obnoxious considering how simple it is, and that there are already hexadecimal and octal conversions.
- _kst_ 11y agoAnd "0b11001001" constants.
- rkangel 11y agoNamespaces please!
- jws 11y agoI've become a heavy user of a number of clang extensions, __attribute__((cleanup)) __attribute__((overloadable)) … are now indispensable to me. Cleanup I use for both object lifetime management (when it fits that model), and lock management. Typically a "get access" type of function will take the lock and return the pointer to the object. Then when that pointer goes out of scope the lock can be freed. overloadable is perfect for keeping names under control. Consider if you have a bunch of structs for encoding various bit arrays. Maybe 32, 64, and 1024 bit long. Each has functions for working on it, so you either prefix all the functions with bit32_, bit1024_ or you pick a letter suffix, e.g. bitset(), bitsetl(), bitseth() (huge?), and try to make the programmer remember them all. With overloadable functions I get to use the same simple name for the operation and which implementation you use underneath is irrelevant. I think I'd like to go one step further and sugar up the syntax so… variable.func(a,b) <----> func( variable,a,b) … but Mr. Stroustrup might call me names. But darn it, sometimes you want to think of your objects in different ways. I'd be using lisp if I wanted everything the same. (Actually, I suppose Kernel, and laughing at the lisp users who think they have uniformity.) It doesn't have to be ".", go ahead an create an "=>" notation if that helps with the ambiguity of structure reference. (No dynamic dispatch here. Just leverage overloadable.) And here is the big one: Thread Safety Analysis. This has the potential to eliminate huge swathes of runtime problems in multithreaded code and even calling convention problems in single threaded code. In a nutshell, you can annotate your program to make statements about objects. You can say an operation ACQUIRE's an object (takes a lock), and that another operation RELEASEs an object. Then you can declare that other options REQUIRE that the object be in the ACQUIREd state. There is more, such as declaring that a the execution is currently in a state and then restricting its ability to perform operations based on that. The current implementation is probably bit rotting in gcc, and the clang version seems to be missing some important bits to making it useful. The C++ end of it apparently works for Google with their Android coding conventions, but the C end of it doesn't quite do it for me. I think with perhaps letting a function declare that its return value is ACQUIRE()d I might be able to put it to use. (And fixing the bit where it doesn't play well with __attribute__((cleanup)) ). But the working group has a '2' in the name. We have 4 years. And one more huge one: PLEASE add a paragraph to the spec that says: "undefined" is NOT license for some language lawyer compiler writer to kill your dog, burn your garden, erase your disk and return 42 from the main program. Undefined should mean "we understand different architectures and compilers might prefer to do this differently, implement something SANE and warn the user that they are on squishy ground".
- entity64 11y agoWhat about templates for C? Has this been proposed before? I'd love to write function templates, and templated structs would make implementing generic code so much easier and cleaner.
- deleted 11y ago[deleted]
- richm44 11y agoI'd like a standardised function to clear a block of memory that is guaranteed to not be optimised out, and a constant time compare function.
- algorithm314 11y agosupport binary literals with 0b prefix. Also include rotate ,count leading zeroes,count trailing zeros and popcount as functions.
- microcolonel 11y agoCyclone-style never-NULL pointers and bounded pointers would be interesting, especially if completely optional. They could be incrementally added to sub-trees of a risky codebase (like a parser) but not poison your ultimate ability to do pointer arithmetic.
- uxcn 11y agoAnother minor thing I think belongs in the C standard is bswap. For such a common operation that's necessary for portable code, I personally don't understand why it hasn't been defined in either the C or C++ standard. Currently, the only compiler I'm aware of that optimizes a bswap correctly is LLVM, which leaves a lot of code in the cold Aside from requiring people to write their own bswap, which is fairly maligned [1] for good reason, It leaves out a reasonably important optimization or potentially requires excess maintenance (platform libs, intrinsics, etc...) for people who do need portable code (the main reason for bswap). I think languages are starting to take the place of platform independent interfaces, and my personal opinion is that bswap is fairly low hanging fruit. Given that one of the stated goals of C is portability, I think it fits well within the mandate. [1] http://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html http://commandcenter.blogspot.com/2012/04/byte-order-fallacy...