7 ms·
GCC 13 Supports New C2x Features, Including Nullptr, Enhanced Enumerations
- jwilk 3y agoRelated: https://news.ycombinator.com/item?id=35813821 https://news.ycombinator.com/item?id=35813821 ("New C features in GCC 13", 11 days ago, >260 comments)
- zabzonk 3y agonullptr is since c++11 https://en.cppreference.com/w/cpp/language/nullptr https://en.cppreference.com/w/cpp/language/nullptr sorry - thought the post was re c++ - my bad
- mananaysiempre 3y agoIn C++. C only copied it in C23 (not yet ratified).
- zabzonk 3y agosorry, misread the post
- cjensen 3y agonullptr has been such a Godsend for C++. Good to see it coming to C. If you ever see the macro NULL in code, be afraid. There are two valid ways of defining the macro and that cause weird issues when porting code. For example, in the statement printf ("%p %s\n", NULL, "Hello world!"), one of the definitions leads to NULL being interpreted as the null pointer, and the other leads to NULL being interpreted as an integer. The latter may crash if integer and pointer are different sizes. It also causes problems with C++ overloading if one overload takes a pointer and another takes an integer.
- LordShredda 3y agoBut does C need a nullptr keyword? If you're programming in C, you usually define 0 as an invalid value, or a null value. C doesn't have the insane type system C++ has and doesn't have a very strong need to make a distinction between a pointer or an integer, since they're all in the end numbers. The printf example you gave is an example of garbage in, garbage out. If NULL is a macro not defined as a pointer sized integer, then you're at fault here.
- LegionMammal978 3y agoWell, the fault depends on who "you" are: the NULL macro generally comes from one's libc, and allegedly some libc maintainers have been very obstinately against changing their NULL macros to have pointer type.
- throwway120385 3y agoAren't there platforms where pointers have additional type or space information encoded that is orthogonal to the numeric address? It's only by convention that NULL == 0 because on platforms like Intel & ARM you would typically not use the first page. But that's only a convention, and you could just as easily put a null page at the top of your address space, especially in systems with an MMU where mappings can be added, removed, or remapped as-needed.
- LegionMammal978 3y agoIn C, the integer 0 is explicitly defined to convert to a null pointer for all assignments, casts, comparisons, etc., regardless of what the pointer's "actual" value is. The only time where you can see that a null pointer doesn't have numeric value 0 is when you manipulate its object representation with memset, memcpy, etc. The compiler is also at liberty to return whatever it wants when you convert a null pointer to an integer, except that converting it back must produce a null pointer (if it's at least as wide as intptr_t).
- mananaysiempre 3y ago> It's only by convention that NULL == 0 [...] and you could just as easily put a null page at the top of your address space [...]. Technically NULL == 0 always because the standard special-cases zero-valued integer constant expressions; (uintptr_t)NULL == 0 or NULL == *(void **)calloc(1, sizeof(void *)) is another matter :) Language lawyering aside, a non-all-zeroes representation of NULL will probably blow up most C programs [e.g. static-storage-duration initialization is now not the same as calloc or memset(,0,) and is even type-specific]. Like CHAR_BIT, that’s a joint that technically exists but has been rusted for decades (pun not intended).
- josefx 3y ago> The latter may crash if integer and pointer are different sizes. Apparently some compilers specified a special __null extension to handle that case before nullptr was a thing.
- kazinator 3y agoSince NULL expands to an implementation-defined null pointer constant, it is valid for those implementations to go as far as #define NULL __null.
- kazinator 3y agoThe problems are that: - NULL is idiomatic: using NULL is entrenched in C programming and it is not going away. - In spite of nullptr existing now, NULL is still (quite stupidly) not required to just expand to nullptr, but to an implementation-defined null pointer constant, rather than #define NULL nullptr. (According to the N2596 draft). - They had over 30 years to tighten the requirements on how NULL can be defined; what's the matter? C99 could already have required NULL to be ((void *) X) where X is an integer-typed constant expression evaluating to zero. I'm not going to start using nullptr. It's not idiomatic C. I'm going to hold out hope that NULL will be fixed so that it expands to nullptr. -- Also, it's possible for a compiler to diagnose when a constant, zero-valued expression is used as the argument of a variadic function. The diagnostic can be confined to cases when such a constant expression is the result of macro expansion: printf_like_function("fmt ...", ... 0, ...); // OK #define FOO 0 printf_like_function("fmt ...", ... FOO, ...); // compiler diagnostic printf_like_function("fmt ...", ... (int) FOO, ...); // OK
- bigbillheck 3y ago> NULL is idiomatic It is today, but idioms are a human concept and who knows how things will be in 2033?
- kllrnohj 3y agoWell hopefully at some point we'll stop writing C at all
- bigbillheck 3y agoInshallah some day, but I don't see it happening in what's left of my career.
- pjmlp 3y agoOnce upon a time K&R C function declarations were idiomatic, in C23 they are out.
- cogman10 3y ago
- ori_b 3y ago> If you ever see the macro NULL in code, be afraid. There are two valid ways of defining the macro Not on a Posix system, where the only valid definition of it is `(void*)0`. C could have adopted this definition. Nullptr is needed in C++ because `0` is the only definition of `NULL` that works with the type system, due to the lack of implicit `void*` conversions. C doesn't have this problem. Adopting the Posix definition of NULL in the standard would have been sufficient -- and unlike `nullptr`, would have solved bugs in existing programs.
- blackpill0w 3y ago>C doesn't have this problem I don't think a strong type system is a `problem`, implicit conversions can lead to so many annoying and hard to find bugs.
- ori_b 3y agoThat's a fine general sentiment. However, in this context it's a problem if you want to assign NULL to a pointer without a cast, which is why C++ added the magically convertible nullptr in addition to the magically convertible `0` constant. char *x = 0; // ok in C and C++ char *y = (void*)0; // ok in C, error in C++ char *z = nullptr; // ok in C++ therefore: #define NULL ((void*)0) // Required by Posix C, invalid C++ #define NULL 0 // Pre-nullptr, the only valid C++ definition C++ can't define NULL the safe way that Posix C does. I don't understand why it's more acceptable to allow magic `0` conversions than magic `(void*)0` conversions, given that the latter is far less likely to happen by accident -- but here we are.
- rightbyte 3y ago> I don't understand why it's more acceptable to allow magic `0` conversions than magic `(void*)0` conversions In the end you don't have to chose between '0' and 'nullptr' anyways. char *x = (decltype (nullptr)) 0;
- kzrdude 3y agoCase in point, integer arithmetic in C. Reasoning about types there is just tiring.
- cryptonector 3y ago> This proposal also recommends adoption of Unicode normalization form C (NFC) for identifiers to ensure that when compared, identifiers intended to be the same will compare as equal. Legacy encodings are generally naturally in NFC when converted to Unicode. Most tools will, by default, produce NFC tex. Er, a much better approach is to allow unnormalized Unicode in source code and use form-insensitive matching of symbol names so that all forms of a symbol are equivalent. This can be done by normalizing during the parse, or by implementing form-insensitive string comparison and hashing functions that normalize glyph by glyph as needed -- the latter can be very fast for all-ASCII and mostly-ASCII symbols! The reason this is a better way is that there's too many places that don't produce NFC. For example, HFS+ uses NFD, so if you cut-n-paste a file name from HFS+ into other contexts, you'll be pasting NFD unless the cut-n-paste system normalizes to NFC. Also, while it's true that input modes typically produce NFC, it's more that they produce NFC for a small subset of Unicode, not that they will normalize other forms seen on input. Using form-insensitive string comparison/hashing/matching yields a better user experience at not that much implementation cost: you're gonna need a Unicode library, and that library will need to have normalization support, so you can implement form-insensitivity.
- wahern 3y ago> Er, a much better approach is to allow unnormalized Unicode in source code and use form-insensitive matching of symbol names so that all forms of a symbol are equivalent. Linkers will often be blissfully unaware of Unicode or any form of localization. This was the impetus for UTF-8, so that the bulk of software which is 8-bit clean or which operates on opaque, NUL-terminated strings can continue working as-is. This can't be changed without breaking backwards ABI compatibility; therefore, it's very unlikely to change. There are countless half-measures that could be taken, but few if any are suitable for standardization. If the history of software localization is any guide, in the face of strict, forward-looking specifications various vendors and ecosystems will likely go there own way, with the one sure thing being a failure to fully adopt or properly implement the specification.
- cryptonector 3y agoYes, the compiler should normalize symbols before writing object files, no doubt. I'm talking about the inputs though -the source files- which should not have to be normalized.
- twic 3y agoWho is the audience for new features in C? And who is driving stuff through the standardisation process? Is this stuff likely to make its way through to embedded toolchains? Or is this for people who are maintaining existing codebases?
- hgs3 3y ago> Who is the audience for new features in C? Folks like myself who use C to write system software. > Is this stuff likely to make its way through to embedded toolchains? Embedded toolchains based on GCC or Clang will presumably see these features one day.
- quesomaster9000 3y agoThe early adopters are usually transpilers (or code generators) which can quickly take advantage of new features without the effort of rewriting an entire codebase. In the same way that Rust used underlying `const` attributes in LLVM (and found all the weird edge cases), and Nim used C as an intermediate as have many other lisp or object-ish languages.
- nitrix 3y agoChanges to the Standard usually happens as a result of defect reports (confusing details that implementation writers want clarity on) or vast enough general adoption (unifying how implementations were differently achieving the same thing). You can read #13 of the Charter https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2086.htm https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2086.htm As for the audience, it's all the C developers, the open-source and commercial compiler implementations, vendors of libraries, tooling, services, learning material and everything else built in C; which is just innumerable. Each Standard version released supersedes and obsoletes the previous versions. Intentionally, the versions are meant to be as backwards compatible as possible so that one can mix and match C89/C99/C11 codebases with minimum effort. C has gained only a handful of features in the last 40 years. Compared to the great many things that are improved w.r.t. undefined/implementation-specific/unspecified behaviors, or removed to keep up with modern times (e.g. Trigraphs, Two's Complement integer representations, etc). I'd say: (1) upgrading is not the spooky thing people make it out to be. Go, Rust, they all move much faster than this and have very ambitious big design ideas on their mind. (2) It's necessary to take good care of C as it, and the things built in it, will realistically outlive many of us.
- whatever1 3y agoI wonder whether LLMs could help with smarter code optimizations, especially, since they can be context aware.
- Gibbon1 3y agoWe should have a ten year moratorium on optimizations and force the compiler maintainers to work on other things.
- quesomaster9000 3y agoNobody else is admiring typed enumerations? Particularly when using structs this removes a lot of ambiguity if you ignore the indirection to find out the underlying type of the enum (or encode it in the name hungarian style). enum D : uint8_t { A = 0, B = 1, C = 2 } typedef struct { D f; } __attribute__((packed)) E; assert(sizeof(E)==1); etc. could make grokking protocol declarations with enums less onerous and requiring one less level of indirection.
- maccard 3y agoI'm a c++ programmer and finding it hard to be excited about things we added to the language 12 years ago.
- quesomaster9000 3y agoAs a D programmer, why haven't you caught up yet?
- loeg 3y agoAs a sneering C++ programmer, why are you even reading / commenting on a new C standard? This is basically a "if you don't have anything nice to say, don't say it" situation.
- tom_ 3y agoThe same goes for C programmers with a chip on their shoulder! There is a downvote button.
- anonymousDan 3y agoAre there any good resources on writing compiler optimization/instrumentation passes in gcc (as opposed to LLVM)?
- xenadu02 3y agoOfficially adopting __auto_type as auto is good. Unfortunate that N2953 dropped function return type and parameters. This feature composes with _Generic macros quite well: #define div(X,Y) _Generic((X)+(Y), int: div, long: ldiv, long long: lldiv) ((X), (Y)) auto res = div(38484848448, 448484844); auto a = b * res.quot + res.rem; It also lets you get rid of all the "typeof(X)" foo in macro definitions.
- typon 3y agoTwo uncontroversially useful C++ features (nullptr, typed enums) entering C is a great thing. I really wish C++ had Rust style enums. Having to implement them with flags in C++ is a bit of a chore.
- deleted 3y ago[deleted]
- xenadu02 3y agoFor those who are wondering about lambdas and defer those were tabled to the next standard revision but not rejected. Lambda: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2892.pdf https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2892.pdf Defer: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2895.htm https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2895.htm
- torrent 3y agoSad perspective for C programmers who need to wait 10+ years until they get half-backen versions of some useful C++ features.