9 ms·
C is the glue interface that connects all the different languages together. I wouldn't want to see anything new added to the language that complicates this ling
by kstenerud 5y ago
C is the glue interface that connects all the different languages together. I wouldn't want to see anything new added to the language that complicates this lingua franca.
I liked C in the 80s, 90s and 2000s. It was a neat and simple language, but that changed as compilers got more aggressive with their optimizations and exposed just how complicated and unintuitive the spec actually is (and the impossibility of avoiding UB). C was a good learning experience for language committees (as was C++), but it's time to cut our losses and move on.
I also liked C++ in the 90s, but soon grew to despise it. When they tried to revamp it and make it safer to use, I was hopeful, but that's now gone. It's too complicated, the error messaging sucks, and there are too many different ways to do the same thing (with ever changing best practices). In a way, CMake and C++ are two peas in a pod.
This is why I now pin my hopes on rust and zig. I want to write low level code, but not in C or C++. I want a build system that's not Makefiles, CMake, or (shudder) gradle.
- kajaktum 5y agoWhat makes you think Rust and Zig will not suffer the same issue given enough time?
- kstenerud 5y agoThere's absolutely no guarantee that these problems will be avoided in rust and zig; we only have the benefit of hindsight to avoid the problems we have now, and a recorded history of the kinds of things that tend to go wrong in committees (factions, infighting, BigCo interference, intrigue, egos, bike shedding, etc).
- jackosdev 5y agoThe Zig creator is very conscious of this, talks a lot about rejecting many proposals and ideas to keep the language simple, not being an ass-hole about it, just to avoid what happened to C++.
- Someone 5y agoAnd then the question is whether it will grow fast enough, or get overshadowed by a language that’s a bit more like a weed, growing fast in whatever direction it can, and whether it will then die because of lack of sunlight. It’s tricky to balance features, backward compatibility and ‘cleanliness’ in a (language, standard library)
- kristoff_it 5y agoYou can come up with your own answer to that question by taking a look at how the Zig project is run. https://kristoff.it/blog/interfacing-with-zig/ https://kristoff.it/blog/interfacing-with-zig/ https://ziglang.org/zsf/ https://ziglang.org/zsf/ https://ziglang.org/news/financials-update/ https://ziglang.org/news/financials-update/
- kbob 5y agoComputer science is less than a century old. There's no reason to think we know enough to design perfect languages yet. But with an additional 30 years of hindsight, we can make somewhat better languages now, and we should.
- pjmlp 5y agoWe already had 20 years of hinsight that C's authors decided to ignore, had UNIX not been free beer for all practical purposes, history would have taken another path regarding C's adoption.
- Koshkin 5y agoYeah but the thought of living in a world where they use Ada++, AdaVM, and AdaScript makes me shudder...
- pjmlp 5y agoIt would have sufficed that the language had proper bounds checking, string and array types (that doesn't preclude pointers to everywhere on the universe), strong namespaced enumerations, required &array[0] instead of pointer decay, proper sized allocation. All lessons from what was being done from JOVIAL, ESPOL, NEWP, PL/I various offsprings, during the 20 years that preceded C.
- galangalalgol 5y agoIndeed, and rust, zig, fortran, and julia don't have the problems with c that c++ does, so is it a problem with c or with c++ that the author is actually talking about?
- omgmajk 5y agoHonestly, this is a C++ problem and the article should be named "The Problem with C++". Like you said, other languages do not have these problems to the same extent.
- kstenerud 5y agoThe biggest problem is that there is still a significant faction within the C++ committee that wants closer relations between C and C++, or even a merging (if such a thing were possible). "C++ is a better C" is a mantra that can still be heard to this day within those hallowed halls. If C++ would just treat C as an interface like everyone else does, this problem would shrink considerably.
- loup-vaillant 5y agoIf C++ had just treated C from the start, it would have been much cleaner, and nobody would have used it. Humans are stupid, short-sighted creatures, and programmers are no exception. The only way to get C programmers to use C++ was to make C-with-classes a drop-in replacement for C. Replace "cc" by "CC" in your build system, and you magically get new features, without breaking old code (at least not too much). Sure it crippled C++ from the start. If C++ had stopped at binary compatibility (either with an FFI like Rust or Zig, or by deciding on a subset that can talk to C interfaces), it would have forced users to use two compilers, as well as learn an entire new language. Few people would have been willing to put in the work, Stroustrup knew this, and he wanted his language to be useful now. And now we have this mess.
- pjmlp 5y agoThe best way to put it for modern generations is that C++ was "TypeScript" for C, with all the plus and minus that it entails.
- unwind 5y agoDo you have a concrete example of some operation where avoiding undefined behavior is impossible?
- kstenerud 5y agoNot offhand, no. It's been more than 5 years since I last did any serious C dev work. But for an entertaining read, there are some fun stories floating around about Linux vs GCC with the kernel devs resisting compiler optimisations, and even holding back the "supported compiler versions" over it :)
- tsimionescu 5y agoIt's not a particular operation that is the problem, it's writing a whole real-life program with no UB that is the problem. Even so, one example in C++ where it's almost impossible to avoid UB is treating a piece of memory as both a struct and raw bytes with guarantees of no copying. This comes up a lot in network packet processing.
- unwind 5y agoRight, yeah I can see how the "no copying" requirement is a tough one. Thanks.
- kstenerud 5y agoThis makes me wonder how protobufs manages to implement zero-copy structs.
- tsimionescu 5y agoWell, in practice memcpy and std::bit_cast will not normally copy, if you're careful with how you use the variables and so on, so it's not completely impossible to do this. There are also compilers (g++ for example, if I understand correctly) that define type punning through unions to work like in C (allowing you to read and write through different members of the union, which the C++ standard prohibits).
- 5y ago
- mjevans 5y agoI'm still a proponent of C as portable assembly, and any sort of optimizations / UB that gets used resulting in warning messages that can improve the source code of the program rather than the one time artifacts the compiler produces.
- _0w8t 5y agoC cannot express quite a few useful things that assembly can. Things like tail calls, stack management, non-flat address space just cannot be expressed.
- foxfluff 5y agoI'm curious, are you working on such a C compiler? For the two decades I've used C, I've not had a compiler that resembles "portable assembly." The unoptimized code they generate is extremely naive and far removed from anything an assembly programmer would write, easily resulting in many times more instructions than a simple & straightforward assembly implementation. As one might expect, the performance of such code is atrocious. With gcc and clang, optimizations are absolutely mandatory if you want compilers to generate anything resembling good assembly. And it is still an uphill fight to avoid silly code. Just last week I scratched my head because gcc insisted on recreating a constant that is already there in a register, in that very same register it is recreating it in [1]. You could force it to keep the value in a register by creating a top level variable and use the asm("register") extension, but that just resulted in gcc making copies of that value into other registers. Also worth pointing out that there's a lot of stuff in assembly that you cannot express in C directly. You want a rotate instead of two shifts and OR? You absolutely have to have an optimizing compiler, because rotate does not exist in C. Want to shift and test carry? No, that is not possible in C. Compiler extensions give you access to some things (e.g. popcnt) but the vast majority of assembly is only achievable indirectly by assuming the compiler can optimize your code and figure out what instruction you want. Also those extensions hardly make it portable.. I also think the vast majority of C code I see looks very different from assembly; it is written under the assumption of an optimizing compiler, which converts idiomatic C to somewhat idiomatic assembly. [1] http://fpaste.dy.fi/bRq/disp http://fpaste.dy.fi/bRq/disp
- my123 5y ago> C is the glue interface that connects all the different languages together. That's one of the issues in most UNIX systems. Windows sidestepped it with COM (and a much improved WinRT as a successor, with a .NET-y object model). On Apple systems, Obj-C is pretty much usable from other languages too, being the standard ABI to glue it all. My takeaway: bring one of those two options properly to Linux, which is needed hard by now, to not fall to the lowest-common denominator. (C++ isn't a solution because of a dubiously stable ABI on quite some platforms)
- pjmlp 5y agoYes, people mistake OS ABI with C, not understanding that is only a reality on pure C OSes. You forgot mainframes or even Android (C ABI without JNI is of not much help), or ChromeOS (WASM yeah). Linux has such an option, D-BUS, now adopting it at scale is another matter.
- badsectoracula 5y agoD-Bus is for IPC not an ABI. If there was something similar it'd be gobject, but i don't think any language other than Vala speaks it "natively" (and considering how much Gtk cares about backwards binary compatibility, i don't think it'd be a good idea to target it anyway).
- pjmlp 5y agoIt can run in-proc and fits the scenarios being given on previous comment. I remeber Bonobo, DCOP and KPart days, so I know pretty well what D-Bus is capable of. In micro-kernels the IPC infrastructure is the userspace ABI, as it is the only way to call into OS services, beyond the little glue library to make it possible to do so.
- marwis 5y agoWhere did you see in-proc D-Bus? It would be wildly inefficient compared to COM/gobject anyway.
- sirwhinesalot 5y ago> C is the glue interface that connects all the different languages together. I wouldn't want to see anything new added to the language that complicates this lingua franca. Indeed, this is one of the two things where C is still king, the other being running on weird hardware with specialized compilers. That said, C is not a great glue language: - Zero terminated strings are only used in C so every other language needs to do a copy to pass a string to C, even C++ (for string_view at least). - A lack of fat pointers means that buffers need to pass their pointer and length separately, which is awkward, or use a custom struct which other languages will know nothing about. - It has no standardized error handling mechanism to help with writing automatic wrappers on the other language endpoints. - It has no modules or namespacing. So while C will continue to be the glue language of the programming world, I wish it was just a bit better than what it is, would make language interoperability a lot nicer...
- _the_inflator 5y agoI agree with you. However, I think the real value of the language is that, despite flaws, it provides a reasonably consistent platform in this "glue" context. It better to have one imperfect language, than a dozen perfect.
- sirwhinesalot 5y agoI know "upvote" comments are frowned upon, but I just wanted to say I most certainly agree. I'm glad we ended up with such a language, even with all its flaws.
- pornel 5y agoI think it would be beneficial to create a better interoperable ABI description (one, not a dozen). Not in a form of a language header, but a data file that can be easily consumed by tools of any non-C language. 1. C headers are exceptionally annoying to correctly parse and interpret. You basically have to have a full C compiler, which is a PITA for a non-C tool. It's not just complexity of the C syntax, but dependency on system headers, implicit platform-specific type sizes and struct layouts, and an arbitrary web of ifdefs which may need to be generated by an arbitrary build system. Everything here resists automation, and if you get any details wrong, you won't know until you see memory corruption. 2. The common baseline between most programming languages has outgrown what C can express. Namespaces and other name mangling, unwinding, non-nullable types, slices, ownership/destructors, thread-safety annotations, etc. C++ has some of these features, but it solves none of the above problems, and only adds more complexity and its own compiler-specific behaviors.
- jvanderbot 5y agoI'm hopeful for Rust. I'm a C++ developer. I use Python all the time as well when I want something to just work, and fast. But by god I love C. I use C for most of my library interfaces so that I can easily make C++, Python, etc versions in more pleasing versions for those languages. It's much, much easier to work from C and to another language than it is to cross language boundaries laterally. That probably won't change, so I'll always use C at least a little bit when building tools. In that respect, C is still winning. It's upstream of everything, easy to compile, and has libraries for everything.