#[1]Kostya's Boring Codec World » Feed [2]Kostya's Boring Codec World » Comments Feed [3]Kostya's Boring Codec World » Why I still like C and strongly dislike C++ Comments Feed [4]alternate [5]alternate [6]alternate [7]Kostya's Boring Codec World Kostya's Rants around Multimedia __________________________________________________________________ [8]« ZMBV support in NihAV and deflate format fun Why I still like C and strongly dislike C++ This comes up in my conversations surprisingly often so I thought it’s worth to write my thoughts down instead of repeating them again and again. As it is common with C programmers, C was not my first nor my last language, but I still like it and when I have to write programs I do it in C. Meanwhile I try to be aware of modern (and not so modern) programming languages and their trends and write my own multimedia-related hobby project in Rust. So why I have not moved to anything else yet and how C++ comes to all this? Why C is not the best language First, the obvious statement that there is no such thing as “the best programming language”. Each language has its best use case scenarios so while you can write raytracing in Excel, it’s better be done in some other language. So it’s good to know programming language limits and do not complain that web servers are not written in Fortran and hardly any app uses Perl or C++ as internal scripting language. C may be considered not good for the following reasons (beside simply being too old and not fast-developing but that’s a matter of taste). C has syntax that is ambiguous at the times (e.g. * may be a binary multiplication operator, an unary dereference operator, or used to declare a pointer; the fun with typedef deserves a separate essay). It is not safe e.g. out of bounds array access is rather common and there’s no runtime check for that while e.g. Borland Pascal let alone something more modern had it (even if you could turn it off in compilation options for better performance). And the pointers make it even trickier to keep everything in order. Plus some other things like calling a function without a prototype declared so you can easily pass a wrong type of argument to it. Rather limited standard library. Some other languages may have even web server (or at least all building blocks for one) out of the box, C standard library lacks even on containers. Why C despite all that The reason why I still like C is that it is a simple language. Simple in a sense that it is easy to express ideas and what to expect from it. For example, if you want to retrieve an array value with two offsets, one of which can be negative, in C you write arr[off1 + off2] while in Rust it would be arr[((off1 as isize) + off2) as usize]. And C-style loop is often shorter than Rust idiomatic way with iterators combined together (of course the former is also allowed in Rust but it’s frowned upon with linter always suggesting to replace it using iterators). Similarly memset() and memmove() are powerful tools. And in most cases you know what will compiler produce—what would be memory representation of the object and how you can reinterpret it differently (I blame C++ for making it harder in newer C standard editions but I’ll talk about it later), what happens on the function calls and such. C is called portable assembly language for a reason, and I like it because of that reason. So to use car analogy, it is like a sports car with manual transmission that gives maximum performance—but you can easily damage transmission or even engine if you mess with clutch and gearbox and of course you can drive off the road if you push gas pedal too hard. Yet more of the engine power goes to the wheels compared to the automatic transmission and you can predict its behaviour and do tricks not possible on other cars (because there you’d have to fight those automated controls). So how C++ is involved here? And moving to C++, I don’t hate it. If you use it and like it, fine. I can’t deny that compared to C it offered two advantages: better program structuring (with namespaces and classes, Simula was good for something after all) and RAII concept (having constructors to initialise object on creation and destructors to clean it up on destruction, to put it oversimplified; if you develop this idea further you can come up with Rust lifetimes). But in the same time it also has two features that make me strongly dislike it. First of all, it’s the holistic nature of the language. If some other programming language has a popular feature, it will end in C++ too. In result you have you have C++ standard being reviewed every couple of years with more features added every time. In result you have a monstrous language that nobody can know in full, with many features being duplicate of the other features. And everybody essentially picks a subset of C++ and writes in it ignoring the existence of other features. Plus there’s no standard way to signal features from which C++ edition you’d want to use. In Rust they have crate-wide edition. In C++ IIRC they wanted to introduce epochs for the same purpose but it didn’t take off. And a fun thought—I encounter news time from time that somebody single-handedly wrote a functional C compiler (and in reasonable time too) but I don’t remember seeing the same news about C++ compiler even once. Another thing is that C++ is not just multiple languages in reality but also it’s a meta-language aka templates. I understand what it is for and agree it’s a better thing than C preprocessor for type-independent code. But in reality it seems to spawn hideous monstrous code including the shift from “header file for declarations, compiled code for the actual functionality” to “header file contains all the code that gets instantiated in the project including it”. I don’t like long compilation times and this approach encourages them. And finally, I could ignore C++ existence had it not been bolted to C and giving a bad influence on it. I’m not talking about C/C++ and “you say C that means you know C++”, I’m talking about the coupling having bad influence on both standards and compilers. On one hand, C++ got a huge boost from being based off C, on the other hand it would probably be better now without most of C legacy (of course it tries to get rid of it by making it obsolete bit by bit but the legacy support is still there). But would e.g. C++24 as a separate language based in C++21 with most of outdated stuff thrown out be as popular? I doubt it. C++ compiler influence on C The related effect is that C gets treated as C++ without some features. The infamous case is Microsoft C-ish compiler that did not bother supporting C99 features until 2015 edition (and even then it still preferred bug-for-bug compatibility because the customers might be shocked to find out that variadic macros finally work there). But the same approach can be seen in both the standard and other compilers, and those are related issues. The principal problem is that both C and C++ standards are written based on the input from compiler developers, and those are mostly C++ developers (and sometimes it feels they know nothing about the real-world programming and think it should just fit their views, but that’s a rant for another day). I do not follow the standard development but I’m pretty sure that the most annoying aspects in C99 and later come from those compiler developers. And those made their considerations for C++ where it makes more sense but it was forced on C as well to make the compilers easier. I’m talking of course about “undefined behaviour” and how compilers treat it. This has become a popular scarecrow (your code relies on two’s complement arithmetic so it has undefined behaviour and the compiler can [DEL: throw :DEL] optimise out the whole block of code!). In my opinion there are four kinds of behaviour that are treated as a big no-no only while half of those deserve this: * Architecture-defined behaviour (i.e. what depends on CPU architecture). That includes mostly arithmetic. For instance, if I know that my target machines use two’s complement arithmetic (yup, no CDC 6600) why the compiler (that is supposed to know target architecture as well) would assume that it should behave otherwise. Because then it can perform some theoretical optimisations better? Hmm… The same applies to bit shifts as well. If I know that on x86 it ignores high bits of shift amount and on ARM negative shift left means shift right why I can’t exploit that fact for my program just for that architecture? Integers having different sizes on different platforms are acceptable after all. Just issue a warning about non-portability and let me continue with it; * Pointer magic and type-punning. This feels forced exclusively for potential compiler optimisations. I agree that memcpy() for overlapping memory regions may not work correctly depending on its implementation (modern x86 implementations start copying from the end) and relative position of the addresses, but the other rules are less reasonable. That includes working with the same memory area using two pointers of different type simultaneously. I can’t imagine why it should not be allowed if not for hindering compiler optimisations (it can’t be an alignment issue). This culminates in impossibility of converting e.g. int to float using a union. Linus [9]ranted on it so I should not repeat the arguments. But to me this feels like something done either for better compiler optimisations or because C++ demands it—because of the type tracking (you don’t want to put one class instance into a union and retrieve it as completely different class difference; it may do something with optimisations as well); * Implementation defined behaviour (here it is not exactly what C standard means by it). My favourite example is function call: depending on calling convention and compiler implementation the function arguments might get evaluated in completely random order, so the result of foo(*ptr++, *ptr++, *ptr++) is undefined and should not be relied upon even if you know the target architecture—what if they’re passed in registers (like on AMD64), the compiler is free to calculate value for whatever register it sees fit. * Completely undefined behaviour. This is also the case where it’s hard to argue with the standard. The most prominent example is violating the rule about changing variable state just once in single statement, like the famous i++ + i++ or even worse *ptr++ = *ptr++ + *ptr++. Since C++ is higher-level language than C (while it has most of the features from C they are discouraged from using, you should use reinterpret_cast<> instead of direct type case and references instead of pointers, etc etc) you’d not expect C++ programmers to understand low-level code as good as C programmers (that’s just a statistical observation, of course it varies for individual people). And yet because of abundance of C++ programmers and C/C++ coupling you often have C compilers extended to support C++ and rewritten in C++ as well to accommodate for the complexity (this has happened to GCC and you have very WTFy GDB with C++ code in .c files). So you need C++ compiler to compile C compiler which is sad (but pure C compilers like LCC, PCC and TCC are still here luckily). Conclusion To summarise it, I like C for its middle-level position where it’s still possible to do low-level things like manipulating memory contents with ease while enjoying the benefits of high-level language (that do not get in your way); and my strong dislike for C++ comes from its design choices (though some claim it was not designed but rather simply happened) and that those design choices affect C standard and compilers making it less the language I like. Well, at least it’s impossible to replace C90 with C90 Special Edition and pretend the original has never existed. This entry was posted on Wednesday, May 26th, 2021 at 11:40 am and is filed under [10]Useless Rants. You can follow any responses to this entry through the [11]RSS 2.0 feed. You can [12]leave a response, or [13]trackback from your own site. 10 Responses to “Why I still like C and strongly dislike C++” 1. [14]mee says: [15]May 26, 2021 at 7:15 pm Ah, what about D? 2. [16]Kostya says: [17]May 27, 2021 at 12:09 am That is an interesting language that (IIRC) lost its chance because of the compiler availability. I don’t have much to say about it except that now there are other languages trying to fit the same niche. As for me, they all have a right to exist. 3. Peter says: [18]May 27, 2021 at 12:19 am Agree. Why no mention of Baidu’s new language? 4. Matthew Fernandez says: [19]May 27, 2021 at 12:36 am FWIW some of the problems you refer to have been addressed by recent standards. C++20 mandates two’s complement integers. And type punning through a union is no longer UB as of C99. 5. [20]Kostya says: [21]May 27, 2021 at 12:41 am @Peter It does not affect C even if it came from Plan9 version of C. And I don’t know what to say about it beside that defer is a nice concept. 6. [22]Kostya says: [23]May 27, 2021 at 12:53 am @Matthew From what I can find, type punning is UB exactly in C99 (not before and not after). And in this post I wonder more about how they became problems in the first place. 7. Joseph E Dante says: [24]May 27, 2021 at 12:56 am C was the slayer of many pop languages of the 80s like PL/1, Basic, Cobol, Pascal but eventually succumbed to the concepts of Objects in the form of C++. I think many of us by the 90s had our own libraries for data isolation, link list, and memory control and didn’t need fancy pants languages like Java or C++. I still use my old libraries to crank out very powerful programs in a few lines of code that compile and run extremely fast. Unfortunately, many programmers I worked with were Basic (pun intended) programmers who need to be somewhere and did have time to write very clean code, so Java was born. Java solved the memory leak problem, link lists, and data isolation so junky programmers were less junky. Unfortunately again, compiler writers needed to junk up another language and we have modern-day Java. I’m not a language guy like the author of this article, I just need to get stuff done easily and quickly and C is my best friend always. Thanks, Ritchie. 8. [25]Kostya says: [26]May 27, 2021 at 1:21 am I disagree that most of the listed languages died because of C. PL/1 was C++ of its time with the C++ problems (too many languages to chose from, too hard to write a decent compiler, maybe it’s the hardware limitations that allow LLVM to prosper now prevented us from having too complex compilers back in the day). BASIC was popular in the 1980s and enjoyed its popularity in form of Visual Basic and then Visual Basic for Apps until it was replaced by VBA2 aka Python. COBOL has never been popular with the major crowd and it’s still in use in its niche and it’s not going away from it. Pascal was intended to be an educational language (like BASIC) so while it enjoyed popularity as a systems language because of MacOS and Borland, it was still limited for larger tasks. Why Delphi didn’t keep its popularity is another question. As for more modern languages, Java was a product of the time—and the time demanded a safe language for less educated programmers because salaries are high and hardware became cheaper. And what do we have now for popular languages? Mostly something suitable for coders who can search what library to use in their product. As I briefly mentioned in the post, C++ seems to move in the same direction. Also I’m not a language guy myself, I just prefer to be aware of more than one language. Fun fact: back in university out data structures course was in C but one of the lectures was about Lisp and its “everything is a list” approach. You can program better if you know the different approaches to solving a problem. 9. Zyx says: [27]May 27, 2021 at 9:22 am Nice sum-up, the C/C++ conflation has definitely harmed C. Any words on Clang compiler? COBOL has never disappeared indeed. Niche – and seemingly ill-designed – as it is, i wanna learn it. Too bad i don’t have a mainframe in the basement. 10. [28]Kostya says: [29]May 27, 2021 at 9:38 am Clang seems to be a side project for LLVM which was written in C++ right from the start. So the same problems with C++ mindset apply there as well. As for COBOL, I think you can find a compiler for something non-IBMy too. Or some zOS emulator hopefully. I understand why COBOL was designed as it is (and why it still makes sense to learn it for a retiring programmer). Leave a Reply [30]Click here to cancel reply. ______________________ Name (required) ______________________ Mail (will not be published) (required) ______________________ Website __________________________________________________________ __________________________________________________________ __________________________________________________________ __________________________________________________________ __________________________________________________________ __________________________________________________________ __________________________________________________________ __________________________________________________________ __________________________________________________________ __________________________________________________________ Submit Comment Currently you have JavaScript disabled. In order to post comments, please make sure JavaScript and Cookies are enabled, and reload the page. [31]Click here for instructions on how to enable JavaScript in your browser. __________________________________________________________________ Kostya's Boring Codec World is proudly powered by [32]WordPress [33]Entries (RSS) and [34]Comments (RSS). References 1. https://codecs.multimedia.cx/feed/ 2. https://codecs.multimedia.cx/comments/feed/ 3. https://codecs.multimedia.cx/2021/05/why-i-still-like-c-and-strongly-dislike-cpp/feed/ 4. https://codecs.multimedia.cx/wp-json/wp/v2/posts/2177 5. https://codecs.multimedia.cx/wp-json/oembed/1.0/embed?url=https://codecs.multimedia.cx/2021/05/why-i-still-like-c-and-strongly-dislike-cpp/ 6. https://codecs.multimedia.cx/wp-json/oembed/1.0/embed?url=https://codecs.multimedia.cx/2021/05/why-i-still-like-c-and-strongly-dislike-cpp/&format=xml 7. https://codecs.multimedia.cx/ 8. https://codecs.multimedia.cx/2021/05/zmbv-support-in-nihav-and-deflate-format-fun/ 9. https://lkml.org/lkml/2018/6/5/769 10. https://codecs.multimedia.cx/category/useless-rants/ 11. https://codecs.multimedia.cx/2021/05/why-i-still-like-c-and-strongly-dislike-cpp/feed/ 12. https://codecs.multimedia.cx/2021/05/why-i-still-like-c-and-strongly-dislike-cpp/#respond 13. https://codecs.multimedia.cx/2021/05/why-i-still-like-c-and-strongly-dislike-cpp/trackback/ 14. http://no/ 15. https://codecs.multimedia.cx/2021/05/why-i-still-like-c-and-strongly-dislike-cpp/#comment-217293 16. https://codecs.multimedia.cx/ 17. https://codecs.multimedia.cx/2021/05/why-i-still-like-c-and-strongly-dislike-cpp/#comment-217294 18. https://codecs.multimedia.cx/2021/05/why-i-still-like-c-and-strongly-dislike-cpp/#comment-217295 19. https://codecs.multimedia.cx/2021/05/why-i-still-like-c-and-strongly-dislike-cpp/#comment-217296 20. https://codecs.multimedia.cx/ 21. https://codecs.multimedia.cx/2021/05/why-i-still-like-c-and-strongly-dislike-cpp/#comment-217297 22. https://codecs.multimedia.cx/ 23. https://codecs.multimedia.cx/2021/05/why-i-still-like-c-and-strongly-dislike-cpp/#comment-217298 24. https://codecs.multimedia.cx/2021/05/why-i-still-like-c-and-strongly-dislike-cpp/#comment-217299 25. https://codecs.multimedia.cx/ 26. https://codecs.multimedia.cx/2021/05/why-i-still-like-c-and-strongly-dislike-cpp/#comment-217300 27. https://codecs.multimedia.cx/2021/05/why-i-still-like-c-and-strongly-dislike-cpp/#comment-217301 28. https://codecs.multimedia.cx/ 29. https://codecs.multimedia.cx/2021/05/why-i-still-like-c-and-strongly-dislike-cpp/#comment-217304 30. https://codecs.multimedia.cx/2021/05/why-i-still-like-c-and-strongly-dislike-cpp/#respond 31. http://enable-javascript.com/ 32. http://wordpress.org/ 33. https://codecs.multimedia.cx/feed/ 34. https://codecs.multimedia.cx/comments/feed/