44 ms·
Tell HN: C Experts Panel – Ask us anything about C
Hi HN,
We are members of the C Standard Committee and associated C experts, who have collaborated on a new book called Effective C, which was discussed recently here: https://news.ycombinator.com/item?id=22716068 https://news.ycombinator.com/item?id=22716068. After that thread, dang invited me to do an AMA and I invited my colleagues so we upgraded it to an AUA. Ask us about C programming, the C Standard or C standardization, undefined Behavior, and anything C-related!
The book is still forthcoming, but it's available for pre-order and early access from No Starch Press: https://nostarch.com/Effective_C https://nostarch.com/Effective_C.
Here's who we are:
rseacord - Robert C. Seacord is a Technical Director at NCC Group, and author of the new book by No Starch Press “Effective C: An Introduction to Professional C Programming” and C Standards Committee (WG14) Expert.
AaronBallman - Aaron Ballman is a compiler frontend engineer for GrammaTech, Inc. and works primarily on the static analysis tool, CodeSonar. He is also a frontend maintainer for Clang, a popular open source compiler for C, C++, and other languages. Aaron is an expert for the JTC1/SC22/WG14 C programming language and JTC1/SC22/WG21 C++ programming language standards committees and is a chapter author for Effective C.
msebor - Martin Sebor is Principal Engineer at Red Hat and expert for the JTC1/SC22/WG14 C programming language and JTC1/SC22/WG21 C++ programming language standards committees and the official Technical Reviewer for Effective C.
DougGwyn - Douglas Gwyn is Emeritus at US Army Research Laboratory and Member Emeritus for the JTC1/SC22/WG14 C programming language and a major contributor to Effective C.
pascal_cuoq - Pascal Cuoq is the Chief Scientist at TrustInSoft and co-inventor of the Frama-C technology. Pascal was a reviewer for Effective C and author of a foreword part.
NickDunn - Nick Dunn is a Principal Security Consultant at NCC Group, ethical hacker, software security tester, code reviewer, and major contributor to Effective C.
Fire away with your questions and comments about C!
- eqvinox 7y agoWhat's the best way to deal with "transitive const-ness", i.e. utility functions that operate on pointers and where the return type should technically get const from the argument? (strchr is the most obvious, but in general most search/lookup type functions are like this...) Add to clarify: the current prototype for strchr is char *strchr(const char *s, int c); Which just drops the "const", so you might end up writing to read-only memory without any warning. Ideally there'd be something like: maybe_const_out char *strchr(maybe_const_in char *s, int c); So the return value gets const from the input argument. Maybe this can be done with _Generic? That kinda seems like the "cannonball at sparrows" approach though :/ (Also you'd need to change the official strchr() definition...)
- DSMan195276 7y agoThe straight-forward approach is just two functions, one with `const` and one without (You can make one of them `static inline` around the other and do some casting to avoid implementing the same thing twice). With that, selecting the correct function via `_Generic` should be possible (`_Generic` is a bit fiddly, but matching on `const char * ` and `char * ` should work just fine for this), and for the most part this is actually an/the intended use case for `_Generic` - it's basically the same as the type-generic math functions, more or less.
- DougGwyn 7y agoMany uses of strchr do write via a pointer derived from a non-const declaration. When we introduced const qualifier it was noted that they were actually declaring read-only access, not unchangeability. The alternative was tried experimentally and the consequent "const poisoning" got in the way.
- pascal_cuoq 7y agoSpeaking as someone who is not in the committee but has observed trends since 2003 or so, I would say that solving this problem is way beyond the scope of evolutions that will make it in C2a or even the next one. There are plenty of programing languages that distinguish strongly between mutable and immutable references, and that have the parametric polymorphism to let functions that can use both kinds return the same thing you passed to them, though. C will simply just never be one of them.
- LHopital 7y agoI'll pass! Thanks though.
- dang 7y agoPlease don't do this here.
- deleted 7y ago[deleted]
- deleted 7y ago[deleted]
- DougGwyn 7y agoSome simple instructions about how to use a thread for conversation would be appreciated. Thanks!
- rseacord 7y agoNothing to it! Just hit the reply button on comments you want to respond to. You can also upvote anything you like by clicking on the up arrow to the left of the comment.
- DougGwyn 7y agoOkay, is there a starting thread for today's C Experts panel? I miss the old net newsgroups.
- dang 7y agoThe thread is https://news.ycombinator.com/item?id=22865357 https://news.ycombinator.com/item?id=22865357, which is the page you've been posting to. It's now listed on the front page of the forum, https://news.ycombinator.com/ https://news.ycombinator.com/, which is a list of the stories people have upvoted today. You're not the only person who misses the old newsgroups! The format that Hacker News uses is one that became sort of standard on the web in the early 2000s. It works differently than usenet did, but you get threaded comments in the sense that replies are nested under the posts they're replying to.
- pascal_cuoq 7y agoThere are very little formatting options when writing posts, for better or for worse: https://news.ycombinator.com/formatdoc https://news.ycombinator.com/formatdoc
- faehnrich 7y agoI've been waiting for a book on C from No Starch Press, so I'm really excited for this one. This might not be too deep a question on the C language in regards to this book, but I've been wondering, why did you decide to have an eldritch horror as the book's cover?
- rseacord 7y agoIt's a longish story, but people do seem to like the cover. We started equating the idea of C == Sea, so we had some early drawings of the robot riding various undersea creatures including a giant squid. I thought that looked overly phallic, so I suggested the robot ride Cthulhu instead, an unofficial mascot of NCC Group.
- faehnrich 7y agoI like how Cthulhu is shown as kind of a guide for the robot. The C==Sea brings to mind the book Expert C Programming: Deep C Secrets.
- beardedwizard 7y agoDeep c secrets, a classic.
- cptnapalm 7y agoWait, they put Cthulhu on the cover of a programming book? I'm buying it.
- rseacord 7y agoSo what do people think about having a feature in the C language akin to the defer statement in GoLang? The GoLang defer statement defers the execution of a function until the surrounding function returns. The deferred call's arguments are evaluated immediately, but the function call is not executed until the surrounding function returns. It looks like an interesting mechanism for cleaning up resources.
- deleted 7y ago[deleted]
- NickDunn 7y agoIt could be very useful for cleaning resources. I've never used GoLang, but can see how that could be useful in various circumstances. As we're talking about C, I suspect a feature like that, with the potential to make things safer, would also enable the unwary to shoot themselves in the foot more easily.
- majke 7y agoI personally don't like golang's defer. For me it obscures the flow of the program. For example when I acquire a lock, I like to see where exactly it's released. For me "defer" only makes sense in the context of exceptions, basically as an equivalent to "finally". This is a slippery slope though, since golang's exceptions are, for a reason, rudimentary.
- bokwoon 7y agoHow about deferring until the surrounding block scope ends? In Go you can get around the limitation of defer only executing at the end of a function by wrapping any arbitrary section of code inside an immediately executed anonymous function. But in C I'm not sure that's possible so maybe one could declare a new block scope instead to control when defer kicks in.
- pascal_cuoq 7y agoIt sounds like the __attribute__((cleanup(…))) already offered by GCC is similar to this. I probably won't have time to investigate the differences while the AMA is ongoing though.
- papermachete 7y agoHow and why will C combat Rust?
- pascal_cuoq 7y agoIn my opinion, the two languages are going to co-exist for a long time. C has billions of lines of legacy software written in it… In recent news, COBOL developers were sought after in order to update existing COBOL software, so the same thing will happen with C, perhaps to the end of humanity (I have become pessimistic as to humanity's future). There are pieces of software that should be given priority for a rewrite in Rust, but most of C software is never going to be rewritten, because there is simply too much of it. Therefore, even if C did not have any advantage of its own over Rust, there would still be legacy software to maintain and to extend. The advantages of C include that sometimes, an embedded processor with a proprietary instruction set is provided by the chipmaker with its own C compiler, which is the only compiler supporting the instruction set; that C is still currently used to write the runtimes of higher-level languages (I'm familiar with OCaml, but it isn't too much of a stretch to imagine that the runtimes of Python, Haskell,… are also written in C).
- sramsay 7y agoThere's tons of legacy C around, we have to maintain it, it's not ideal unless you're on some niche platform, lots of stuff should probably be written in a better language . . . I sincerely hope this is not the general attitude of the standards committee. Some of us actually prefer C, and would like to see the language continue to flourish.
- pascal_cuoq 7y agoNote that among the C experts participating in this AMA, I am not one who is in the standardization committee. At 14:59 EDT, just before the AMA was posted, we were joking between ourselves about me having to post this disclaimer but I guess there was a hidden truth in the joke.
- cesarb 7y ago
- sgawlik 7y agoWhen you're looking at an unfamiliar C code base for the first time, how do you approach it? Which files do you look for? Which tools to you open up immediately?
- DougGwyn 7y agoIt all depends on how organized previous workers were, and what your goal is for a modification of the source text. Often, headers (dot-h files) document the data structures and interfaces.
- jhallenworld 7y agocscope can help
- DougGwyn 7y agoYes, I have found it helpful. One nice feature is that it uses a character-terminal interface, not a platform-specific GUI.
- clarry 7y agoIs there a vim-style cscope interface for emacs? I hate that xcscope brings up its own persistent buffers (replacing other buffers that I had deliberately placed on the screen). Vim, conveniently, just pops up the cscope interface when I need to enter some input, and then hides it away. Also I don't think xcscope works with evil's tag stack whereas in vim, I believe, you can just return to where you were with ^T, whether using ctags or cscope.
- rseacord 7y agoThis depends a bunch on what your goals are. There are no specially named files, so looking for a particular filename is not particularly useful. It is sometimes informative to find the file containing the main, but not always. My job at NCC Group involves a lot of code reviews, so frequently the files that are of interest to me are the ones that contain the most defects. I typically identify these by compiling with compiler warnings turned up and warning suppression turned down. I'll frequently also make use of static and dynamic analysis, including the GCC and Clang sanitizers.
- rudchenkos 7y agoAre any concurrency primitives planned for introduction in future C revisions?
- AaronBallman 7y agoWe currently have not seen papers proposing to add new concurrency primitives for C2x, but we have been actively working on the concurrency object model and would welcome proposals for new primitives or concurrency-related fixes. One goal is to re-unify C with the concurrency object model used by C++ to make std::atomic<T> and _Atomic(T) be ABI compatible as intended in C11. Some small fixes in this area are the removal of ATOMIC_VAR_INIT, clarifying whether library functions can use thread_local storage for internal state, and things along those lines. However, we expect there to be more efforts in this area as we progress the standard.
- jpfr 7y agoC11 has seen new features, such as Generic Selection. Is the current language standardization converging (just adding clarifications, removing the surface for undefined behavior, etc.) or is C still growing with new features? In other words, will the C standard be effectively “done” at some time in the future?
- rseacord 7y agoI would say no, that we are still adding new features. Aaron Ballman was responsible for adding attributes to the C2x (he can tell you more). We're also looking at #embed feature to incorporate binaries the way that #include incorporates text.
- msebor 7y agoFixing minor bugs or inconsistencies and reducing the number and kinds of instances of undefined behavior are some of the efforts keeping the C committee busy. Reviewing proposals to incorporate features supported by common implementations is another. Aligning with other standards (e.g., floating point) and improving compatibility with others (C++) is yet another. In general, when an ISO standard is done it essentially becomes dead. So for the C standard to continue to be active (on ISO's books) it needs to evolve.
- ken 7y agoIt's interesting to hear the standardization perspective, because it's pretty much the opposite of my perspective as a user. I see the classic path of any programming language -- regardless of standardization -- is to continuously add features until it's too big and complex that nobody wants to deal with it any more. Then it's replaced by a newer, simpler language that takes the important bits and drops the unnecessary complexities. At that point, everybody sees that the older language was barking up the wrong tree, and they stop wasting time on it. It's not the cessation of language change that causes language death -- that's merely a symptom. You can't keep a language alive simply by changing it every year. Some people sure have tried. Alternatively, until it's evolved so much that there is so much diversity of implementation that simply knowing a library is written in "language X" doesn't tell me much about how it's written, or whether I can use it in my program which is also written in "language X". Then again, C is the exception to every rule, so maybe we can keep piling on features indefinitely, and people will have to use it (even if they don't like it), for the same reason they started using it decades ago (even if we didn't like it).
- overfl0w 7y agoCan memory safety be ensured in the C programming language? By static analysis at compile time for example?
- deleted 7y ago[deleted]
- pascal_cuoq 7y agoIt is possible to guarantee that a C program does not have any undefined behavior, which includes all the memory errors that are often also security vulnerabilities. “Static analysis” may be the wrong name to classify the tools that work in that area, because “static analysis” is usually used for purely automatic tools, whereas the tools used to guarantee the absence of undefined behaviors are not entirely automatic except for the simplest of programs. Results of a static analyzer are often characterized in terms of “false positives” and “false negatives”. It is a possible design choice to make an analyzer with no false negatives. It is absolutely not impossible! (Some people think it is fundamentally impossible because it sounds like a computer science theorem, but it isn't one. The theorem would apply if one intended to make an analyzer with no false positives and no false negatives—and if computers were Turing machines.) Analyzers designed to have no false positives are called “sound”. In practice, this kind of analyzer may prove that a simple program is free of Undefined Behavior if the program is a simple example of 100 lines, but for a more realistic software component of at least a few thousand lines, the result will be obtained after a collaborative human-analyzer process (in which the analyzer catches reasoning errors made the human, so the result is still better than what you can get with code reviews alone). Here is what the result of this collaborative human-analyzer process may look like for a library as cleanly designed and self-contained as Mbed TLS (formerly PolarSSL): https://trust-in-soft.com/polarSSL_demo.pdf https://trust-in-soft.com/polarSSL_demo.pdf?
- pantalaimon 7y agoWill C eventually get something like C++' constexpr?
- AaronBallman 7y agoC has some basic support for constant expressions already, but there has not yet been a proposal to bring 'constexpr' over from C++. Personally, I would love this feature to be in C!
- loeg 7y agoYou and me both!
- dktoao 7y agoThis is really the only thing that I really want from C++. It would be amazing if this could make the cut for a future spec. EDIT: I work on embedded systems, where C is king, and it seems like a spend an inordinate amount of time working with code generators that build simple tables. All of which could go away with this feature.
- enhray 7y agoWhy do you want it in C? What are your use cases? I’ve always thought that idiomatic C for constexpr would be to write the code you want to be executed at compile-time in a separate file(s), build it, execute and then #include the result in your program before building the final executable, adding a build step but keeping overall complexity minimal. This is different from C++ approach, where everything and the kitchen sink is added to the standard and then you have to issue errata for errata for the standard and hope that the compiler you have to use for your current platform is keeping up for the last changes.
- freemind 7y ago1. What is the easiest way to build cross-platform (native) GUI with C? 2. Why it is harder to find lgpl licenced libraries to access windows directories over network like jcifs pysmb (and libraries overall) when needed to close most part of software source to sell small softwares to businesses? 3. If you needed to combo C with another language to do everything you need to do forever and never look back what other language would that be?
- teleonorax 7y agoWhat's up with `strlcpy` and `strlcat`? Are they getting standardized?
- rseacord 7y agoNo one has proposed making these standard. I doubt they would gain much support as they are similar to the Annex K Bounds Checked Interface functions strcpy_s and strcat_s but not quite as good IMHO.
- rseacord 7y agoThere were a number of recent proposals to adopt various POSIX functions by Martin Sebor into C including: N2353 2019/03/17 Sebor, Add strdup and strndup to C2X N2352 2019/03/17 Sebor, Add stpcpy, and stpncpy to C2X N2351 2019/03/17 Sebor, Add strnlen to C2X He is lurking on this thread as well. These proposals can all be found in the document log at http://www.open-std.org/jtc1/sc22/wg14/www/wg14_document_log.htm http://www.open-std.org/jtc1/sc22/wg14/www/wg14_document_log...
- rseacord 7y agoThe results (from the minutes http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2377.pdf http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2377.pdf) 6.33 Sebor, Add strnlen to C2X [N 2351] Result: No consensus on putting N2351 into C2X. 6.34 Sebor, Add stpcpy, and stpncpy to C2X [N 2352] Result: No consensus to put N2352 into C2X. 6.35 Sebor, Add strdup and strndup to C2X [N 2353] Result: N2353 be put into C2X. The committee wants a proposal for the wide character versions of any POSIX functions voted in this meeting.
- rmind 7y agoThere have been some disagreements on strlcpy/strlcat (BSD vs glibc crowd), although by now the debate has died off and these functions are pretty widely used. Also, while here, it would be lovely to have strchrnul() included.
- 7y ago
- zabana 7y agoIs it worth it to learn C in 2020 ? Will it still be a prominent language for systems programming in the future ?
- stephencanon 7y agoYes. - Languages like Rust will gain more mindshare over the next decade, and be used in more and more new projects, but there are billions of lines of existing code in C, and those aren't going away. - Hardware architects, for better or worse, largely think about software in terms of [a somewhat dated and idealized mental model of] C. So if you want to be able to converse with architects (which anyone doing systems programming should want to do), you need to have some basic fluency with C.
- rseacord 7y agoC also has renewed interest around IoT programming and mobile devices
- wolf550e 7y agoI believe C will continue to be used as lingua franca after no one uses it to write software, and we're decades from even that point. You need to know enough C to interface with the OS, and enough C to talk about memory layout, memory management, dynamic libraries, ABI, etc. Most higher language runtimes need C, even with a self hosting compiler. Not being able to work on the C parts is limiting. You also need to know enough assembly to be able to understand what the compiler did with your own code, even if you never write assembly yourself. Not being able to compare the disassembly to the high level language to understand why it doesn't work (or is order of magnitude slower than expected) is limiting.
- knz42 7y agoWhat is the story behind the removal of VLAs from C99 in later revisions?
- DougGwyn 7y agoWhat removal? C11 section 6.7.6.2 specifies the semantics.
- cesarb 7y agoWhat the parent comment probably meant is that support for VLA was required in C99, but is no longer required in C11, so while code written for C99 could use VLAs without any special consideration, code written for C11 cannot depend on VLAs since it might not be present in all compilers.
- AaronBallman 7y agoVLAs are still present in C17 and have not been removed. They are, however, an optional feature with a truly weird (IMHO) feature testing macro. If '__STDC_NO_VLA__' is defined to 1, then the implementation does not support VLAs. IIRC, this macro was added to C11 along with a batch of other "these are optional" macros for atomics, complex, threads, etc. However, I don't recall whether C99 adopted the features as optional features and missed the feature testing macro, or if they were required features in C99 that we made optional in C11.
- stephencanon 7y agoComplex and VLA were required by C99, but made optional in C11. The others were new in C11.
- wuxb 7y agoI can't live without it.
- alerighi 7y agoThey did not remove them, but made them optional. Is a controverial feature, that can produce bugs, and are banned in a lot of project (one famouse, the Linux kernel).
- billfruit 7y agoI do find that C is difficult use for large programs. It there any thoughts that introducing features like namespaces. Another thing very cumbersome is to do in C is object creation; creating instantiable objects is possible very cumbersome. Is there some feature in the thoughy process to deal with it. To make it clear, in C we can create a data structure like a Stack or a queue easily. But if the program needs 10 stacks then presently no simple way of achieving it.
- DougGwyn 7y agoIn BRL's MUVES project, we used a 2-character prefix indicating category. E.g., all the external identifiers for our fancy memory allocator began with "Mm", where Mm.h documented the interface for the Mm package only. To minimize the external identifiers, one could make just the name of a container structure the sole entry access handle, with structure members pointing to the functions. Then use it like: #include <Mm.h> if ((new = Mm.allo(size)) == NULL) Er.abort("out of memory");
- jfkebwjsbx 7y agoTip: you can use four leading spaces to write code. Like this
- deleted 7y ago[deleted]
- steveklabnik 7y agoYou only need two! like this
- beefhash 7y agoNow that C2x plans to make two's complement the only sign representation, is there any reason why signed overflow has to continue being undefined behavior? On a slightly more personal note: What are some undefined behaviors that you would like to turn into defined behavior, but can't change for whatever reasons that be?
- rseacord 7y agoMaybe someone else can respond to this as well, but I feel like the primary reason signed overflow is still undefined behavior is because so many optimizations depend upon the undefined nature of signed integer overflow. My advice has always been to use unsigned integer types when possible. Personally, I would like to get rid of many of the trap representations (e.g., for integers) because there is no existing hardware in many cases that supports them and it gives implementers the idea that uninitialized reads are undefined behavior. On the other hand, I just wrote a proposal to WG14 to make zero-byte reallocations undefined behavior that was unanimously accepted for C2x.
- saagarjha 7y ago> My advice has always been to use unsigned integer types when possible. Unsigned types have their own issues, though: they overflow at "small" values like -1, which means that doing things like correctly looping "backwards" over an array with an unsigned index is non-trivial. > On the other hand, I just wrote a proposal to WG14 to make zero-byte reallocations undefined behavior that was unanimously accepted for C2x. You're saying that realloc(foo, 0) will no longer free the pointer?
- slavik81 7y agorealloc(foo, 0) was changed to no longer free in C99. A rant on the subject: https://github.com/Tarsnap/libcperciva/commit/cabe5fca76f6c38f872ea4a5967458e6f3bfe054 https://github.com/Tarsnap/libcperciva/commit/cabe5fca76f6c3...
- msebor 7y agoSome instances of undefined behavior at translation time can effectively be avoided in practice by tightening up requirements on implementations to diagnose them. But strictly speaking, because the standard allows compilers to continue to chug along even after an error and emit object code with arbitrary semantics, turning even such straightforward instances into constraint violations (i.e., diagnosable errors) doesn't prevent UB. It might seem like defining the semantics for signed overflow would be helpful but it turns out it's not, either from a security view or for efficiency. In general, defining the behavior in cases that commonly harbor bugs is not necessarily a good way to fix them.
- 0x09 7y agoNot about the language exactly, so maybe not fair game, but: how did you all find yourselves joining ISO? And maybe more generally, what's the path for someone like a regular old software engineer to come to participate in the standardization process for something as significant and ubiquitous as the C programming language?
- AaronBallman 7y agoGreat question! Joining the committee requires you to be a member of your country's national body group (in the US, that's INCITS) and attend at least some percentage of the official committee meetings, and that's about it. So membership is not difficult, but it can be expensive. Many committee members are sponsored by their employers for this reason, but there's no requirement that you represent a company. I joined the committees because I have a personal desire to reduce the amount of time it takes developers to find the bugs in their code, and one great way to reduce that is to design features to make harder to write the bugs in the first place, or to turn unbounded undefined behavior into something more manageable. Others join because they have specific features they want to see adopted or want to lend their domain expertise in some area to the committee.
- johannes1234321 7y agoRelated to that: C++ standards body seems to be quite open allowing non-members to participate (outside official votes, while respecting them when looking for consensus) is it just due to my limited observation or is the C group less open? Any plans in that regard?
- msebor 7y agoMost of us on the committee would like to see more participation from other experts. The committee's mailing list should be open even to non-members. Attendance by non-members at meetings might require an informal invitation (I imagine a heads up to the convener should do it).
- 7y ago
- jpfr 7y agoQuite a few new languages generate C code for the “backend” of their compiler. For example ATS and the ZZ language. This helps bringing these languages to embedded targets with closed toolchains (with an existing C compiler). Will there be developments to use a subset of C as a “portable assembly” in a standard way? Like there is WebAssembly for JavaScript.
- msebor 7y agoThat doesn't seem likely. There have been no proposals for anything like it and there is a general resistance to subsetting either C or C++ (the exception being making support for new features optional).
- emilfihlman 7y agoThank you for taking time to take questions! Have you ever considered or will you consider deprecating char, int, long, (s)size_t, float, double and etc in favour of specific length types? Will you ever add / have you considered adding [su]\d+ and f\d+ as synonyms for those mentioned stdint.h? Since char is signed on most platforms, arm eabi being an exception and even there it's really just a matter of compile time flags, will you ever just drop char from being able to be either and just say it's signed, as int is also signed? Will you ever define / have you considered defining signed overflow behaviour?
- rseacord 7y agoI don't think we'll ever deprecate char, int, long, float, double, or size_t. ssize_t is not part of the C Standard, and hopefully never will be as it is a bit of an abomination. The main driver behind the evolution of the C Standard is not to break existing code written in C, because the world largely runs on C programs. C does provide fixed width types like uint8_t, uint16_t, uint32_t, and uint64_t. These are optional types because they can't be implemented on implementations that don't have the appropriate word sizes. We also have required types such as uint_least16_t uint_least32_t uint_least64_t uint_least8_t
- deleted 7y ago[deleted]
- emilfihlman 7y ago>The main driver behind the evolution of the C Standard is not to break existing code written in C, because the world largely runs on C programs. If not deprecate, then at least make fixed width types as equivalent members to them, ie all char based apis should accept s8 (typedef signed char s8) and all int based apis should accept s32.
- rseacord 7y agoWell, there are number of problems with this proposal. For example, if your implementation defines int as a 16-bit type (which is permitted for by the standard) and you pass an int32_t, the value you pass maybe truncated if it is outside of the range of the narrower type. When programming, it is best to match the type of the API of the function you are calling for portability.
- rbultje 7y agoI'd love your opinion on the abundance of "undefined behaviour" (as opposed to implementation-defined, or some new incantation such as "unknown result in variable but system is safe") for relatively trivial things such as signed (but not unsigned) integer overflows. I've heard that this is to allow for non-twos-complement implementations. However, in practice, you notice that most people use ugly workarounds which lead to ugly code that (because of e.g. casting to unsigned and allowing the same overflow to happen anyway) only work correctly on twos-complement anyway. Is this intended to be addressed in the future in some way?
- stephencanon 7y ago> (because of e.g. casting to unsigned and allowing the same overflow to happen anyway) only work correctly on twos-complement anyway Unsigned arithmetic never overflows, and guarantees two's-complement behavior, because unsigned arithmetic is always carried out modulo 2^n: > A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type. (6.2.5, Types) Doing the computation in unsigned always does the "right thing"; the thing that one needs to be careful of with this approach is the conversion of the final result back to the desired signed type (which is very easy to get subtly wrong).
- shawnz 7y agoWrapping around the modulus to me is an "overflow", although maybe the spec doesn't use the word that way
- polishdude20 7y agoWhat is your favorite language other than C and why?
- pascal_cuoq 7y agoI answered a similar question in another thread: https://news.ycombinator.com/item?id=22866242 https://news.ycombinator.com/item?id=22866242
- shric 7y agoIs there a rule that any new proposals must already be a feature in an existing major implementation?
- beefhash 7y ago(Not one of the OPs:) Wasn't C11 Annex K, the notoriously failed bounds-checking interfaces, a example of not having an existing implementation?
- AaronBallman 7y agoAnnex K had an existing implementation from Microsoft. It wasn't a fully conforming implementation when C11 shipped, however (the specification drifted apart from the initial implementation).
- AaronBallman 7y agoYes, the C2x charter has this requirement: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2086.htm http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2086.htm
- shric 7y agoThanks, so from "Only those features that have a history and are in common use by a commercial implementation should be considered", this precludes stuff that may only exist in clang, gcc, glibc, etc.? If so, why?
- AaronBallman 7y agoI wouldn't read into "commercial" there, I think we meant "production-quality" instead. (We should fix that!) Basically, we prefer seeing features that real users have used as opposed to an experimental branch of a compiler that doesn't have usage experience. Knowing it can be implemented is one thing, but knowing users want to use it is more compelling.
- parenthesis 7y ago
- emilfihlman 7y agoWill you ever add / have you considered adding sane formatting options for fixed length variables in printf? Say %u32 or %s64 ? Have you considered adding access to structure members by index or by string name? Have you considered dynamic structures?
- AaronBallman 7y ago> Will you ever add / have you considered adding sane formatting options for fixed length variables in printf? Say %u32 or %s64 ? I'm not certain about the historical answer to this, but I do know that we're currently considering a proposal to introduce an exact bit-width integer type '_ExtInt(N)' to the language, and how to handle format specifiers for it is part of those discussions, so we are considering some changes in this area. > Have you considered adding access to structure members by index or by string name? Have you considered dynamic structures? I don't recall seeing any such proposals. I'm not familiar with the term "dynamic structures", what do you have in mind there?
- emilfihlman 7y ago>and how to handle format specifiers for it is part of those discussions, so we are considering some changes in this area. Please, please, please pick short and descriptive format specifiers, like %[suf]\d+, ie s64 v=somenumber; printf("%s64\n", v); _ExtInt(N) and PRIx64 etc look absolutely horrid. u?int\d+_t are also really bad, it would be great to have just [suf]\d+ as types, where \d+ is 8, 16, 32, 64 for [us] and 32 and 64 for f. >what do you have in mind there? Say like VLAs but structures with members that are dynamically defined and used.
- AaronBallman 7y ago> Please, please, please pick short and descriptive format specifiers, like %[su]\d+, ie That's my personal preference as well. Using the PRI macros always makes me feel sad. > Say like VLAs but structures with members that are dynamically defined and used. Ah, no, I don't recall any proposals along those lines. It's an interesting idea, and I'd be curious what the runtime performance characteristics would be vs what kind of new coding patterns would emerge that you couldn't do previously though!
- dboon 7y agoWhat are two or three C codebases that are elegantly and cleanly written, and that every mid-level C programmer should read for sake of knowledge?
- pascal_cuoq 7y agoI would recommend musl, although the style is a bit idiosyncratic in places: https://www.musl-libc.org https://www.musl-libc.org Mbed TLS, since I have it in mind from another thread, is also a pretty clean C library for the problem it tries to solve; it's a testament to its design that we (TrustInSoft, who had not participated to its development) were able to verify that some uses of the library were free of Undefined Behavior: https://tls.mbed.org https://tls.mbed.org
- uasm 7y ago> "I would recommend musl, although the style is a bit idiosyncratic in places: https://www.musl-libc.org" https://www.musl-libc.org" Opened a random part of musl out of sheer boredom. Here's what I see: https://git.musl-libc.org/cgit/musl/tree/include/aio.h https://git.musl-libc.org/cgit/musl/tree/include/aio.h A bunch of return codes #defined like so (see https://git.musl-libc.org/cgit/musl/tree/src/aio/aio.c https://git.musl-libc.org/cgit/musl/tree/src/aio/aio.c): #define AIO_CANCELED 0 #define AIO_NOTCANCELED 1 #define AIO_ALLDONE 2 #define LIO_READ 0 #define LIO_WRITE 1 #define LIO_NOP 2 #define LIO_WAIT 0 #define LIO_NOWAIT 1 Why weren't they using an enum instead? I wouldn't sign off on this code (and I don't think it lives up to best practices).
- pdw 7y agomusl is implementing POSIX. POSIX requires those constants to be preprocessor defines. (Generally, musl asssumes the reader is quite familiar with the C and POSIX standards, which makes sense since it's a libc implementation.)
- fanf2 7y agoPostgreSQL
- beefhash 7y agoC has been making strides towards complete Unicode support. I've been having trouble following along though: Am I correct in assuming that there's no actual multi-byte UTF-8 to UTF-32 Rune function and the best approximation depends on whatever wchar_t is? How would I best handle pure Unicode input and output scenarios on a "hostile" OS whose native character encoding is some EBCDIC abomination or a Windows codepage?
- loeg 7y agoProbably link libicu rather than rely on libc.
- rurban 7y agolibicu is a 40MB mess where you need only 5Kb of it. Only case folding and one normalization is needed, with tiny tables. Additionally the used UNICODE_MAJOR and _MINOR are needed. They are always years behind, and you never know which tables versions are implemented.
- loeg 7y ago-Wl,--gc-sections
- moonchild 7y agoConverting arrays of utf8-encoded char to arrays of utf32-encoded 'rune' would probably not do what you want. That still leaves e.g. combining diacritical marks as separate from the characters they modify. If you care about breaking up text into codepoints, you probably also care about that sort of thing. The base unit of unicode is the extended grapheme cluster. In order to actually convert text into extended grapheme clusters, however, you need to have a database that tells you what kind of codepoint each codepoint is. Since c is standardized less frequently than unicode, any kind of unicode or utf support from the specification would quickly get out of date.
- fanf2 7y agoAre you looking for mbstowcs() or mbtowc() ?
- Daemon404 7y agoWhat has been the rationale or hinderance for not adding locale-independent versions of various stdlib functions? Practically every second C codebase on earth has their own implementations of these at some point, and it remains a huge problem for e.g. writers of libraries, where you don't know how/where your library will be used.
- rwmj 7y agoTo clarify, do you mean functions like c_isalpha (part of Gnulib) which is like isalpha but only matches 7 bit ASCII characters?
- Daemon404 7y agoAn easy (and problematic) example is decimal separators (radix characters) being parsed or written differently based on locale.
- msebor 7y agoFirst, there needs to be a proposal for adding a feature (I'm not aware of one having been submitted recently). Second, any non-trivial proposed feature needs to have some existing user experience behind it. For libraries that typically means implementations shipping with operating systems or compilers (but successful third party libraries might also be considered). Finally, it also needs to appeal to people on the committee; that can be quite challenging as well. Many proposals that meet the first two criteria die because they simply don't get enough support within the committee.
- Daemon404 7y agoSounds mostly like the issue is nobody has bothered to submit a proposal for it then? (There is so much in-the-wild experience and code dealing with this issue, I cannot imagine the second point being problematic.) On the third point, I have trouble thinking of any technical objections to such proposal.
- ux 7y agoIs there any plan to deal with the locale fiasco at some point? Some hints on what I'm referring to can be found here: https://github.com/mpv-player/mpv/commit/1e70e82baa9193f6f027338b0fab0f5078971fbe https://github.com/mpv-player/mpv/commit/1e70e82baa9193f6f02... Unrelated, but I also miss a binary constant notation (such as 0b10101)
- pascal_cuoq 7y agoMany C compilers offer, as an extension, the very binary constant notation that you miss, as anyone who has worked on the front-end of a C static analyzer would tell you.
- ux 7y agoYes I'm aware. But we can agree it would be welcome in the standard, isn't it?
- pascal_cuoq 7y agoYes, if only so that we (as a category) do not have to discover it exists when already facing C programs that use it.
- OnACoffeeBreak 7y agoI know that we're not voting, but I miss a binary literal very much. I would also like a literal digit separator to improve readability. Verilog Hardware Description Language does that with an underscore [1]. For example, 0xad_beef to improve readability of a hex literal, and 0b011_1010 to improve readability of a binary literal. 1: http://verilog.renerta.com/mobile/source/vrg00020.htm http://verilog.renerta.com/mobile/source/vrg00020.htm
- jfkebwjsbx 7y agoIf they pick this up, they will likely use C++'s syntax/rules.
- 7y ago
- orsenthil 7y agoWhy is still the learning curve for C so high? * Why can't the learning curve be solved using tools? * Why don't we actively promote more higher level languages which are implemented in C (by fewer people)?
- pantalaimon 7y agoDo you find the learning curve for C to be high? I find it quite the opposite. It's a simple language with only a few concepts to learn, once you got those, that's it. There might be some preprocessor tricks you'll pick up later, but the base language and library is pretty comprehensive IMHO.
- orsenthil 7y agoC is indeed a very small language. But the expressive power of C for real-world problems brings a huge learning curve in terms of organization, tracking, and understanding.
- darepublic 7y agoComing from python/js I found it to be high. Mostly because of the memory management/ making sure I call free correctly etc. In many cases where I would plow ahead in programming, with C I had to stop and would feel dread. A lifesaver for me was using C/C++ Repl environments where I could quickly prototype or sanity check things I was doing.
- pantalaimon 7y agoThe trick is to just not use `malloc()` and `free()` unless absolutely necessary ;)
- throw_m239339 7y ago> The trick is to just not use `malloc()` and `free()` unless absolutely necessary ;) The problem is that often C programmers have to deal with API and libraries they didn't write themselves to solve their problems, thus are forced to use constructors and destructors even when they don't want to.
- 0xDEEPFAC 7y agoDear god, is the precedence of the "&" operator ever going to be fixed?
- rseacord 7y agoI can't imagine it will ever be changed, since this would be a breaking change to the language.
- 0xDEEPFAC 7y agoI disagree that this would be a "breaking" change as many people have already resorted to using extra () and such a change might actually may "fix" broken code which makes the reasonable assumption that things like == have a higher-order. https://ericlippert.com/2020/02/27/hundred-year-mistakes/ https://ericlippert.com/2020/02/27/hundred-year-mistakes/ int x = 0, y = 1, z = 0; int r = (x & y) == z; // 1 int s = x & (y == z); // 0 int t = x & y == z; // 0 UGH
- DougGwyn 7y agoIf you're using parentheses, as has been recommended for decades, there is no problem. Otherwise, it is likely that such a change would adversely impact previously working code. There just isn't a pressing need to change it.
- 0xDEEPFAC 7y agoBesides the fact that its unintuitive and could lead to low-level or hard-to-find bugs? It seems to me that C would benefit greatly to iron over its many inconsistencies and exactly the kind of thing people expect in new revisions of the language. Also, I dont see how it would impact previous working code when compilers already do things like allow selections between versions of languages a la C99, C2x, etc. Users could just avoid the new version if they don't feel like changing.
- DougGwyn 7y ago
- Lucasoato 7y agoIs there any new programming language that you particularly love? Do you like the way programming is evolving?
- pascal_cuoq 7y agoAs a member of the development team for a C static analyzer, I use OCaml, which is also my favorite programming language, but that is because I'm from the generation in which it was the new thing (I learnt it when it had the same level of maturity as Rust, at a time when Rust didn't exist). It helps that it's perfect for writing compilers and static analyzers. There are a lot of problems that seem a good match for Rust, and Rust is first in my list of programming languages I will never find the time to learn but wish I could.
- artursapek 7y agoWhy won't you ever find time? It should only take a good 20 hours of reading and playing with code before you start to grok it.
- rseacord 7y agoI spent the early part of my career bragging about how many programming languages I knew, and the later part of my career complaining about how I don't know any of them well enough.
- artursapek 7y agoI certainly wouldn't go for quantity there, but if you really want to learn Rust you should. It brings some groundbreaking new ideas to programming and is more than "just another language".
- Tronic2 7y agoWhy is the struct tm* returned by localtime() not thread-local like errno and other similar variables are (at least in implementations)? Do you have any plans to improve calendar support for practical uses?
- pascal_cuoq 7y agoBoth question would get better answers if they were asked to a panel of experts on POSIX (which could including members of the POSIX standardization committee). For the first one, I can attempt a guess: maybe it was feared that making the result of localtime thread-locale would break some programs? You could build such a program on purpose, although I am not clear how frequently one would write one by accident. Anyway, localtime_r is the function that one should use if one is concerned by thread-safety. A more likely answer is that no Unix implementation bothered to fix localtime because the proper fix was for programs to call localtime_r.
- nicoburns 7y agoAre there any plans to "clean up C"? A lot of effort has been put into alternative languages, which are great, but there is still a lot of momentum with C, and it seems that a lot of improvements that could be done in a backwards compatible way and without introducing much in the way of complexity. For example: - Locking down some categories of "undefined behaviour" to be "implementation defined" instead. - Proper array support (which passes around the length along with the data pointer). - Some kind of module system, that allows code to be imported with the possibility of name collisions.
- msebor 7y agoThere are "projects" underway to clean up the spec where it's viewed as either buggy, inconsistent, or underspecified. The atomics and threads sections are a coupled of example. There are efforts to define the behavior in cases where implementations have converged or died out (e.g., twos complement, shifting into the sign bit). There have been no proposals to add new array types and it doesn't seem likely at the core language level. C's charter is to standardize existing practice (as opposed to invent new features), and no such feature has emerged in practice. Same for modules. (C++ takes a very different approach.)
- DougGwyn 7y agoActually there was no need to disenfranchise non-twos-complement architectures. Now that SIMH has a CDC-1700 emulation, I had planned on producing a C system for it as an example for students who have never seen such a model.
- flatfinger 7y agoRather than trying to decide whether to require that all implementations must use two's-complement math, or suggest that all programs should support unusual formats, the Standard should recognize some categories of implementations with various recommended traits, and programs that are portable among such implementations, but also recognize categories of "unusual" implementations. Recognizing common behavioral characteristics would actually improve the usability of arcane hardware platforms if there were ways of explicitly requesting the commonplace semantics when required. For example, if the Standard defined an intrinsic which, given a pointer that is four-byte aligned, would store a 32-bit value with 8 bits per byte little-endian format, leaving the any bits beyond the eighth (if any) in a state which would be compatible with using "fwrite" to an octet-based stream, an octet-based big-endian platform could easily process that intrinsic as a byte-swap instruction followed by a 32-bit store, while a compiler for a 36-bit system could use a combination of addition and masking operations to spread out the bits.
- ender1235 7y agoHi I took an amazing course in college that focused heavily on C. Do you have any recent examples of small side projects you’ve worked on using C?
- DougGwyn 7y agoHow about a Sudoku solver? Send me a request via e-mail.
- dang 7y agoDoug, the email address in your account is private by default, but you can make it public by putting it in the About field of your profile at https://news.ycombinator.com/user?id=DougGwyn https://news.ycombinator.com/user?id=DougGwyn. ender1235, if you don't see an email address there, email hn@ycombinator.com and I'll put you in touch.
- DougGwyn 7y agoOkay, check my About text. I'll soon remove it, to avoid getting a lot of spam.
- AvImd 7y agoIs there a possibility there will be introduced a new rule saying "if the compiler detects an UB it should abort the compilation instead of breaking the code in the most incomprehensible way possible"? Right now it's just scary to start a new project in C. It would be really great if there was more emphasis on correctness of the produced code instead of the insane optimizations.
- AaronBallman 7y agoIt would be wonderful (IMO) if we could get to that point, but that would leave implementations with too great of a burden because many forms of UB can only be caught at runtime (without a considerable number of false positives). Generally, the C committee makes things a "constraint violation" (aka, we would like implementations to err) whenever something can be caught at compile time, and we leave the undefined behavior hammer for scenarios where there is not a reasonable alternative. Thankfully, there are a lot of tools to help developers catch UB these days (UBSan, static analyzers, valgrind, etc). I would recommend using those tools whenever starting a new project in C (or C++, for that matter).
- klodolph 7y agoThis can only be done at compile time in very specific cases. The huge problem here is the compiler has no way of knowing which cases of undefined behavior are bugs in the program and which cases of undefined behavior are just examples of unreachable code. If the compiler aborted compilation when it detected undefined behavior, you’d be getting a lot of false positives for unreachable code, and you’d need to solve that problem (figuring out how to generate sensible errors and suppress them). This is not even remotely easy. If you are concerned about safety there are ways to achieve that, like using MISRA C, formally verifying your C, or by writing another language like Rust.
- AvImd 7y ago> If the compiler aborted compilation when it detected undefined behavior, you’d be getting a lot of false positives for unreachable code Could you please provide an example of this?
- rvp-x 7y agoA lot of you seem to be working on commercial solutions to C's insecurity. Does this feel like a conflict of interest to you?
- rseacord 7y agoGood question, but not at all! I've been working as hard as I can for the past 15 years to improve C Language security as have other security-minded members of the committee. Generally speaking, we are in the minority as performance is still the major driver for the language. Any security solution that introduces > 5% overhead, for example, is a nonstarter. I think we all understand that are jobs are completely safe no matter what security improvements we can get adopted. The committee works a lot lobbyist. A minority of people with a large financial interest in the technology (such as compiler writers) have undue influence because they participate in the process. I always encourage C language users to take a more active role, but they usually don't. Cisco is an example of user community that actively takes part in C Standardization.
- pjmlp 7y agoI guess this is why vendors like Apple, Oracle, ARM and Google end up going the hardware memory tagging route instead.
- pascal_cuoq 7y agoI have been told in this very AMA that I lacked enthusiasm about C (and the gratuitous insecurity of the language when we know that a well-designed type system and a few runtime checks solve the problem entirely is indeed the reason for my perceived lack of enthusiasm): https://news.ycombinator.com/item?id=22865912 https://news.ycombinator.com/item?id=22865912 I hope that this perceived lack of enthusiasm means I am handling the conflict of interest honorably.
- parenthesis 7y agoCould we have variadic macros with zero arguments in the standard? I'm not using any compiler that doesn't allow it.
- pascal_cuoq 7y agoThe C standard description does not allow a function that does not have at least one normal argument before the variadic arguments. Conceptually, something must indicate to the function how many arguments it is supposed to request next, and with what types. Yes, you could write a function where this information is passed through a static-lifetime variable, but in practice the first mandatory argument is almost always used for that anyway.
- david2ndaccount 7y agoYou’re replying to a comment about macros, not about functions.
- emilfihlman 7y agoHave you considered adding multiplexing capability to the standard? It would be great to have a directly portable one.
- DougGwyn 7y agoWe would need a specific proposal and assurance that nearly all computers can efficiently provide that service. It is more likely in the POSIX standard.
- deleted 7y ago[deleted]
- emilfihlman 7y agoThough it's interesting that threads were added to the standard. Perhaps though they filled a niche that wasn't as well filled as select/poll/epoll/kqueue/etc had already since pthread api is perhaps harder.
- DougGwyn 7y agoI thought it would be best to standardize just a single thread, which should be the basic unit to be embedded in a good parallel-processing model. However, others prevailed.
- Tronic2 7y agochar effectively behaves as a signed type, making it unsuitable for binary operations (e.g. UTF-8 manipulation). I/O functions deal with char pointers, so using unsigned type like uint8_t requires casting back and forth. Is there any way out of this problem, and am I already breaking the aliasing rules with that cast?
- emilfihlman 7y agoThere are no aliasing differences between uint8_t and char as far as I know.
- hsivonen 7y agoIn practice not. In theory, it’s implementation-defined whether yhere are differences.
- emilfihlman 7y agoAt least from what I've heard that's because stdint values are optional. 6.2.5p17 The three types char, signed char, and unsigned char are collectively called the character types. The implementation shall define char to have the same range, representation, and behavior as either signed char or unsigned char. 48) and 5.2.4.2.1 says that width of char, signed char and unsigned char are the same (8).
- radford-neal 7y agoI don't think it's anything to do with uint8_t being optional. It's because a char might have more than 8 bits.
- flatfinger 7y agoA conforming implementation could extend the language with an 8-bit type __nonaliasingbyte which has no special aliasing privileges, and define uint8_t as being synonymous with that type. On the other hand, the Standard should never have given character types special aliasing rules to begin with. Such rules would have been unnecessary if the Standard had noted that an access to an lvalue which is freshly visibly derived from another is an access to the lvalue from which it is derived. The question of whether a compiler recognizes a particular lvalue as "freshly visibly derived" from another is a Quality of Implementation issue outside the Standard's jurisdiction.
- packetlost 7y agoI'm about a mid-level experienced developer, and have been attempting to learn C via a few side projects. I come from mostly Python and Go, which both have very robust standard libraries, so I was quite surprised to find that string parsing is very poorly supported in C. Is there a reason that very common string parsing cases are missing from the C stdlib?
- emilfihlman 7y agoWhy isn't there a binary prefix in the standard? Like 0b0111010?
- rwmj 7y agoNot a question, a request: Please make __attribute__((cleanup)) or the equivalent feature part of the next C standard. It's used by a lot of current software in Linux, notably systemd and glib2. It solves a major headache with C error handling elegantly. Most compilers already support it internally (since it's required by C++). It has predictable effects, and no impact on performance when not used. It cannot be implemented without help from the compiler.
- AaronBallman 7y agoFunny you should mention that, as that feature has come up recently in mailing list discussions. We have not seen an actual proposal for adopting it yet, but features similar semantics are being discussed as a possible idea (no promises). FWIW, I don't think it would wind up being spelled with attribute syntax because we would likely want programmers to have a guarantee that the cleanup will happen (and attributes can be ignored by the implementation).
- eqvinox 7y agoHopefully it'd at least be syntactically similar, so we can have an #ifdef __STDC_CLEANUP__ #define my_cleanup(func) stdc_cleanup(func) #else #define my_cleanup(func) __attribute__((cleanup(func))) #endif i.e. it would require that it at least goes in the same places as an attribute.
- rwmj 7y agoI believe the last proposal was in 2008 (ignore the try..finally stuff here): http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1298.pdf http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1298.pdf So I guess it needs someone to take that and update it, also to pull up a full list of current Linux software which is using this feature (which as I say these days is a surprising amount).
- eqvinox 7y agoHere's our usage: https://github.com/FRRouting/frr/blob/master/lib/privs.h#L141-L146 https://github.com/FRRouting/frr/blob/master/lib/privs.h#L14... #define frr_with_privs(privs) \ for (struct zebra_privs_t *_once = NULL, \ *_privs __attribute__( \ (unused, cleanup(_zprivs_lower))) = \ _zprivs_raise(privs, __func__); \ _once == NULL; _once = (void *)1) This gives us a block construct that guarantees elevated privileges are dropped when the block is done: frr_with_privs(privs) { ... whatever ... break; /* exit block, drop privileges */ return; /* return, drop privileges */ }
- wcarey 7y agoI'm teaching C to high schoolers as their first language, which is quite the adventure. Do you have any good advice or resources on how to introduce the way C treats the function stack and heap allocated memory? Most of my students struggle (naturally) with making sense of function scoped identifiers and pass-by-value semantics.
- imglorp 7y agoCurious what were the requirements to select C as a first high school language over many other choices? I imagine there's a balance of practicality (after the class), and then the usual questions about tooling, sharp edges, and ease of learning.
- wcarey 7y agoIt's a three year rotation: Python, C (Unix), C (Arduino). My goal with the class is to teach ideas that will stand the test of time. C (and Unix) certainly fit that bill. Happily, the tooling is the easiest part. Every student has a rasberry-pi running debian, no mouse, no window server, and no extraneous software. You can spool kids up on a nano-based C toolchain in one class period with remarkably few sharp edges. There's even some fun accidental learning the first time they nano their executable file.
- rramadass 7y agoNeat! I think your choice of C and Python as the languages to be taught is very right. The idea of showing the use of C in both Desktop/Server and Embedded environments has long been the approach i had advocated. C is truly the de-facto "universal" language and students should be made aware of it from the start. I would suggest the following additions; * The Arduino "language" is C++. Use this as a gentle introduction to C++ as a "better C". From there you can move on to proper C++ (do NOT teach "Modern C++" in the beginning). The intent is to show how "C + some syntactic sugar for expressing abstractions" is quite powerful and that is what is C++. This should prepare the students to embark on a proper study of C++. * Instead of using the Arduino "language+library" through the IDE, show them how to use the same GNU gcc toolchain to program the MCU directly in C. See Make: AVR programming by Elliot Williams for details. This teaches the students the idea of a "cross compiler toolchain" and all other related matters from first principles.
- douglascorrea 7y agoI'm trying to learn C during this quarantine times. I'm looking for good beginner-friendly opensource projects to learn from. Can you please suggest some repositories to look into?
- woodrowbarlow 7y ago(obviously, i'm not one of the panel members, just chiming in.) if you're interested in looking at how C can be used in embedded realtime operating systems, i recommend diving into: https://github.com/ARMmbed/littlefs https://github.com/ARMmbed/littlefs (i'm not affiliated.) it's a lean, logging flash filesystem implementation and i recommend it because the research, rationales, documentation, organization, codebase, test harness, and public API ergonomics all impressed me a lot. it was written for the mbed OS, but it is so well designed that i could integrate it into any realtime OS without too much trouble. and the documentation is thorough enough that after skimming the wikipedia article for filesystems, and maybe an article on how flash chips read and write data, you'll be able to work your way through it. i learned a lot by reading through that repository.
- Javantea_ 7y agoDo you think that static analysis is a valuable tool for security research? Do you recommend static analysis software to a single developer with a limited budget or an amateur?
- msebor 7y agoYes, both :) There are a few in public domain that might be helpful to experiment with. Clang has had a static analyzer for a while and GCC 10 adds one as well (and the maintainer is looking for help with implementing checkers so that's a good way to gain experience with writing one).
- dtornabene 7y agowould love to see a couple of detailed comments on this directly as well, I know that one of yall is a maintainer of an analyzer, maybe just some general discussion on beginning to learn C while at the same time incorporating a static analyzer and what that would look like.
- oscoder 7y agoA more chill question for you - What's your favourite string library?
- AvImd 7y agoWhat is your vision of C, its future and its past? What was it supposed to become and did it become that thing? What is it now? What will it involve into in the near and far future?
- msebor 7y agoThe C charter and the C committee's job is to standardize existing practice. That means codifying features that emerge as successful in multiple implementations (compilers or libraries), and that are in the overall spirit of the language.
- psherbet 7y agoI love how small of a language C is and get concerned when people recommend adding feature x,y and z. What's the plan for C over the next 5 - 10 years?
- DougGwyn 7y agoThere is no grand goal that I know of. I wish more importance were being placed on keeping existing well-written code working, which includes continued support for what might be considered near-obsolete. If one wanted to design a new (not fully compatible) language, that could have lofty goals; just don't call it "C".
- baybal2 7y agoHello, I coded in C as a high schooler. Now, 16 years later, I have to code C again semiprofessionally after a very long break. Big question, how to start programming in C on a high professional level for somebody self schooled in it? Is there a way to cut the corner, without having to go through 10+ years trial and error to gain experience? Anything for somebody ready to sit, study, and practice for a few hours a day?
- Nemerie 7y agoThere was a nice discussion recently https://news.ycombinator.com/item?id=22519876 https://news.ycombinator.com/item?id=22519876
- lioeters 7y agoI'm in a similar situation as the parent comment, wanting to re-learn C after more than a decade (or two). Thanks for the link to a recent discussion! For the parent, here are some of the recommended books: Head First C - Griffiths and Griffiths Expert C Programming: Deep C Secrets - Peter van der Linden Modern C - Jens Gustedt C Programming: A Modern Approach - K. N. King 21st Century C: C Tips from the New School - Ben Klemens Understanding and Using C Pointers - Richard Reese C Interfaces and Implementations: Techniques for Creating Reusable Software - David R. Hanson The Standard C Library - P. J. Plauger
- emmelaich 7y agoCompilers are much more helpful now. Better diagnostics, more options for warnings.
- deleted 7y ago[deleted]
- pcr910303 7y agoAs there are a lot of C-masters lurking in this thread: How can one process unicode (UTF-8) properly in C? As a CJK person, I wish there was a robust solution. Are there any standardized ways or proposals? (Using wchar doesn't count.)
- DougGwyn 7y agoUTF-8 encoding works "as is" based on byte strings (char[]). The latest versions of the draft standard provide somewhat more support. I recommend heading toward a future where only UTF-8 encoding is used for multibyte characters and UCS-2 or similar for wchar_t. There is no need to support several different encodings.
- deleted 7y ago[deleted]
- rseacord 7y agoAaron Ballman even got a u8 character prefix added to C2x: N2198 2018/01/02 Ballman, Adding the u8 character prefix http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2198.pdf http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2198.pdf
- ori_b 7y agoUCS-2 is a bad choice -- it fails to represent most unicode characters. If you meant UTF-16, that's also a bad choice, because UTF-16 is also a variable width encoding, forcing programmers to use a some for of "extra-wide char". I'm of the opinion that wchar_t should become an alias for char32_t.
- DougGwyn 7y agoYes, I meant the 31-bit code point value (more than 16, anyway). It is the most useful width for doing things with wide characters.
- a1369209993 7y agoUTF-32 is also a variable-width encoding; eg 00000044 00000308 aka "D̈".
- Jahak 7y agoTell me where I can get the C89 standard for free (pdf or other formats)
- pascal_cuoq 7y agoThe last time I needed it, archive.org had a link to a PDF of it. I couldn't find that again in one minutes, but here is the text version: http://web.archive.org/web/20030222051144/http://home.earthlink.net/~bobbitts/c89.txt http://web.archive.org/web/20030222051144/http://home.earthl...
- Jahak 7y agoThanks
- defectbydesign 7y agoWhat's prevent you from buying K&R? A paperbook is less likely to be lost and K&R is the more affordable reference to C rather than ISO 9899.
- bumblebritches5 7y agoHey guys, How likely would the standard be to accept a proposal to add compile time reflection to the preprocessor, or even adopt C++'s constexpr? My use case is creating a global array in a header from static compound literals in multiple source files at compile time, and outside of some crazy clang-tblgen type solution, or very platform specific linker hacks, it's completely unsupported by C.
- om42 7y agoNot particular to the C language, but what are your opinions on build systems, particularly for the embedded space? There's a couple vendor specific embedded IDEs and toolchains and having to glue together make/cmake files to support all of them can be a pain.
- msebor 7y agoRobert's upcoming book has a survey of a few popular IDEs.
- asimpletune 7y agoWhy is shifting by a negative amount undefined?
- kps 7y agoBecause people want `c = a << b` to compile into `shl c, a, b` and C89 made the giant mistake of calling it ‘undefined’ instead of ‘implementation-defined, possibly fatal’.
- jpizza 7y agoHello, First off thank you so much for taking the time to answer questions. As a new programmer starting with C I am trying to learn how to go from a beginner to an intermediate any recommendations of projects to help learn C? It is difficult for me to find projects that I see are "valuable" for a lack of a better term. Thank you!
- DougGwyn 7y agoOne possibility is to modify some existing program to include an additional new feature. You should soon develop a sense for what works well versus what causes problems.
- nchelluri 7y agoHello, just a quick note; I wanted to buy the book so I went to the website and when I picked my country as Canada it started giving me a strange list of provinces (definitely not Canadian) so I abandoned the process for now.
- rseacord 7y agoI'll pass this on to the publisher....
- billpollock 7y agoI've asked our Operations Manager to look into this issue. Thanks for bringing this to our attention. We'll get it sorted out. Please email info@nostarch.com so that they can help troubleshoot.
- gnachman 7y agoSince 1999, a lot of undefined behavior has been added to the language to improve compilers’ ability to optimize. For example, pointer aliasing rules. How have you measured the benefit?
- natch 7y agoCan you please repeat this AMA at a later date and at a time of day when people on the west coast of the USA are awake? Alternatively, please keep it going for a few hours if you would be able to be so generous with your time! Thank you for doing this! Do you also answer questions about the standard libraries? This is not so much a C question as a library question: I'm wondering if Apple's Grand Central Dispatch ever made it into a more integrated role in C's libraries, or if it will forever remain an outside add-on. And whether there is anything else at that level (level in the sense of high versus low level) in the standard libraries that plays such a role, that I should read up on instead of GCD.
- AaronBallman 7y ago> Alternatively, please keep it going for a few hours if you would be able to be so generous with your time! We're remaining active while there are still people asking questions, so the west coast folks should hopefully have the chance to ask what they'd like. > Do you also answer questions about the standard libraries? Sure! > I'm wondering if Apple's Grand Central Dispatch ever made it into a more integrated role in C's libraries, or if it will forever remain an outside add-on. GCD has not been adopted into C yet, and I don't believe it's even been proposed to do so by anyone (or an alternative to GCD, either). It would be an interesting proposal to see fleshed out for the committee, and there is a lot of implementation experience with the feature, so I think the committee would consider it more carefully than an inventive proposal with no real-world field experience.
- wahern 7y agoGCD relies on Blocks (closures) for ergonomics, and Blocks have been proposed to WG14, for example N1451: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1451.pdf http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1451.pdf
- iamed2 7y agoWhat's an example of a codebase where _Generic has had a notable positive impact?
- AaronBallman 7y agoNot necessarily a code base, but _Generic is what makes <tgmath.h> implementable for the type-generic math functions.
- jcranmer 7y agoAre there any plans to add support for multiple register return values to C?
- rand0mstring 7y agowill we ever see compile time programming in C like constexpr in C++?
- rmind 7y agoA lot C programmers prefer to keep structures within the C source file ("module"), as a poor man's encapsulation. For example: component.h: struct obj; typedef struct obj obj_t; obj_t *obj_create(void); // .. the rest of the API component.c: struct obj { int status; // .. whatever else }; obj_t * obj_create(void) { return calloc(1, sizeof(obj_t)); } However, as the component grows in complexity, it often becomes necessary to separate out some of the functionality (in order to re-abstract and reduce the complexity) into a another file or files, which also operate on "struct obj". So, we move the structure into a header file under #ifdef __COMPONENT_PRIVATE (and/or component_impl.h) and sprinkle #define __COMPONENT_PRIVATE in the component source files. It's a poor man's "namespaces". Basically, this boils down to the lack namespaces/packages/modules in C. Are you aware of any existing compiler extensions (as a precedent or work in that direction) which could provide a better solution and, perhaps, one day end up in the C standard? P.S. And if C will ever grow such feature, I really hope it will NOT be the C++ 'namespace' (amongst many other depressing things in C++). :)
- msebor 7y agoThe ELF visibility attributes solve the part of the problem at the binary level (by hiding private library APIs from the application). The rest should be doable by structuring the project sources and headers in a suitable way.
- loeg 7y agoELF is very much not part of the C standard.
- pascal_cuoq 7y agoI am sorry I do not have an answer to your question. It's a very valid one and I would be interested in any pointer to an answer. What I can say while we are on the subject, is that I have seen C code (most often C code that started its life in the 1990s, to be fair) that instead of showing an abstract struct in the public interface, showed a different struct definition. Please don't do this. Yes, when compiling nowadays, eventually every compilation unit ends up as object files passed to a linker that doesn't know about types, but this is undefined behavior. It makes it difficult to find undefined behavior in the rest of the code because there is a big undefined behavior right in the middle of it.
- ativzzz 7y agoOther than these experts, what kind of companies do C developers work at? How does the compensation look like compared to doing web development?
- pascal_cuoq 7y agoI do not actually develop in C (other than short examples to feed the C analyzer that I work on, which is not written in C) but our customers do employ plenty of C developers. These customers are developing embedded software that reads inputs from sensors, process them, and send the final results of the computations to actuators, in fields such as IoT, aeronautics, rail, space, nuclear energy production, autonomous transportation, … The list is very much biased by the sort of analyzer we provide. There are certainly plenty of non-embedded codebases in C and of developers paid to maintain and extend them, it's just that we currently do not work with them as much. I do not know about whether the compensation is better or worse than for other technologies.
- brainzap 7y agoHow do you join three float values into a comma separated string, and then split it again?
- emilfihlman 7y agoNot sure what you mean but would s8 buf[enoughspace]; snprintf(buf, sizeof(buf), "%f,%f,%f", your, three, values); sscanf(buf, "%f,%f,%f", &your, &three, &values); Do the job?
- KMag 7y agoI think that the GP was making a commentary on the sorry state of locale handling in C. You need to first store the current locale, change the locale to one that doesn't use a comma as the decimal point, perform the above, and set the locale back. Plus, there's no threadsafe way to do this, since the locale is process-wide.
- rand0mstring 7y agois there no way to make C "memory-safe" during compilation?
- zzzcpan 7y agoThere are a bunch of research projects that did just that. And even just compiling with address sanitizer makes it "memory-safe" to a significant degree.
- rand0mstring 7y agocan you link any to check out?
- a-bit-of-code 7y agoAny chance that we could have an STL equivalent in C. Of course, templating and other features being absent it won't be as generic as CPP. However, having even something close to STL will help in the long run. Thanks!
- rseacord 7y agoThere is always a chance. We would need to see a proposal based on experience with an existing implementation.
- potiuper 7y agoAny plans to add semantics for exceptional situations such as divide by zero and dereferencing a null pointer? https://blog.regehr.org/archives/232 https://blog.regehr.org/archives/232 Or incorporating features from this 14 item list? https://blog.regehr.org/archives/1180 https://blog.regehr.org/archives/1180 As it appears these have failed: https://blog.regehr.org/archives/1287 https://blog.regehr.org/archives/1287
- DougGwyn 7y agoThe problem is that if the checks are always performed, the object code is significantly slowed down. If all computers supported the checking in hardware, then we could do it. You don't really want the current C approach (signal) to trigger except in an emergency, because there is no way to insert cleanup/retry/etc. recovery code via a signal handler.
- rseacord 7y agoI don't know of any plans to add semantics for divide-by-zero of dereferencing a null pointer. I'm guessing this is not viable because there is no agreed upon semantics among different implementations. Making C friendlier is always a good idea, and I think the committee is (slowly) working towards this goal. I would have to examine these papers by John Regehr in more detail. Looking quickly at his proposals I can see why there he couldn't find consensus for these ideas as some of them do appear controversial. An example of a friendly dialect of C is always is C0 (C-naught) from CMU. I don't think I'm exaggerating when I say that this language has not "caught on".
- flatfinger 7y agoConsider the following function: int test(int a, int b) { int c = a/b; if (f1()) f2(a,b,c); } Should a compiler be required to compute c before calling f1, and thus have to store the value of c across the function call? Better would be to define a set of semantics for loosely-sequenced traps, along with "causality barriers" to ensure that they only occur at tolerable times.
- RandNOx 7y ago- Which differences between the C abstract machine and actual modern CPUs/hardware have proven most difficult to deal with in the language? - Are you planning any addition regarding modeling of how modern CPUs work (e.g. pipelines, branches, speculative execution, cache lines, etc)? PS: Thank you for doing this!
- AaronBallman 7y ago> - Which differences between the C abstract machine and actual modern CPUs/hardware have proven most difficult to deal with in the language? For me, I think it's 'volatile' because, by its nature, you can't describe what it means in the abstract machine very well. For instance, consider a proposal to add something like a "secure clear" function for clearing out sensitive data. The natural inclination is to pretend that data is volatile so the optimizer won't dead-code strip your secure clear function call, but that leaves questions about things like cache lines, distributed memory, etc. > - Are you planning any addition regarding modeling of how modern CPUs work (e.g. pipelines, branches, speculative execution, cache lines, etc)? Maybe? ;-) We tend to talk about features at a higher level of abstraction than the hardware because hardware changes at such a rapid pace compared to the standards process. So we largely leave hardware-specific considerations as a matter of QoI for implementers. However, that doesn't mean we wouldn't consider proposals for more concrete things like a defensive attribute to help mitigate speculative execution attacks.
- oreally 7y agoAbout time someone advocated for code in lower level styles of programming. Hope it goes well! Anyway, here's some questions: - What kind of programs would you say C is a good fit for? - There is some catching up to do for C. Is there a roadmap for C improvement, or even a recommendation of C++ things that fit somewhat in the style/philosophy of C? For example, I'd recommend not using the C++ smart pointers stuff, while still using C++ threads and lambdas. Also, you should include programmers from other fields in your committee. Game (engine) developers, HFT programmers are used to lower level styles of coding and align with your perspective.
- cperciva 7y agoWhen will C gain a mechanism for "do not leave this sensitive information laying around after this function returns"? We have memset_s but that doesn't help when the compiler copies data into registers or onto the stack.
- pascal_cuoq 7y agoThis is an entire language extension, as you note. The last time various people interested in this were in the same room (it was in January 2020 in a workgroup called HACS), what emerged was that the Rust people would try to add the “secret” keyword to the language first, since their language is still more agile than C, while the LLVM people would prepare LLVM for the arrival of at least one front-end that understand secret data. Is this enough to answer your question? I can look up the names of the people that were involved and communicate them privately if you are further interested.
- loeg 7y ago(Not OP) I would appreciate any references you can provide. An LLVM __attribute__((secret)) would be a great place to start.
- pascal_cuoq 7y agoUnfortunately I am out of useful information: https://news.ycombinator.com/item?id=22868999 https://news.ycombinator.com/item?id=22868999 I hope someone will provide the next link.
- cperciva 7y agoThanks for the update. I was encouraging some of the people who were going to be at HACS to address this but I hadn't heard the latest progress. Unfortunately I couldn't be there myself.
- pascal_cuoq 7y agoIf I remember correctly, Chandler was the one writing down the draft for LLVM developers to comment on LLVM-side. Unfortunately, if you Google his name and the relevant keywords, the results are full of his work on speculative load hardening. Someone who read the LLVM mailing-list attentively should have seen it and may have a link.
- lemaudit 7y agoHi, Do you think Annex K of C11 will be widely adopted by programmers or unused? Why aren't people adopting it? Do you see the use of any analysis tools that are particularly effective for finding memory safety issues? C++ added in smart pointers to its specification. Are there any plans to do something similar in future C specifications? Thanks!
- AaronBallman 7y ago> Do you think Annex K of C11 will be widely adopted by programmers or unused? Why aren't people adopting it? So far, it's not been widely adopted. Part of the issue is that there are specification issues relating to threads and the constraint handlers, and part of the issue is that popular libc implementations have actively resisted implementing the annex. That said, I field questions about Annex K on a regular basis and there are a few implementations in the wild, so there is user interest in the functionality. > Do you see the use of any analysis tools that are particularly effective for finding memory safety issues? <biased opinion>I think CodeSonar does a great job at finding memory safety issues, but I work for the company that makes this tool.</biased opinion> I've also had good luck with the memory and address sanitizers (https://github.com/google/sanitizers https://github.com/google/sanitizers) and tools like valgrind. > C++ added in smart pointers to its specification. Are there any plans to do something similar in future C specifications? We currently don't have any proposals for adding smart pointers to C. Given that C does not have constructors or destructors, we would have to devise some new mechanism to implement or replace RAII in C, which would be one major hurdle to overcome for smart pointers.
- hedora 7y agoI’ve had good luck (in C++) replacing the underlying memory allocator with one that tracks leaks by allocation type (which is fast enough for production use). This can be done in C, but the calling code has to spell malloc and free differently. In debug mode, configuring malloc to poison (and add fences) on allocation and free finds most of the remaining things. These techniques tend to have much lower runtime overhead than valgrind (2-digit percentages vs 5-10x), so they can be left on throughout testing and partially enabled in production. They find >90% of the memory bugs that I write (assuming valgrind finds 100%). YMMV.
- Bambo 7y agoWhat is your favourite design pattern?
- floatms 7y ago1. How likely are named constants of any types to be included in C2x? I'm referring to the idea of making register const values be usable in constant expressions. 2. Is there, or was there ever a proposal to make struct types without a tag be structurally typed? This would not break backwards compatibility as far as I can see, and would make these types much more useful as ad-hoc bags of data. Small example: struct {size_t size; void *data;} data = get_data(); int hash = hash_data(data); I believe there was at least one proposal about error handling that more or less relied on the above to be valid semantically. 3. Is there any interest in making the variadic function interface a bit nicer to use? I would like to bring back an old feature and have an intrinsic to extract a pointer from the variadic parameter list, so that we can iterate over it ourselves (or even index directly). void *arg_ptr = va_ptr(last); More out there would be a parameter that would be implicitly passed to a variadic function to indicate the number of arguments. void variadic(..., va_size count) { } variadic(10, 20, 30); // count would be three
- msebor 7y agoI'd expect a proposal for (1) to be well received. The only proposal I recall that deals with (2) is http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2067.pdf http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2067.pdf. I think it's still being discussed. (3) is highly unlikely if it involved ABI changes. Even if it could be done without such changes unless there is a precedent for it in an existing compiler (and preferably more), it would likely be a tough sell.
- floatms 7y agoIs the linked proposal really dealing with unnamed struct types? I skimmed it and it seems like it is dealing with named constants. Also, is there a proposal for (1) currently, or is someone planning on writing one? Regarding (3), yes, this one was mostly wishful thinking.
- pascal_cuoq 7y ago3. would have to be a new mechanism for variadic functions, that would have to be distinguished in header files from the old mechanism with which it is incompatible. So this proposal would imply some new keyword or syntax. I am not in the committee, but I don't think this is going to happen. The improvement is way too incremental to force a new syntax. (The committee is fine with incremental improvements, but new syntax need to have strong motivation behind it, much stronger than this.)
- blocks_plz 7y agoThanks for the AMA 1. Will the Apple's Blocks extension, which allows creation of Closures and Lambda functions, be included in C2X? 2. Are there any plans to improve the _Generic interface (to make it easy to switch on multiple arguements, etc.)?
- yvdriess 7y ago+1 for the first point. Every major compiler can do the lambda-lifting transformation, either because of C++ lambda or OpenMP support. It's frustrating doing this manually while knowing the compiler supports it internally, but does not expose it natively.
- AaronBallman 7y ago> 1. Will the Apple's Blocks extension, which allows creation of Closures and Lambda functions, be included in C2X? We haven't seen a proposal to add them to C2x, yet. However, there has been some interest within the committee regarding the idea, so I think such a proposal could have some support. > 2. Are there any plans to improve the _Generic interface (to make it easy to switch on multiple arguements, etc.)? I haven't seen any such plans, but there is some awareness that _Generic can be hard to use, especially as you try to compose generic operations together.
- blocks_plz 7y ago1. The reason I asked was because I remember reading the proposal as N2030[1] and N1451[2] a while back. Were these never actually presented for voting? (not sure how the commitee works) [1]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2030.pdf http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2030.pdf [2]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1451.pdf http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1451.pdf
- AaronBallman 7y agoAh! No, those just predate my joining the committee and haven't really come up since they were presented. Basically, every paper that gets submitted by an author will get some amount of discussion time at the next available meeting as well as feedback from the committee on the proposal. I'm not certain what feedback these papers received (we could look through the meeting minutes for the meetings the papers were discussed at to find out, though).
- mey 7y agoThis is a subjective question. From the array of tools in your belt, when do you personally/professionally reach for C, or maybe more interestingly, when do you not reach for C?
- DougGwyn 7y agoSince I do almost all my software development in a Unix environment, usually I check the toolbox to see if there is already a program that has nearly the functionality I want, and if so then I cobble together a shell script. Sometimes (as with the Sudoku solver) it will be necessary to build a new component, and for that I usually use C since I am comfortable and experienced with it. (Also, if coded in Standard C, odds are that I can install it on whatever platform I need, with little or no adaptation.)
- WFHRenaissance 7y agoA bit off topic, but what are your views on Golang? I'm leaving this pretty open-ended, but I'm curious how you see it interacting with the C/C++ ecosystem in the future.
- MaxBarraclough 7y agoDoes the following code fragment cause undefined behaviour? unsigned int x; x -= x; There's a lengthy StackOverflow thread where various C language-lawyers disagree on what the spec has to say about trap values, and under what circumstances reading an uninitialised variable causes UB. I'd appreciate an authoritative answer. Thanks for dropping by on HN! https://stackoverflow.com/q/11962457/ https://stackoverflow.com/q/11962457/
- msebor 7y agoYes, it's undefined. It involves a read of an uninitialized local variable. Except for the special case of unsigned char, any uninitialized read is undefined.
- emilfihlman 7y ago>Except for the special case of unsigned char, any uninitialized read is undefined. Could you expand on this?
- rseacord 7y agoUninitialized Reads https://queue.acm.org/detail.cfm?id=3041020 https://queue.acm.org/detail.cfm?id=3041020
- loeg 7y agoI'm guessing you were asking about this part rather than UB in general: > Except for the special case of unsigned char, The SO article makes the bizarre claim that because (1) an unsigned char, per the standard, cannot have any padding bits, it therefore cannot have a trap representation. And (2) if it cannot have a trap representation, the use of an uninitialized value isn't undefined. I'm willing to buy (1) but I don't remember (2) being required for UB. I think (2) is the step that is harder to follow intuitively. Admittedly, I have not read that part of the standard closely in some time.
- msebor 7y agoAn object of any type, initialized or not, can be read by an lvalue of unsigned char (or any character type). That lets functions like memcpy (either the standard one or a hand-rolled loop) copy arbitrary chunks of memory. There's some debate about the effects of reading an uninitialized local variable of unsigned char (like whether the same value must be read each time, or whether it's okay for each read to yield a different value). This special exemption doesn't extend to any other types, regardless of whether or not they have padding bits or trap representations that could cause the read to trap. Few types do, yet the behavior of uninitialized reads in existing implementations is demonstrably undefined (inconsistent or contradictory to invariants expressed in the code of a test case), so any subtleties one might derive from the text of the standard must be viewed in that light.
- stwcx 7y agoOne feature of C which I do not use often is enums. Support for constants beyond the range of an int is not portable. And I also try to avoid is putting enums inside structs, because there is no portable way to enforce the size or the alignment of the enum's base type. Will this be addressed in future revisions of the C standard?
- BeeOnRope 7y agoWhen deciding on the behavior of some operation that maps to hardware [1], how do you weight the existing hardware behaviors? For example, if all past, current and contemplated hardware behaves in the same way, I assume that the standard will simply enshrine this behavior. However, what if 99% of hardware behaves one way and 1% another? Do you set the behavior to "undefined" to accommodate the 1%? At what point to you decide that the minority is too small and you'll enshrine the majority behavior even though it disadvantages minority hardware? --- [1] Famous examples include things like bit shift and integer overflow behavior.
- rseacord 7y agoI would say that the committee does pay attention to hardware variations, even when there are no examples of existing hardware that implement a feature (for example, a trap representation for integers other than _Bool). Some of the thinking is that "if it was ever implemented in hardware, it could be again). I'm not crazy about this thinking, and I largely think that language features for which there are no existing hardware implementations should be eliminated and then brought back if needed. However, the C Committee is much smaller than the C++ committee so there is a labor shortage. More people getting involved would certainly help. We have dropped support for sign and magnitude and one's complement architectures from C2x (a decision Doug Gwyn does not agree with). There was some concern that Unisys may still use a one's complement architecture, but that this may only be in emulation nowadays.
- rseacord 7y agoSome example of hardware variation (since you mentioned shifting and overflow): - signed integer overflow or division by zero occurs, a division instruction traps on x86, while it silently produces an undefined result on PowerPC - left-shifting a 32-bit one by 32 bits yields 0 on ARM and PowerPC, but 1 on x86; - left-shifting a 32-bit one by 64 bits yields 0 on ARM, but 1 on x86 and PowerPC
- BeeOnRope 7y agoOn x86 it's actually mixed: scalar shifts behave as you describe, but vectorised logical shifts flush to zero when the shift amount is greater than the element size! So x86 actually has both behaviors in one box (three behaviors if you could the 32-bit and 64-bit scalar things you mentioned separately). This is an example of where UB for simple operations actually helps even on a single hardware platform: it allows efficient vectorization.
- deleted 7y ago[deleted]
- graycat 7y ago(1) Explain just how malloc() and free() work under the covers and the implications for multi-threading, memory leaks, virtual memory paging, etc. Maybe also cover some means, algorithms, and code for reporting on the state, status, etc. of the memory use by malloc() and free(). By the way, I know and have known well for longer than most C programmers have lived JUST what the heap data structure, as used in "heap sort", is. But what is the meaning of "the heap" in C programming language documentation? (2) Cover in overwhelmingly fine detail the "stack" and the chuckhole in the road, stack overflow. (3) Where to get a reliable package for a reasonable package of code for handling character strings -- what I saw and worked with in C is not reasonable. (4) From the C programming I did, it looks like a large C program for significant work involves some hundreds, maybe tens of thousands, of includes, inserts, whatever, and what a linkage editor would call external references. There must somewhere be some tools to help a programmer make sense of all those includes and references, the resulting memory maps, issues of locality of reference, word boundary alignment, etc. (5)How can C exploit a processor with 64 bit addressing and main memory in the tens of gigabytes and maybe terabytes? (6) How can C support, i.e., exploit, integers and IEEE floating point in 64 and/or 128 bit lengths? (7) How to handle exceptional conditions with, say, non-local gotos and without danger of memory leaks? (8) Sorry, but far and away my favorite programming language long has been and remains PL/I, especially for its scope of names rules, handling of aggregates with external scope, its data structures, and its exceptional conditional handling with non-local gotos and freeing automatic storage and, thus, avoiding memory leaks. Of course I can't use PL/I now, but the problems PL/I solved are still with us, also when writing C code. So, how to solve these problems with C code? (9) For C++, please explain how that works under the covers. E.g., some years ago it appeared the C++ was defined as only a source code pre-processor to C. Is this still the case? If so, then explaining C++ under the covers should be feasible and valuable.
- BeeOnRope 7y agoWhen deciding on standardized behavior for C operations or data representation that may favor some hardware over others [1], who argues the side of the various hardware vendors, if they have no members on the standardization committee? Is it fair to assume that hardware-related decisions occur in an environment where members who are sponsored by vendors argue their employers case, rather an a neutral one? --- [1] E.g., because some hardware's behavior may more naturally implement the operation.
- AaronBallman 7y ago> When deciding on standardized behavior for C operations or data representation that may favor some hardware over others [1], who argues the side of the various hardware vendors, if they have no members on the standardization committee? The C committee has a number of implementation vendors on it (GCC, Clang, IBM, Intel, sdcc, etc) and these folks do a good job of speaking up about the hardware they have to support (and in some cases, they're also the hardware vendor). If needed, we will also research hardware from vendors who have no active representation on the committee, but this is usually for more broad changes like "can we require 2's complement?". > Is it fair to assume that hardware-related decisions occur in an environment where members who are sponsored by vendors argue their employers case, rather an a neutral one? In my experience, the committee members typically do a good job of differentiating between "this is my opinion" and "this is my employer's opinion" during discussions where that matters. However, at the end of the day, each committee member is there representing some constituency (whether it's themselves or their company) and votes their own conscience.
- BeeOnRope 7y agoThanks for your quick and honest answer.
- loeg 7y agoHas Annex K been axed yet, and if not, why not?
- rseacord 7y agoIt has not. The C Committee has taken two votes on this, and in each case, the committee has been equally divided. Without a consensus to change the standard, the status quo wins. Sounds like you don't care for Annex K. What don't you like about it?
- loeg 7y agoI think my complaints are summed up nicely in some of your coauthors' report: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1967.htm http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1967.htm (1) runtime constraint handler callbacks are a terrible API. (2) The additional boilerplate doesn't buy us anything — the user can still specify the wrong size. (3) The Annex invents a feature out of whole cloth, rather than standardizing existing practices. There are no performant real-world implementations that anyone uses. Microsoft's similar functionality is non-standard.
- hsivonen 7y agoDoes the committee have plans to deprecate (as in: give compiler license to complain suchthat compiler developers can appeal to yhe standard when users complain back) locale-sensitive functions like isdigit, which is useless for processing protocol syntax, because it is locale-sensitive, and useless for processing natural-language text, because it examines only one UTF-8 codw unit?
- DougGwyn 7y agoisdigit is likely to remain, because much existing code does use it (perhaps in different contexts from the one you cited). If you need a different function specification to do something different, it could be added in a future release, but that doesn't mean that we need to force programmers to change their existing code.
- hsivonen 7y agoDoes there exist a use case in portable code such that use of isdigit is not a bug? How does the committee view non-portable existing code generally when considering changes?
- DougGwyn 7y agoCode can be non-portable for various reasons, not all of them bad. I just grepped a recent release of DWB and found about 100 uses of isdigit, most of which were not input from random text but rather were used internally, such as "register" names (limited to a specified range). Other packages are likely to have similar usage patterns. I really don't want to have to edit that code just for aesthetics.
- _kst_ 7y agoWhat about giving isdigit and friends defined behavior for any argument value that's within the range of any of char, signed char, or unsigned char? The background (I know Doug knows this): isdigit() takes an argument of type int, which is required to be either within the range of unsigned char, or have the value EOF (required to be negative, typically -1). The problem: plain char is often signed, typically with a range of -128..+127. You might have a negative char value in a string -- but passing any negative value other than EOF to isdigit() has undefined behavior. Thus to use isdigit() safely on arbitrary data, you have to cast the argument to unsigned char: if (isdigit((unsigned char)s[i])) ... A lot of C programmers aren't aware of this and will pass arbitrary char values to isdigit() and friends -- which works fine most of the time, but risks going kaboom. Changing this could raise issues if -1 is a valid character value and also the value of EOF, but practically speaking -1 or 0xff will almost never be a digit in any real-world character set. (It's ÿ in Unicode and Latin-1, which might cause problems for islower and isalnum.)
- oldiob 7y agoIs the committee planning on working on the preprocessor? I don't see any reason for not boosting it. It's time for C to have real meta-programming. Would be nice to have local macros that are scoped. On another note: - Official support for __attribute__ - void pointers should offset the same size as char pointers. - typeof (can't stress this one enough) - __VA_OPT__ - inline assembly - range designated initializer for arrays - some GCC/Clang builtins - for-loop once (Same as for loop, but doesn't loop) Finally, stop putting C++ craps into C.
- jparkie 7y ago+1 for Modern Metaprogramming. I know some people are against metaprogramming because they believe the abstractions hide the intrinsic of how the underlying code will execute, but I would love to write substantial tests in C without relying on FFI to Python or C++ to perform property-based testing, complex fuzzing, and whatever. I feel metaprogramming would be a huge boon for C tooling and developer productivity.
- oldiob 7y agoIn my point of view, there's a difference between abstraction created by the language, e.g. lambdas or virtual table in C++, and abstraction created by the programmers via the CPP. The former is compiler dependent and you cannot know how it's implemented. The former is simple text substitution and you're the one implementing it. I often find myself creating small embedded languages in CPP for making abstraction, and I know exactly what C code it's going to generate and thus the penalty if there's any. People that are afraid of the preprocessor simply don't understand how powerful it's in good hands.
- hawski 7y agoWhat do you think about Zig language [0] and if you have any opinions on it, what distinguishing features would you like to see adopted in the C world? [0] https://ziglang.org/ https://ziglang.org/
- axelf4 7y agoIn C89 is there a portable way to figure out the alignment requirement for a struct, to be able to, say, store it after the NUL terminator in the same allocation as a C string?
- DougGwyn 7y agoI'm not sure what your requirement is. Usually things work out if you're careful not to assume any specific value for alignment etc. It may mean a few unused bytes here and there, but keeping things simple and portable often pays off.
- quelsolaar 7y agoBeing able to know your alignments is VERY important for a lot of network implementations. They are all defined by the ABIs, but its very annoying that the standard keeps thinking that alignment is unknowable, when in fact its impossible to implement a ABI without defining it. One of the reasons I stick to C89.
- DougGwyn 7y agoNote that the ABIs cover endianness as well as value range and/or object widths. In general, one needs to have explicit marshaling and unmarshaling functions to map from network octet array and C internal data representation. Failure to get this right is (or used to be) a common bug for code developed and tested on too few architectures.
- quelsolaar 7y agoSure, it wont be portable between any architectures, but a lot of times you know you will be on a little endian platform where types are aligned to their sizeofs. That covers a lot of ground and the performance gains you get from optimizing with this in mind is significant. There is value in C being able to be portable, but there is also a huge value in being able to write non-portable code that takes advantage of what you know about the platform. C needs to acknowledge that that is a legitimate use case.
- emreiyican 7y agoI know this opinion is unpopular and contradict with a core value of the C standardization committee but I personally think at some point, C standard should abandon supporting the legacy codebase. I think bool and stdint definitions should be available as part of the standard feature set and shouldn't need including their respective headers. These and some other features are available at the core of every modern language but C, and C has to provide them via other means. Is the sentiment of discontinuing legacy support shared within the committee, by any proportion?
- xyzzy2020 7y agoCan't upvote enough. I think these changes could also be made in a way that can be mechanically-translatable. For example: removing the register keyword, always requiring a return statement, etc etc. A lot of changes can me made that will make static analysis easier. There will always be people with 50 year old code bases that will never change (and some c89 compiler will always be there for them), but the language is pervasive enough that it deserves progressive changes to make it (even) simpler and safer and slightly more high level.
- AaronBallman 7y agoWe've started doing some things in this area, but I don't think the committee would abandon legacy code bases entirely. Instead, we try to make a migration path for code bases. For instance, we added the '_Bool' data type and require you to include <stdbool.h> to spell it 'bool' instead and to get 'true' and 'false' identifiers. This was done to not impact existing code bases that had their own bool/true/false implementation with those spellings. Now that "enough" time has passed for legacy code bases to update, we're looking into making these "first-class" features of the language and not requiring <stdbool.h> to be included to use them. We're doing the same for things like _Static_assert vs static_assert, etc for the same reason.
- loeg 7y agoI'd love it if we could do away with all the headers. Just #include <stdc.h> and be done with it. No need to remember stdio, stdint, stdbool, limits, assert, signal.h, etc, etc. This new header comes with a guarantee that use of identifiers in the standard-reserved namespace will break your code. Perhaps compilers could even enforce this preemptively.
- ancarda 7y agoAs a C newbie, will there ever be "safe" C, i.e. no undefined behavior and help with writing code that has less memory related crashes/bugs? For comparison, Rust has the `unsafe { }' block which lets you mark regions of code as being able to do funky stuff. Could we get the opposite for C, i.e. `safe { }' and for an entire file, `#pragma safe'? I have a love-hate relationship with C - I like it for small projects, but anything serious I really need to write it in a more safe language. I think GCC has some flags that can help, and I've been using tools like splint, but something baked into the standard would be amazing.
- sramsay 7y agoI'm pretty happy with C as it is, but I will admit to being surprised that a "minimalistic Rust" hasn't risen to prominence. I guess what I mean by that is a language that has Rust's hyperactive, strongly opinionated compiler, borrow checker, no NULL, immutable by default, etc, but in a language that is no more syntactically ambitious that C89. I would be way more into a language like that than Rust. A language that sort of feels like Go, but can actually be used for low-level systems programming.
- Leherenn 7y agoI think it's going to arrive, but some time is needed to see what works in Rust or not. D is going this way as well, so should provide another data point.
- hsivonen 7y agoDoes the committee have any plans to document the rationale for each kind of Undefined Behavior? Does the committee have any plans to make NULL pointer arguments to memcpy non-UB when the size argument is 0?
- AaronBallman 7y ago> Does the committee have any plans to document the rationale for each kind of Undefined Behavior? In the C99 timeframe, we had a rationale document that was separately maintained. My understanding (this predates my joining the committee) is that this was prohibitively labor-intensive and so we stopped doing it for C11. I don't know of any plans to start doing this again, even in a limited sense for justifying UB. That said, we do spend time considering whether an aspect of a proposal requires UB or not, so the rationale exists in the proposals and committee minutes. > Does the committee have any plans to make NULL pointer arguments to memcpy non-UB when the size argument is 0? I have not seen such a proposal, and suspect that implementations may be concerned about losing their optimization opportunities from such a change. (Personally, I'd be okay losing those optimization opportunities as this does not seem like a situation where UB is necessary.)
- watergatorman 7y agoSome random thoughts: I appreciate the original simplicity of K & R, "The C Programming Language", 2nd Edition, and the relatively simple semantics of ANSI C89/ISO C90 compared to C99 and later. You don't need complex parsing methods for ANSI C89/ISO C90 and you do not need the "lexer hack" to handle the typedef-name versus other "ordinary identifier" ambiguity. A surprising number of colleges still teach K & R 2nd Edition C. Whenever someone brags about using recursive-descent parsing methods, I always ask, are they using predictive, top-down parsing, or back-tracking? I hope C never loses sight of it's roots nor morphs into C++ under the guise of creating a common subset, but which is really a disguised superset of C and C++ Please prevent the ever increasing demand for new features from overwhelming C's simplicity so it can no longer be parsed with simple methods.
- dpipemazo 7y agoOne of my favorite features recently while developing C for embedded systems has been the --wrap linker flag that allows me to effectively test code that interacts with hardware without modifying the source. By passing -Wl,--wrap=some_function at link time with test code we can then define __wrap_some_function that will be called instead of some function. Within __wrap_some_function one can also call __real_some_function which will resolve to the original version if you still want to call the original one. This is especially useful if trying to observe certain function calls in tests that interact with hardware. Do you have any other recommendations/preferences to help with unit-testing C code?
- ebg13 7y agoHow accurate, relevant, and useful today is http://c-faq.com http://c-faq.com ?
- _kst_ 7y agoIt's a bit dated (it hasn't been updated since 2005), but apart from that I'll say that parts of it are excellent. In particular, section 6 is the best resource I know of for explaining the often counterintuitive relationship between arrays and pointers.
- mlvljr 7y agoHow much UB does your own code contain, folks (and what practices do you follow to avoid it)? Cheers from the shadowland :)
- hsivonen 7y agoWhat’s the current committee thinking on providing locale-independent conversions from potentially-invalid UTF-8 to valid UTF-8, from potentially-invalid UTF-8 to valid UTF-16, and from potentially-invalid UTF-16 to valid UTF-8 (i.e. replacing ill-formed sequences with yhe REPLACEMENT CHARACTER)?
- DougGwyn 7y agoIf you changed UTF-16 to UTF-32 or UCS-4 I'd support it. I think there are already implementations that use the replacement character for all "impossible" codes.
- jboschpons 7y agoHola!
- clarry 7y agoOpen up WG14 mailing list for non-members? It's hard to appreciate what's going on at WG14 (or take part) when you can see the results only from afar, with none of the surrounding discussion. I recently read Jens Gustedt's blog on C2x where he casually recommended this as a way to get involved: "The best is to get involved in the standard’s process by adhering to your national standards body, come to the WG14 meetings and/or subscribing to the committee’s mailing list." Afaict (from browsing the wg14 site), the mailing list and its archives are not open to access. https://webcache.googleusercontent.com/search?q=cache:TnEGL4_UNK4J:https://gustedt.wordpress.com/2018/11/+&cd=13&hl=en&ct=clnk&gl=fi https://webcache.googleusercontent.com/search?q=cache:TnEGL4... EDIT: In general, how is one supposed to approach wg14 with ideas or need for clarification on the standard's wording / interpretation?
- AaronBallman 7y ago> In general, how is one supposed to approach wg14 with ideas or need for clarification on the standard's wording / interpretation? I'm currently working on an update to the committee website to clarify exactly this sort of thing! Unfortunately, the update is not live yet, but it should hopefully be up Soon™. Currently, the approach for clarifications and ideas both require you to find someone on the committee to ask the question or champion your proposal for you. We hope to improve this process as part of this website update to make it easier for community collaboration.
- ori_b 7y agoAgreed. I would like to get involved, but I don't see any reasonable way for me to do that as an individual.
- DougGwyn 7y agoIn general, the committee accepts what we used to call "defect reports" (now something like "requests for improvement"), assigns them "WG14 series" sequence numbers, and upon requests for "floor time" schedules meeting discussions. Occasional votes are taken, which might trigger modifications to the draft standard. At some point, the committee decides that the updated draft standard is ready for public review, and the various national representatives deal with review comments. All this starts with proposal documents in "WG14 series" form.
- deleted 7y ago[deleted]
- seamyb88 7y agoThoughts on Gnome glib, gobject, vala etc? I tend to use glib for my (academic) code for pretending C is a high-level language. It also seems to make up for implementation-dependent functions in C and many portability issues. Also, IMO, vala > C++. My question is, really, are there any other tools for high-level C programming and do you know of any disadvantages of the Gnome stack?
- jfmc 7y agoC is a great low-level language to write the engines/runtimes of other languages.
- jmckinley 7y agoIt is 2020. You are looking at a series of projects your company has teed up. All are greenfield efforts - no legacy. What would be the attributes of a project that would have you recommend C as the programming language?
- joefourier 7y agoFor anything embedded you have practically no choice but to use C (or assembly). Same goes for a lot of systems programming, e.g. writing Linux drivers.
- quelsolaar 7y agoAnything high performance: game engine, scientific computation, deep packet inspection, image analysis, machine learning, rendering engines, high frequency trading.... The list is long!
- tayistay 7y agoAFAIK, few seem to choose C for game engines or rendering engines. Not familiar with the other domains.
- JoshTriplett 7y agoWhat are the chances of typeof, or statement expressions, finding their way into the C standard? They're already widely implemented.
- msebor 7y agoSeveral of us discussed typeof and I'd expect a proposal for a feature along these lines to be well received. (I recall someone even saying they're working on one but that shouldn't stop anyone from submitting one of their own.)
- JoshTriplett 7y agoI'm glad to hear that. What about statement expressions? They're quite useful, and supported by multiple independent compilers.
- msebor 7y agoI'm not aware of recent proposals for those but we have discussed ideas along those lines (closures: N2030, C++ lambdas, Apple Blocks: N1451, and I think there was one from Cilk). I think there was interest but not enough support for the details and likely also concerns from implementers.
- aray 7y agoWhen do you think we will get an update to C11 or more recent version of C to MISRA? Do you all have any influence on "Safety Critical C" standards?
- AaronBallman 7y agoThe MISRA committee is a separate organization from the C standards committee, but there is overlap between the two groups and an official liaison process for the committees to collaborate. So there's a bit of bidirectional influence between the two groups. I am not on the MISRA committee, but I believe they talk a bit about their public roadmap in this video: https://vimeo.com/190304951 https://vimeo.com/190304951
- hedora 7y agoI frequently rely on reading and writing uninitialized struct padding in code that compare and swaps the underlying struct representation with some (up to 128bit) integer. I could use a union type, but that adds extra memory operations, and is finicky. Is there a better way?
- loeg 7y agoHave any of you looked at the CHERI hardware architecture and fat capability pointers, broadly?
- mesaframe 7y agoHow to become a compiler engineer if you don't have a degree in CS?
- deleted 7y ago[deleted]
- cyber1 7y agoKen Thompson, Rob Pike, Brian Kernighan, Russ Cox, Robert Griesemer are guys who created Unix, B, C, Go, Utf-8, etc. Maybe it will be useful to invite these guys(one of them) in the C Standards Committee for help to improve and design new language features?
- rseacord 7y agoI think a lot of these dudes are retired. A lot of good C people like P.J. Plauger, John Benito, and Clark Nelson have all retired recently. Anyway, they are all invited back. As an incentive, we typically have free coffee and snacks at most of the meetings. :)
- Koshkin 7y agoWhy not keep C a simple little language with fast compile times and delegate all "enhancements" (such as 'cleanup') to C++?
- lioeters 7y agoFrom reading all their comments up to now, my feeling is that's exactly their plan. When asked, "Where do you think C is going?", one of them said, "I don't see it going anywhere." I took that as a good thing, meaning, they're concerned about backward compatibility, compiler performance, and only adding features when there's a wide concensus in implementation - which is a high enough hurdle that avoids the feature bloat of C++. Overall, I felt the "conservatism" refreshing, to keep the language small. On the other hand, there are several common feature requests I see in this thread that probably will never be part of the language, since it moves slow relative to other languages.
- clarry 7y ago1. Are there any plans for standardizing empty initializer lists? struct foo { int a; void *p; }; struct foo f = {0}; // legal C, f->p initialized like a static variable struct foo f = {}; // not legal but supported by gcc To me it would make sense that there is no need to specify a value for any of the members that are intended to be initialized exactly like static variables (and the first member is not special so I shouldn't have to explicitly assign a zero?). However the syntax currently demands at least one initializer. -- 2. I recall seeing a proposal for allowing declarations after case labels: switch (foo) { case 1: int var; // ... } This is currently not allowed and you'd have to wrap the lines after case in braces, or insert a semicolon after the case label. Is this making it to c2x? -- 3. I've run into some recent controversy w.r.t. having multiple functions called main (and this has come up in production code). In particular, I ran into a program programs that has a static main() function (with parameters that are not void or int and char[]), which is not intended to be the* main function that is the program's entry point. gcc warns about this because the parameters disagree with what's prescribed for the program entry point. It's not clear to me whether this is intended to be legal or not. -- 4. Looking at the requirements for main brings up another question: it says how main should be defined (no static or extern keyword). However, the definition could be preceded by a static declaration, which then affects the definition that follows: If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier extern. For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible, if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the linkage specified at the prior declaration. Therefore, it is possible to have a main function with internal linkage and a definition that exactly matches the one given in the spec: static int main(int, char *[]); int main(int argc, char *argv[]) { /* ... */ } As one might guess, this program doesn't make it through the linker when compiled with gcc. Is this supposed to be legal? Should the spec perhaps require main to have external linkage, and then allow other functions called main with internal linkage (and parameters that do not match what is required of the external one)? EDIT: --- Are the fixes w.r.t. reserved identifiers going to make it in c2x? Can I finally have a function called toilet() without undefined behavior?
- jasonhansel 7y agoCan/should the C language be extended to better support vector processors and GPGPU?
- ocithrowaway 7y agoA couple of (I hope easy) requests - 1. Can we add separators in constants (C++ does 0xFFFF'FFFF'FFFF'FFFF any other reasonable scheme is fine too?) 2. I think many compilers already do this, but can the static initialization rules be relaxed a bit? static const int a = 0; static const int b = a; /* This is not standard C afaik. */ Thank you, CodeandC
- rightbyte 7y agoA binary literal would be nice too. Doing masks for embedded systems makes my head hurt sometimes. "Cpp compatibility" etc etc could be the excuse to implement it.
- msebor 7y agoWG14 in general looks favorably at proposals to align C more closely with C++ (within the overall spirit of the language) and I'd expect (1) would viewed in that light. I'd also say there is consensus that (2) would be beneficial. There are some good ideas in http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2067.pdf http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2067.pdf although I don't think repurposing the register keyword for it was very popular. Not just because it wouldn't be compatible with C++ which deprecated register some time ago, but also because it's novel with no implementation or user experience behind it. My impression that this is waiting for a new proposal.
- magicbanana 7y agoIs there a chance to ever see C++-template-like features appear in C? For instance, a lot of redundant code (or ugly macro business) could be neatly replaced by function templates. Even just template functions with only POD values allowed would be a great readability improvement.
- MiKom 7y agoIt's already there. It's called C++ templates
- SaxonRobber 7y agocan we get compile time constant variables? something cleaner than enums and defines
- commandersaki 7y agoA few years ago I came across this article Pointers Are More Abstract Than You Might Expect In C [1]. I followed the article which attempted to interpret the C standard and come to a conclusion. The conclusion is: > The takeaway message is that pointer arithmetic is only defined for pointers pointing into array objects or one past the last element. Comparing pointers for equality is defined if both pointers are derived from the same (multidimensional) array object. Thus, if two pointers point to different array objects, then these array objects must be subaggregates of the same multidimensional array object in order to compare them. Otherwise this leads to undefined behavior. Based on the above, I arrived at the conclusion after reading this that comparing two distinct malloc()'d pointers for equality itself is undefined behaviour since malloc() is likely to return pointers to distinct objects that are not part of a sub-aggregate object. I know this is incorrect, but I don't know why I'm wrong. [1]: https://stefansf.de/post/pointers-are-more-abstract-than-you-might-expect/ https://stefansf.de/post/pointers-are-more-abstract-than-you...
- pascal_cuoq 7y agoThe only thing that is not defined is comparing a pointer one-past-the-end to a pointer to the very beginning of a toplevel object. Apart from this rule, pointers of course do not need to be derived from the same object in order to be compared with == and !=. &a + 1 == &b is unspecified: it may produce 0 or 1, and it may not produce the same result if you evaluate it several times. Similarly, if both the char pointers p and q were obtained with malloc(10), after they have been tested for NULL, all these operations are valid: p == q (false) p + 1 == q (false) p + 1 == q + 1 (false) p + 10 == q + 1 (false) Only p+10 == q and p == q+10 are unspecified (of the comparisons that can be built without invoking UB during the pointer arithmetic itself). I have no idea what led that person to (apparently) write that &a==&b is undefined. This is plain wrong. I do not see any ambiguity in the relevant clause (https://port70.net/~nsz/c/c11/n1570.html#6.5.9p6 https://port70.net/~nsz/c/c11/n1570.html#6.5.9p6 ). Yes, the standard is in English and natural languages are ambiguous, but you might as well claim that a+b is undefined because the standard does not define what the word “sum” means (https://port70.net/~nsz/c/c11/n1570.html#6.5.6p5 https://port70.net/~nsz/c/c11/n1570.html#6.5.6p5 ).
- gautamcgoel 7y agoCurious what the committee members think of the new competitors to C, e.g. Go, Rust, and Zig. Any comments?
- VWWHFSfQ 7y agogo isnt a competitor to c
- pjmlp 7y agoF-Secure apparently thinks otherwise, https://www.f-secure.com/en/consulting/foundry/usb-armory https://www.f-secure.com/en/consulting/foundry/usb-armory As does Google, https://github.com/google/gvisor https://github.com/google/gvisor https://github.com/google/gapid https://github.com/google/gapid Naturally if one is talking about specific uses cases like IoT with a couple of KBs, MISRA-C, or UNIX kernels, then yes Go is not a competitor.
- cyber1 7y agoHow close C Standard Committee works with Linux Kernel Developers? Is Linux Kernel development influence on C standard?
- AaronBallman 7y agoThere's not an official collaboration between the committee and the kernel developers (that I'm aware of), but we do have people on the committee who need to support Linux kernel development (such as GCC maintainers), so there is some level of indirect influence there.
- commandersaki 7y agoWill Effective C cover the strict aliasing rule and also why the BSD sockets API seems to get away with it (e.g. (sockaddr *) &sockaddr_in)?
- DougGwyn 7y agoI thought we had fixed the BSD socket aliasing a long time ago?
- AaronBallman 7y agoI don't think the book covers strict aliasing, at least not in detail.
- saagarjha 7y agoIsn't that legal if they are all in a union?
- Uptrenda 7y agoWhat would you say to people who claim that writing "secure C code" is impossible [not me but I'm curious what you all think]?
- AaronBallman 7y agoI'd ask them if they really meant "impossible" or just "harder than I wish it was". I've typically found that the tradeoffs between security, performance, and implementation efforts are usually more to blame for why writing secure C code is a challenge. There are a ton of tools out there to help with writing secure code (compiler diagnostics, secure coding standards, static analyzers, fuzzers, sanitizers, etc), but you need to use all the tools at your disposal (instead of only a single source of security) which adds implementation cost and sometimes runtime overhead that needs to be balanced against shipping a product. This isn't to suggest that the language itself doesn't have sharp edges that would be nice to smooth over, though!
- freemind 7y agoDo you think object oriented languages are better than C to develop GUI-based cross-platform programs? The licenses of the majority of third-party libraries available for C are GPL, do you think this makes harder reusing code to sell software?
- tzs 7y agoIf an old timer who used to be good with C wanted to use C again, would they have to learn a whole bunch of weird new stuff or could they pretty much use it like they did back in the stone age (i.e., the 20th century)? Back in the '80s and '90s I was pretty good at C. I don't think there was anything about the language or the compilers than that I did not understand. I used C to write real time multitasking kernels for embedded systems, device drivers and kernel extensions for Unix, Windows, Mac, Netware, and OS/2. I did a Unix port from swapping hardware to paging hardware, rewriting the processes and memory subsystems. I tricked a friend into writing a C compiler. I could hold my own with the language lawyers on comp.lang.c. Somewhere in there I started using C++, but only as a C with more flexible strings, constructors, destructors, and "for (int i = ...)", and later added STL containers to that. Sometime in the 2000s, I ended up spending more and more time on smaller programs that were mostly processing text, and Perl became my main tool. Also I ended up spending a lot of helping out less experiences people at work who were doing things in PHP, or JavaScript, or Java. My C and C++ trickled to nothing. I've occasionally looked at modern C++, but it is so different from what I was doing back in '90s or even early '00s I sometimes have to double check that I'm actually looking at C++ code. Is modern C like that, or is it still at its core the same language I used to know well?
- AaronBallman 7y agoI'd put it this way -- as someone who writes both C and C++ and has for a long while, I find that the difference between "best practice" C89 and C17 code is not as wide as the difference between "best practice" C++98 and C++17 code. However, this is subjective and may be specific to what kinds of projects I work on, so YMMV.
- msebor 7y agoC17 doesn't look much different than C89. If you are used to K&R C there may be some adjustment but I would expect it to be manageable. What might perhaps be more challenging is adjusting to the changes in compilers. They tend to optimize code more aggressively and so writing code that closely follows the rules of the language (rather than making assumptions about the underlying hardware, even valid ones) is more important today than it was back in the 80's.
- grok22 7y agoThings I would like C to have: - stricter type-checks on typedef types (useful when passing function parameters) - gcc's ' warn_unused_result' attribute for functions (ensure error returns are checked) - on-entry/on-exit qualifiers for functions (to do things like make sure you lock/unlock semaphores for instance before entry/exit of function) - D language's 'scope' feature (better handling of error path) - loops in the c pre-processor! (better code-gen) Any chance any of this is on the radar for the next-gen C standard? Some of these are just ergonomics, but the first two might've have saved me some grief a few times.
- _kst_ 7y agotypedef, in spite of the name, doesn't create a new type. It only creates a new name for an existing type. Changing that would break existing code. I wouldn't mind seeing a new feature that does define a new type (one that's identical to, but incompatible with, an existing type), but we can't call it "typedef". In a sense that feature already exists. You can define a structure with a single member of an existing type. But you have to refer to the member by name to do anything with it.
- bonzini 7y agoIs there any reason to keep the undefined behavior for shifts of negative numbers, instead of making it implementation defined? Most compilers (for twos-complement architectures at least) are not using that latitude, and I would also guess that most programs that are written for twos-complement arithmetic likewise not expecting undefined behavior for non-overflowing left shifts of negative numbers. Thanks!
- DougGwyn 7y ago"Implementation-defined" is a nuisance, because then you need to add code for all the variations, which also requires a set of standard macros, etc. It is easier and less trouble-prone to just avoid using the currently undefined behavior.
- deleted 7y ago[deleted]
- ori_b 7y agoWhat do you think of a variant on this? https://blog.regehr.org/archives/1180 https://blog.regehr.org/archives/1180
- dang 7y agopascal_cuoq cowrote it. Maybe we should ask him if his views have changed since then. Btw, there was a thread about it at the time: https://news.ycombinator.com/item?id=8233484 https://news.ycombinator.com/item?id=8233484.
- pascal_cuoq 7y agoThanks Dan, I missed this question in the heat of the moment.
- pascal_cuoq 7y agoI still want to write at least one sequel to that post, on the theme “Alright, can we make a Friendly C Compiler by disabling the annoying optimizations, then?”. Obviously the people who want a Friendly C Compiler do not want to disable all optimizations. This would be easy to do, but these users do not want the stupid 1+2+16 expressions in their C programs, generated through macro-expansion, to be compiled to two additions with each intermediate result making a round-trip through memory. So the question is: can we get a Friendly C Compiler by enabling only the Friendly optimizations in an unfriendly compiler? And for the answer to that, I had to write an entire other blog post as preparation, to show that there are some assumptions an optimizing compiler can do: - that may be used in one or several optimizations, but the compiler authors did not really keep track of where they were used, - that cannot be disabled and that the compiler maintainers will not consider having an option to disable, - and that are definitely unfriendly. Here is the URL of the blog post that I had to write in preparation for the upcoming blog post about getting ourselves a Friendly C Compiler: https://trust-in-soft.com/blog/2020/04/06/gcc-always-assumes-aligned-pointers/ https://trust-in-soft.com/blog/2020/04/06/gcc-always-assumes... . I recommend you take a look, I think it is interesting in itself. You will have guessed that I'm not optimistic about the approach. We can try to maintain a list of friendly optimizations for ourselves, though, even if the compiler developers are not helping. This might still be less work that maintaining a C compiler.
- hellofunk 7y agoI really like the relative simplicity of C compared to C++ and recently wrote a project in C, but eventually rewrote it in C++ for just a few seemingly trivial reasons that nonetheless were important time savers. I'd love to know if the C standard, as can run on GPUs also, will ever evolve to offer: 1) namespaces, so function names don't need to be 30 characters to avoid naming collision 2) guaranteed copy elision or RVO -- provides greater confidence for common idioms and expressivity compared to passing out parameters
- pornel 7y agoWould you consider adding a built-in way to safely multiply two numbers? Numeric overflows in things like calculation of buffer sizes can lead to vulnerabilities. Signed overflow is UB, and due to integer promotion signs creep in unexpected places. It's not trivial to check if overflow happened due to UB rules. A naive check can make things even worse by "proving" the opposite to the optimizer. And all of that is to read one bit that CPUs have readily available.
- DougGwyn 7y agoThere are a lot of arithmetic conditions for which C could generate special code. There are div_t-related functions for the other direction. I for one would like a good way to obtain, using some Standard C coding pattern, fast "carry" for multiple-precision integer arithmetic. Several places in support functions, I have coded unusually to avoid wrap-around etc. I bet you could devise something like that for (unsigned) multiplication.
- tropo 7y agoA horrifying case was multiplication in an x86 emulator. The opcode handler needed to multiply a pair of unsigned 16-bit values, then return a 64-bit result. The uint16_t got promoted to an int for the multiplication, causing undefined behavior. (if I remember right, the result was assigned to a uint16_t as well, making the intent clear) The compiler then assumed that the 32-bit intermediate couldn't possibly have the sign bit set, so it wouldn't matter if promotion to a 64-bit value had sign extension or zero extension. Depending on the optimization level, the compiler would do one or the other. This is truly awful behavior. It should not be permitted.
- tropo 7y agoFound it: http://kqueue.org/blog/2013/09/17/cltq/ http://kqueue.org/blog/2013/09/17/cltq/
- flatfinger 7y ago
- arunc 7y agoWhat do you think about D language's mode to work as a better C alternative[0]? It seems to even do printf format validation. Can this be the future of C? [0] https://dlang.org/spec/betterc.html https://dlang.org/spec/betterc.html
- radford-neal 7y agoThe syntax used in the following function definition is said to be obsolescent in C11: int f (a, n) int n; int a[n][n]; { return a[n-1][n-1]; } How could one define this function without using the obsolete syntax?
- AaronBallman 7y agoYou couldn't in that parameter order. However, you could do this: int f(size_t n, int a[n][n]) { return a[n-1][n-1]; } (https://godbolt.org/z/DV9c-C https://godbolt.org/z/DV9c-C) Btw, that definition was obsolescent in C89 too.
- radford-neal 7y agoWell, yes. But putting the array argument(s) first is the more natural order, in my opinion. And it is surely odd that only one order is allowed in this context, when otherwise C is happy with changing the order of parameters to be whatever you like. Plus, of course, there may be existing code using such functions, with parameters in the order that would become impossible if this syntax were disallowed.
- tridentboy 7y agoKnow it's not exactly related to what you do. But do you have some recommendations of books/online classes to learn C?
- modeless 7y agoCan you do anything to push Microsoft to implement recent C standards? Their failure to fully implement even C99 in Visual Studio is holding the language back.
- AaronBallman 7y agoNot really -- vendors are free to ignore newer releases of the standard that do not meet their customers needs and the committee can't do much about it. However, as a user, you can help apply pressure on the vendor to support newer standards. For instance, with Microsoft, you could support this feedback request: https://developercommunity.visualstudio.com/idea/387315/add-c11-support.html https://developercommunity.visualstudio.com/idea/387315/add-...
- DougGwyn 7y agoThere is little that the C Standards group can do about it. One idea is to write a C Standards conformance into contracts. When I was in the government we often did that, but it still wasn't enough clout.
- DerekL 7y agoMy understanding is that Microsoft doesn't want to support C, and the only reason Visual Studio supports C at all is for legacy code. Also, you can use 3rd-party compilers with Visual Studio. Really, anyone writing C nowadays should ignore Microsoft's compiler, and tell Visual Studio users to install Clang.
- DougGwyn 7y agoBack from lunch. Any West Coasters?
- pjmlp 7y agoMicrosoft's "Checked C" seems to be the last attempt to fix C security flaws. From the outside, after Annex K adoption failure, WG14 doesn't seem to be willing to make C safer in any way. Are there any plans to take efforts like Checked C in consideration regarding the future of ISO C?
- hyc_symas 7y agoThe standard string library is still pretty bad. This would have been a much better addition for safe strcpy. Safe strcpy char *stecpy(char *d, const char *s, const char *e) { while (d < e && *s) *d++ = *s++; if (d < e) *d = '\0'; return d; } main() { char buf[64]; char *ptr, *end = buf+sizeof(buf) ; ptr = stecpy(buf, "hello", end); ptr = stecpy(ptr, " world", end); } Existing solutions are still error-prone, requiring continual recalculation of buffer len after each use in a long sequence, when the only thing that matters is where the buffer ends, which is effectively a constant across multiple calls. What are the chances of getting something like this added to the standard library?
- msebor 7y agoThere are many improved versions of string APIs out there, too many in fact to choose from, and most suffer from one flaw or another, depending on one's point of view. Most of my recent proposals to incorporate some that do solve some of the most glaring problems and that have been widely available for a decade or more and are even parts of other standards (POSIX) have been rejected by the committee. I think only memccpy and strdup and strdndup were added for C2X. (See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2349.htm http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2349.htm for an overview.)
- AceJohnny2 7y ago> Most of my recent proposals [...] have been rejected by the committee. Does anyone have insight on why?
- saagarjha 7y agomemccpy is a very welcome addition in the front of copying strings; what else were you thinking of proposing?
- doublesCs 7y agoWhat's wrong with: *p += sprintf(*p, "hello"); *p += sprintf(*p, "world");
- rurban 7y ago1. When will we get proper strings in the stdlib? 2. When we will get the Secure Annex K extensions? 3. When we will get mandatory warnings when the compiler decides to throw away statements it thinks it doesn't need? Like memset or assignments. Compilers are getting worse and worse, and certainly not better. ad 1) Strings are Unicode nowadays, not ASCII. Nobody uses wchar but Microsoft. Everybody else is using utf8, but there's nothing in the standard. Not even search functions with proper casing rules and normalization. Searching for strings should be pretty basic enough. 2. The usual glibc answer is just bollocks. You either do compile-time bounds checks or you don't. But when you don't, you have to do it at runtime. So it's either the compilers job, or the stdlib job. But certainly not the users.
- rseacord 7y agoFor (3) mandatory warnings the closest thing is probably ISO/IEC TS 17961:2013. The purpose of ISO/IEC TS 17961 is to establish a baseline set of requirements for analyzers, including static analysis tools and C language compilers, to be applied by vendors that wish to diagnose insecure code beyond the requirements of the language standard. All rules are meant to be enforceable by static analysis. The criterion for selecting these rules is that analyzers that implement these rules must be able to effectively discover secure coding errors without generating excessive false positives.
- rseacord 7y agoGoing to try to answer these separately. For (1) if you mean strings that are primitive types my guess is never. When had an hour discussion on this topic at a London meeting where we were discussing new features for C11 and my take away was that this would never happen because it would require a significant change to the memory model for the language.
- rurban 7y agoFor the u8 type sure. Nobody needs a new type. But at least add wcsnorm and wcsfc as I implemented them in the safeclib are required. Not even coreutils, grep, awk, ... can search unicode strings. And u8 library variants of str* and wcs* are definitely needed, maybe just with uchar* not char*.
- deleted 7y ago[deleted]
- deleted 7y ago[deleted]
- deleted 7y ago[deleted]
- networkimprov 7y agoHas there been consideration of async/await semantics?
- rseacord 7y agoMany of your remaining questions have devolved into "When will I see my favorite feature xyz appear in the C Standard?" The answer in most cases is "that depends on how long it takes you to submit a proposal". Take a look at http://www.open-std.org/jtc1/sc22/wg14/www/wg14_document_log.htm http://www.open-std.org/jtc1/sc22/wg14/www/wg14_document_log... for previous proposals and review the minutes to see which proposals have been adopted. In general, the committee is not going to adopt proposals for which there is insufficient existing practice or haven't been fully thought out. There are cases where people have come to a single meeting with a well-considered proposal that was adopted into the C Standard. I wrote about one such case here: https://www.linkedin.com/pulse/alignment-requirements-memory-management-functions-robert-seacord/ https://www.linkedin.com/pulse/alignment-requirements-memory... Alternatively, you can approach someone on the committee and ask us to champion a proposal for you. It is likely that we'll agree or at least provide you with feedback on your proposal.
- sramsay 7y agoThanks to one and all for this AMA! The massive number of comments testifies to the continuing interest in C, and I think we're all grateful to all of you for your expertise, your patience, and your even-handed responses.
- flatfinger 7y agoIs the present purpose of the Standard to: 1. define a highly-extensible abstraction model, which implementations intended for various purposes should be expected to extend to suit those purpose, or 2. define an abstraction model which is sufficiently complete that programs can do everything that would need to be done, without need for extensions? Reading the C89 and C99 Rationale documents, it's clear that those standards were intended to meet the former purpose. The way some compilers treat "Undefined Behavior", however, suggests that the maintainers view the Standard as aimed toward the latter purpose. During the 1980s and 1990s, it was generally cheaper and easier for implementations to extend the Standard's abstraction model by specifying that many actions would be processed "in a documented fashion characteristic of the environment" than it would have been to do anything else, so there was no need to worry about whether the Standard allowed programmers to specify when such behavior was required. That no longer holds true, however. While it would be reasonable to deprecate code which relies upon such treatment without explicitly demanding it, such deprecation would only make sense if there were a means of demanding such treatment when required. For the Committee to provide such means, however, it would have to reach a consensus as to the purposes for which the Standard's abstraction model is meant to be suitable. Are you aware of any such consensus?
- wpietri 7y agoAs experts, where do you see C going? In particular, given the many languages now out there built on decades of learnings from C, where will C have unique strengths? What projects starting today and hoping to run for 20 years should definitely pick C?
- rseacord 7y agoI don't really see C going anywhere. It's not going away, and it's not going to evolve into Java. It's going to remain especially useful for memory constrained and performance critical applications such as IoT and embedded.
- wpietri 7y agoThat sounds reasonable, but the resource-constrained space seems to me to be an ever-shrinking share of the field. So is it fair to say you see C becoming a specialist niche language going forward?
- tayistay 7y agoI'm no C expert, but my two wishes for C would be: - Basic type inference to reduce keystrokes, and prevent ripples when changing types. (like auto in C++) - Equality operators defined for structs. Perhaps even lexicographical comparison, if I'm dreaming. Any thoughts on either of those?
- cyber1 7y agoI think C is an exceptional good language for a long time, but the world is changing and maybe C must evolve with new trends, new researches in programming languages. In my view C and C++ now almost different languages with a different philosophy of programming, different future, and different language design. It will be sad if "modern" C++ almost replace C. Many C++ developers use "Orthodoxy C++" https://gist.github.com/bkaradzic/2e39896bc7d8c34e042b https://gist.github.com/bkaradzic/2e39896bc7d8c34e042b, and this shows that people will be more comfortable with C plus some really useful features(namespaces, generics, etc), but not modern C++. I very often hear from my job colleagues and from many other people who work with C++ is how terrible modern C++ (https://aras-p.info/blog/2018/12/28/Modern-C-Lamentations/ https://aras-p.info/blog/2018/12/28/Modern-C-Lamentations/, https://www.youtube.com/watch?v=9-_TLTdLGtc https://www.youtube.com/watch?v=9-_TLTdLGtc) and haw will be good to see and use new C but with some extra features. Maybe time to start thinking about evolution C, for example: - Generics. Something like generics in Zig, Odin, Rust. etc. - AST Macros. For example Rust or Lisp macroses, etc. - Lambda - Defer statement - Namespaces What do you think? https://ziglang.org/documentation/master/#Generic-Data-Structures https://ziglang.org/documentation/master/#Generic-Data-Struc... https://odin-lang.org/docs/overview/#parametric-polymorphism https://odin-lang.org/docs/overview/#parametric-polymorphism https://doc.rust-lang.org/rust-by-example/generics.html https://doc.rust-lang.org/rust-by-example/generics.html
- dhhwrongagain 7y agoIs memset(malloc(0), 0, 0) undefined behavior?
- DougGwyn 7y agoLet's assume the types have been corrected. malloc((size_t)0) behavior is defined by the implementation; there are two choices: (a) always returns a null pointer; or (b) acts like malloc((size_t)1) which can allocate or fail, and if it allocates then the program shall not try to reference anything through the returned non-null pointer. Now, memset itself is required (among other things) to be given as its first argument a valid pointer to a byte array. In particular, it shall not be a null pointer. Tracking through the conformance requirements, if the malloc call returns a null pointer then the behavior is undefined. Thus, you should not program like this.
- dhhwrongagain 7y agoWhat observable difference is there between malloc(0) and malloc((size_t)0)?
- saagarjha 7y agoNone.
- dhhwrongagain 7y agoI agree but he said the types needed to be corrected. As far as I know the types were already correct.
- DougGwyn 7y agoThe argument "0" is not automatically converted to the right type unless there is a prototype in scope. It isn't as important in this case because it is highly likely that the appropriate prototype has been #included, but it is a bigger deal if we're dealing with arguments for a variadic function. Anyway, it's good to be reminded what the declared types are.
- tayistay 7y agoTo what extent does compiler complexity factor into your thinking about the evolution of C? Thanks for this!
- AaronBallman 7y agoWhen the committee considers proposals, we do consider the implementation burden of the proposal as part of the feature. If parts of the proposal would be an undue burden for an implementation, the committee may request modifications to the proposal, or justification as to why the burden is necessary.
- tayistay 7y agoThanks. Do you have an example of a proposal that the committee considered an undue burden for an implementation but was otherwise sound?
- AaronBallman 7y agoNot off the top of my head, but as an example along similar lines, when talking about whether we could realistically specify twos complement integer representations for C2x, we had to determine whether this would require an implementation to emulate twos complement in order to continue to support C. Such emulation might have been too much of a burden for an implementation's users to bear for performance reasons and could have been a reason to not progress the proposal.
- mcguire 7y agoAny chance of getting something like Frama-C officially blessed?
- WalterBright 7y agoI wrote about a simple addition to C that could eliminate most buffer overflows: https://www.digitalmars.com/articles/C-biggest-mistake.html https://www.digitalmars.com/articles/C-biggest-mistake.html I.e. offering a way that arrays won't automatically decay to pointers when passed as a function parameter.
- quelsolaar 7y agoArrays are pointers. If they aren't pointers then you need to copy the data when you are giving an array as a function parameter. that's a lot slower. Being able to prepare an set of data in an array and then giving a pointer to a function is very useful. You could add a second type of array on top of what you have in C that includes more stuff, but if that's what you want you can implement that yourself with a struct.
- napsy 7y agoAn array is not a pointer. These are completely different data types. For example, you can't apply pointer arithmetic to arrays without casting them to pointers.
- WalterBright 7y agoThat's right. They are converted to pointers when passed to a function, even if the function declares the parameter as an array.
- napsy 7y agoThey're not converted but can be implicitly casted to pointer types.
- _kst_ 7y agoNo, they're converted. There is no such thing as an "implicit cast". And it's not specific to arguments in function calls. Array types and pointer types are distinct. An expression of array type is, in most but not all contexts, implicitly converted (really more of a compile-time adjustment) to an expression of pointer type that yields the address of the 0th element of the array object. The exceptions are when the array expression is the operand of a unary & (address-of) or sizeof operator, or when it's a string literal in an initializer used to initialize an array (sub)object. (The N1570 draft incorrectly lists _Alignof as another exception. In fact, _Alignof can only take a parenthesized type name as its operand.) If you do: int arr[10]; some_func(arr); then arr is "converted" to the equivalent of &arr[0] -- not because it's an argument in a function call, but because it's not in one of the three contexts listed above in which the conversion doesn't take place. Another rule that causes confusion here is that if you define a function parameter with an array type, it's treated as a pointer parameter. For example, these declarations are exactly equivalent: void func(int arr[]); void func(int arr[42]); // the 42 is quietly ignored void func(int *arr); Suggested reading: http://www.c-faq.com/ http://www.c-faq.com/, particularly section 6, "Arrays and Pointers". A conversion converts a value of one type to another type (possibly the same one). The term "cast" refers only to an explicit conversion, one specified by a cast operator (a parenthesized type name preceding the expression to be converted, like "(double)42"). An implicit conversion is one that isn't specified by a cast operator.
- quelsolaar 7y agoA few proposals: Why not mandate a warning every time the compiler detects and makes use of UB? It would solve SO many issues. If you are looking to improve security of C programs, then letting the user know what the compiler does should be number one. Try to convert as many UB's to Platform specific, as possible would also be a big help. I would love to see native vector types. Its time. Vector types are now more common in hardware then float was when it was included in the C spec. Time to make it a native type. Hoping the compiler does the vectorization for you is not good enough. Allow for more then one break. for(i = 0; i < n; i++) for(j = 0; j < n; j++) if(array[i][j] == x) break break; is equal to: for(i = 0; i < n; i++) for(j = 0; j < n; j++) if(array[i][j] == x) goto found; found :
- clarry 7y ago> Why not mandate a warning every time the compiler detects and makes use of UB? It would solve SO many issues. Because that's hardly ever what happens, except when it actually does, and compilers do an increasingly good job of issuing diagnostics in that case. If you actually mandated it, no compiler today would come close to being standards compliant. This comes close to making the language unimplementable. The most common issue with UB and optimizations is not that "compiler detects UB and does something with it," it's that compiler analyzes and optimizes code with the assumption that UB doesn't actually happen. It doesn't know whether it does (and in general, it is impossible to tell whether it would happen -- it's something that might or might not happen at run time, and proving it one way or another amounts to solving the halting problem), it just assumes it doesn't. And if one mandated compilers to report every time they make an optimization that is valid under the assumption that the program is well behaved, then you would never finish reading compiler output. Or you would turn off optimizations.
- quelsolaar 7y agoThey need to do better then remove NULL checks silently. You can read all about Linus rants on this. Every time the compiler breaks things they blame the C standard for letting them do what ever. Thats whats wrong with C today. The C standard hasn't put its foot down.
- clarry 7y agoWhy can't I have flexible array members in union? Consider this: struct foo { enum { t_char, t_int, t_ptr, /* .. */ } type; int count; union { char c[]; int i[]; void *p[]; /* .. */ }; }; This isn't allowed, since flexible array members are only allowed in structs (but the union here is exactly where you'd put a flexible array member if you had only one type to deal with). Furthermore, you can't work around this by wrapping the union's members in a struct because they must have more than one named member: struct foo { enum { t_char, t_int, t_ptr } type; int count; union { /* not allowed! */ struct { char c[]; }; struct { int i[]; }; struct { void *p[]; }; }; }; But it's all fine if we either add a useless dummy variable or move some prior member (such as count) into these structs: struct foo { enum { t_char, t_int, t_ptr } type; int count; union { /* this works but is silly and redundant */ struct { int dumb1; char c[]; }; struct { int dumb2; int i[]; }; struct { int dumb3; void *p[]; }; }; }; Of course, you could have the last member be union { char c; int i; void *p; } u[]; but then each element of u is as large as the largest possible member which is wasteful, and u can't be passed to any function that expects to get a normal, tightly packed array of one specific type.
- begriffs 7y agoWhat does the presence or absence of __STDC_ISO_10646__ indicate exactly? I found this part of the C99 spec obscure. For instance, the macOS clang environment does not define this symbol. Is their implementation of wchar_t or <wctype.h> lacking some aspect of Unicode support?
- AaronBallman 7y agoIf that macro is defined, then wchar_t is able to represent every character from the Unicode required character set with the same value as the short code for that character. Which version of Unicode is supported is determined by the date value the macro expands to. Clang defines that macro for some targets (like the Cloud ABI target), but not others. I'm not certain why the macro is not defined for macOS though (it might be worth a bug report to LLVM, as this could be a simple oversight).
- begriffs 7y agoWould the following be a correct way to determine whether there's a problem? * First call setlocale(LC_CTYPE, "en_US.UTF-8") * Next feed the UTF-8 string representation of every Unicode codepoint one at a time to mbstowcs() and ensure that the output for each is a wchar_t string of length one * If all input codepoints numerically match the output wchar_t UTF-32 code units, then the implementation is officially good, and should define __STDC_ISO_10646__?
- rseacord 7y agoShould work provided your wchar_t type is at least 21-bits wide.
- AaronBallman 7y agoI think this is correct, assuming that locale is supported by the implementation and wchar_t is wide enough, but I am by no means an expert on character encodings.
- jfim 7y agoOut of curiosity, if there was anything you could change about C, and not have to worry about breaking existing code or any other practical concern, what would it be, and why?
- eska 7y agoThere's a compiler attribute in GCC to promise that a function is pure, i.e. free from side effects and only uses its inputs. This is useful for parallel computations, optimizations and readability, e.g. sum += f(2); sum += f(2); can be optimized to x = f(2); sum += x; sum += x; Would the current motto of the consortium forbid adding a feature such as marking a function as pure, that would not just promise, but also enforce that no side effects are caused (only local reads/writes, only pure functions may be called), and no inputs except for the function arguments are used?
- kazinator 7y agoNo enforcing! This is useful even when it's, strictly speaking, a lie. Suppose I want to add some debug tracing into f(): f.c: 42: f entered f:c: 43: returning 2 that's a side effect, right? But now the pure attribute tells a lie. Never mind though; I don't care that some calls to f are "wrongly" optimized away; I want the tracing for the ones that aren't. In C++ there are similar situations involving temporary objects: there is a freedom to elide temporary objects even if the constructors and destructors have effects. Even a perfectly pure function can have a side effect, namely this one: triggering a debugger to stop on a breakpoint set in that function! If a call to f(2) is elided from some code, then that code will no longer hit the breakpoint set on f. Side effect is all P.O.V. based: to declare something to be effect-free in a conventional digital machine, you have to first categorize certain effects as not counting.
- gbear605 7y agoJust offer a -Wpure flag for checking if functions are pure. That way production/test releases can check while you can still use it for debugging. Also, the problem with eliding breakpoints already exists afaik, since the compilers already check for pure functions.
- flatfinger 7y agoSuch attributes would be most useful if the semantics were that any time after a program receives inputs that would cause a "pure" function to be called with certain arguments, a compiler may at its leisure call the function with those arguments as many or as few times as it sees fit. The notion that "Undefined Behavior" is good for optimization is misguided and dangerous. What is good for optimization is having semantics that are loose enough to give the compiler flexibility in how it processes things, but tight enough to meet application requirements. Instead of saying that compilers can do anything they want when their assumptions are violated, it would be far more useful to recognize what they are allowed to do on the basis of certain assumptions. For example, given a piece of code: long long test1(long long x, int mode) { while(x) x = slow_function_no_side_effects(x); return x; } void long test2(long long x, int mode) { x = test1(x); if (!mode) x=0; doSomething(x); } It would generally be useful and safe to allow a compiler that determines that no individual action performed by "test1()" could have any side effects may omit the call to "test1()" if its value never ends up being used, without having to prove that the slow function with no side effects will eventually return zero. It is likewise useful and safe to say that if the generated code observes either that the loop exits or that "mode" is zero, it may replace the call "doSomething(x)" with "doSomething(0)". The fact that both optimizations would be safe and useful individually, however, does not imply that it would be safe and useful to allow compilers to change the code for "test2()" so that it calls "doSomething(0)" or otherwise allow code to observe that the value of "x" is zero when mode is non-zero, without regard for whether "test1()" would complete.
- kazinator 7y agoCAN I HAZ UNNAMED UNUSED PARAM void callback(int x, void *) // VOID STAR UNUZED, SO ANON { foo(x); }
- DougGwyn 7y agoWhy is there a second argument which is not used?
- begriffs 7y agoHas there been a survey to determine what percentage of known compilers support each C version, like C89, C99, C11? I've been sticking to C99 because I assumed later versions won't be widely adopted for a long time to come. Is this accurate?
- DougGwyn 7y agoThere is a Web page I saw a few days ago that does that, probably findable by grepping Wikipedia. Unfortunately I forget its URL.
- 7532yahoogmail 7y agopascal_cuoq - Pascal Cuoq is the Chief Scientist at TrustInSoft and co-inventor of the Frama-C technology This looks to be a hell'va' good tool chain. I'm playing with as of yesterday.
- neop1x 7y agoIn my opinion C is good as it is. C++ is terrible complicated mess, always have been and adding more and more "modern" functionality isn't helping it much. There are great standard functions, e.g. for strings in C, whereas it is often very inconvenient or complicated to do simple things like uppercase string in C++. I always ended up basically using C with just basic OOP functionality from C++. But I am not writing in C/C++ daily so my opinion is not very important...
- shivambw 7y agoWhat are your recommendations on going about learning the C language properly? And How to go about learning all levels of abstraction of the language?
- layoutIfNeeded 7y agoHmm seems to be an intersting thread. >Cmd + F >“Rust” >34 results Nnnnnnope, better close this tab.
- badrabbit 7y agoHi, I have two questions. 1) Are there any plans or discussions on having a subset/extension of C that is designed for formal verification? Much like SPARK with ADA. 2) Is there no plan to support GC? Even as an extension of C?
- kizer 7y agoHow should I represent Unicode in memory?! UTF8? 16? 32bit integers? I keep hearing pros and cons of all the previous three. Is there a consensus? In cases where you don’t need a full blown Unicode lib.
- kerkeslager 7y agoHow do modern C developers approach writing secure network code in C? Are there any tools for verifying network code?
- rs23296008n1 7y agoModern C language features: - Why no sized text strings? - Why is there no hash data type? - Where's the linked list? - Why no package management as part of ecosystem? What is the modern rationale? Caveats: - I'm not implying any need for object-orientation (OOP) - I'm fully aware I can write these myself and can access third party libraries that have each laboriously implemented their own versions. - I'm interested in why these are not native C constructs in 2020. I appreciate why not in 1980.
- shivambw 7y agoWhat is the difference between C objects(#aka region of data storage in the execution environment, the contents of which can represent value) and objects in C++ in terms of representations and usage? # from Chp2 of Effective C
- holografix 7y agoIs a time of Rust and Golang, how is C still relevant? (Sincere question)
- saagarjha 7y agoThere's millions of lines of C code that isn't going anywhere, and still many platforms that those languages don't support.
- defectbydesign 7y agoI am sorry to tell this but the C programming language doesn't need anymore the ISO committee since it introduced non de facto standard features such as VLA. For reference I still use The C Programming Language by KERNIGHAN/RITCHIE and The Standard C Library by PLAUGER. In my view what programmers need the most is good practices rather than any syntactic sugar. I prefer C rather than any other programming language for its conciseness. There is opportunities for any new programming language to replace C if it is at least backward compatible with K&R C SE (aka ISO C90) and provides a portable access to de facto standard hardware acceleration such as SIMD instructions for vector computing. For now we have to write in assembly language SIMD optimized libraries in order to get the full calculation power of modern processors. For programmers who expect C to bring them a hot drink, I would recommend them to stick with the bloated C++ framework which sometimes enlarges your p*s. :-P
- defectbydesign 7y agoNo answer but -2 points. It seems cowards don't have any argument. :-)
- ndesaulniers 7y agoWhat GNU C extensions do you think ISO WG14 would more readily accept?
- ellis0n 7y agoHi, I'm 20 years dev and I love C. C is my second language after assembler. A good days with Turbo C with 20 MB hard drive and 8086 without IT marketing and viruses. I working on a real-time reverse-debugger for new programming platform. It's possible to debug C code and prevent NULL and memory exceptions. I create my language based on C and removed all keywords, and it works perfectly. I want to make a gcc backend to my programming language and all features will be available for any C-programs. How I can find help for this?
- complangc 7y agoAnybody know where Dan Pop went and what he's up to these days?
- atum47 7y agoYeah, I don't program much in C and I don't have a question. I'm here just to congratulate everyone involved for this amazing thing. It's awesome to see people take the time to help each other. Nice job!
- smlckz 7y agoI want this feature in the standard. If there exists any memory block allocated using malloc() / calloc() / realloc() which has not been free()'d, at the end of the program, they would be free()'d automatically. One can easily do it with keeping a linked list and using atexit(), but, can it be added to the standard? A general question, will anything, any feature, which is "easy" to implement in pure C, like array knowing its own length or pascal strings, NOT be allowed to be in C standard, even if it is widely used, maybe almost everywhere?
- bch 7y agoThe operating system handles this for you on process deletion. Lots of “one shot” programs count on this (and (e.g.) file descriptors being automatically closed).
- smlckz 7y agoSo, should I not care about that so much, and write programs without free()'ing allocated memory? If OSes do that, why not standardize that in C?
- deleted 7y ago[deleted]
- smlckz 7y agoanother proposal: _If, _Ifdef, _Ifndef inside function macros for example: #ifdef SOME_CONST #define WHATEVER(w, h, a, t, e, v, e, r) \ ... common part ... \ ... for SOME_CONST ... \ ... common part continued ... #else #define WHATEVER(w, h, a, t, e, v, e, r) \ ... common part ... \ ... when SOME_CONST not defined ... \ ... common part continued ... #endif With _Ifdef, the above could be written like: #define WHATEVER(w, h, a, t, e, v, e, r) \ ... common part ... \ _Ifdef(SOME_CONST, \ (... for SOME_CONST ...) , \ (... when SOME_CONST is not defined ...) ) \ ... common part continued ... With these, one could also do: #define FACTORIAL(n) _If(n == 0, 1, (n) * FACTORIAL(n)) int f = FACTORIAL(6); turns into: int f = (6) * (5) * (4) * (3) * (2) * (1) * 1; That would be very useful, I think. It might help with code duplication in function macros. Maybe _Switch/_Case thereafter.
- clktmr 7y agoWhy not write is like this: #ifdef SOME_CONST #define HAS_SOME_CONST \ ... for SOME_CONST ... #else #define HAS_SOME_CONST \ ... when SOME_CONST not defined ... #endif #define WHATEVER(w, h, a, t, e, v, e, r) \ ... common part ... \ ... HAS_SOME_CONST ... \ ... common part continued ...
- thesmileyone 7y agoWhat did you think of the Stuxnet code from your perspective? Was it clear who made it from the start, and what it's purpose was? (Iran or China vs India?). Thanks.
- pakwlau 7y agoWhat do you think about Web Assembly?
- troukistan 7y agoIs there a way to append/extend a MACRO value ? For example, I have a arbitrary number of includes, each of them declare a struct that need to be listed later on. #define MOD_LIST // start with an empty list #include "mod/a.c" // MOD_LIST is: a, #include "mod/b.c" // MOD_LIST is: a,b, Module modules[] = { MOD_LIST }
- 7532yahoogmail 7y agoA ton of comments here talk about arrays and basic preconditions. See frama-c.com. even in c++ where encapsulation helps class/function contracts and unit testing is a must
- bythckr 7y agoHi Team "C", I am a beginner level programmer and C is not one of the languages for which I have even bothers to write a "hello world" for. That is my level. As the people that "runs" C, why do we need C? Forget the legacy systems. With fancy languages like Go, Rust, Elixir, Python and the millions others. Of course, the "offsprings" like C++ & C#. What was the use case that C was designed for (I have read from sources like Wikipedia, would love to hear straight from source)? In 2020, how relevant is C? If someone is going to write a system/application today, why consider C? Do you think, C will be relevant in 5 yrs (I know 1 yr in computing is like 10 yrs for humans)? With all your combined experience in computing over the years and as the members of a team that is guiding a valuable thing like "C". What is your advice/wisdom/thought for us?
- rafaelturk 7y agoSomething in the works for Async & Await?
- kazinator 7y agoHere is a library suggestion: a "m" mode for fopen. "m" is the same as "w", but does not truncate the file. In POSIX terms, it doesn't add O_TRUNC to the flags. There is "r+", of course; but "r+" requires that the file exists already. In POSIX terms, "r+" does not include the O_CREAT flag. fopen("foo", "m") creates the file if it does not exist, and opens it for writing. The stream is positioned at the beginning of the file without truncating it. We can sort of emulate it with fopen("foo", "a"), then fclose, then open with "r+".
- flatfinger 7y agoRather than trying to come up with "compromise aliasing rules", the Standard needs to recognize that different tasks require different features, and allowing all possible optimization opportunities that would be useful for some tasks would make an implementation totally unsuitable for others. I would suggest that the Standard define directives to demand three modes, with the proviso that a compiler may reject code which demands a mode it cannot accommodate: 1. clang/gcc mode, which would be adjusted to match the way clang and gcc actually behave, as well as anything they want to do but their interpretation of the Standard woudln't allow. 2. precise mode, which behaves as though all loads and stores of objects whose address are taken behave according to a precise memory-based abstraction 3. sequence-based mode, which would allow compilers to hoist, defer, consolidate, and eliminate loads and stores in cases where they honor data dependencies that are visible in the code sequence, but would require that compilers recognize visible dependencies which clang and gcc presently ignore, and would also require that the definition of "based on" used by "restrict" recognize that any pointer formed by adding or subtracting an integer from another pointer by recognized as "at least potentially based on" the former, even in corner cases where clang and gcc would ignore that. Recognizing mode #1 would avoid allow clang and gcc to keep using their aliasing logic with programs that can tolerate it. Mode #2 would ensure that all programs that have trouble with that logic could have defined behavior by adding a directive demanding it. Mode #3 would allow most of the same useful optimizations as mode #1, but work with a wide range of programs that would presently require `-fno-strict-aliasing`. If one recognizes the need for different modes, the effort required to describe all three modes would be tractable, compared to the obviously-intractable problem of reaching consensus about how one mode that would need to serve all purposes.
- dang 5y agoAll: this thread has almost 1000 comments and is paginated, so to see all of it you need to click More at the bottom of the page, or like this: https://news.ycombinator.com/item?id=22865357&p=2 https://news.ycombinator.com/item?id=22865357&p=2 https://news.ycombinator.com/item?id=22865357&p=3 https://news.ycombinator.com/item?id=22865357&p=3 https://news.ycombinator.com/item?id=22865357&p=4 https://news.ycombinator.com/item?id=22865357&p=4 (Posts like this will go away once we turn off pagination.)