11 ms·
Principles for C programming
- borplk 10y agoAll sounds good in theory but in practice in a large enough project many of the suggestions are not practical. Recently I was looking at rsyslog's source code. Look at this "simple" file for example, https://github.com/rsyslog/rsyslog/blob/master/plugins/omstdout/omstdout.c https://github.com/rsyslog/rsyslog/blob/master/plugins/omstd... It's an output module for rsyslog that logs to stdout. I wanted to gouge my eyes out.
- Sir_Cmpwn 10y agoThis code fails to follow many of my suggestions. - Liberal use of macros - Horribly unreadable coding style - Needless use of compiler extensions - Very poorly organized code This is awful code because the authors are morons, not because the language is bad. They could stand to read this blog post.
- borplk 10y agoI'd say that's a bit naive. How would you go about writing something like rsyslog without doing the things they have done? How would you create rsyslog's flexible (I'm not saying it's "good") module system where people can write their own pluggable custom input/output modules? Your comment somehow suggests that it's possible to achieve everything they have achieved in terms of functionality while doing it in a much much better way that they just don't know about. If people writing rsyslog aren't good enough to do it then 99% of other people aren't either. So let's not blame people, it's the weakness of the language.
- Sir_Cmpwn 10y agoAre you serious? You could start by fixing that godawful code style and removing the macros. You could change these variable names and function names to make more sense (CHKiRet? omsdRegCFSLineHdlr? What the hell?). The compiler extensions are unnecessary and can just be removed. None of these changes have any impact on the functionality of rsyslog.
- brogrammer2 10y agoCool down a bit, would you? You could get your point across without using that tone.
- borplk 10y agoMaybe you are not too familiar with rsyslog. Those are modules that get compiled into rsyslog itself. If you attempted to create such a module system you will very soon see that doing a lot of the things that they have done is unavoidable (weird naming and so on aside). I see this attitude where people suggest that writing beautiful secure wonderful C code is possible however just somehow all people are just too dumb to be able to do it. Every example you show them they say "nah, that person? also too dumb". You can find similar crap like that example that I pasted in all popular C projects including the Linux kernel and Redis. At some point does something become not fit for purpose? I'd say we'd make more progress if we become less tolerant of technologies that disrespect us as humans. If only an elite subset of people are good enough to program in C. I'd say that's because C is not good enough, not because everyone else is too bad for C.
- Sir_Cmpwn 10y agoHave I said anything that implies the module system is bad here? None of the guidelines in my article nor my comments here have anything to say about their module system. You could easily make this style better, name things better, and expand the macros and it would (1) work exactly the same and (2) be much better code for it.
- birc_a 10y agoI'm not sure which parts of that you are referring to as unavoidable since C can do modules just fine without any mess. Define the functions you want to implement as static functions and add something like this at the bottom of the file: outputmodule_t omstdout = { .name = "omstdout", .description = "blah", .init = prepare_stdout, .do_action = write_to_stdout } #if COMPILING_FOR_RUNTIME_LOADING outputmodule_t *rsyslog_outputmodule = &omstdout; #endif Then either stick `omstdout` in a list of modules known at compile-time or compile separately and use dlopen/dlsym to get the one necessary symbol. No GNUisms, no language extensions, no linker tricks, no macro magic. C has problems but it's not that hard to create readable code in it.
- ktRolster 10y agoI did find this line of code quite entertaining: if((r = write(1, toWrite, len)) != (int) len) { /* 1 is stdout! */ If you're going to go to the effort to add the comment, why not just use stdout instead of 1?
- pcwalton 10y ago> This is awful code because the authors are morons, not because the language is bad. Rainer Gerhards is a researcher who has published in peer-reviewed journals [1]. Can we please end this "people who write code in a style I don't prefer are idiots" meme? [1]: https://www.researchgate.net/profile/Rainer_Gerhards https://www.researchgate.net/profile/Rainer_Gerhards
- Sir_Cmpwn 10y agoIf you don't think this code is awful then we aren't have a meaningful conversation about it. Smart people can write garbage code, too, this is great evidence for it.
- makapuf 10y agoGood researcher and good coder is definitely not always the same (not specifically talking about Mr Gerhards - but this code is UURGH. Redis also has modules). Most of the research code I've seen if definitely not clean code. And needn't be. (Version Control ? what's that ?)
- wruza 10y agoWhile I read this thread I see how people make arguments and present working production solutions, but you often use 'terrible', 'horrible' and 'very' words to value them. Please don't take it as personal attack, but I think these words are purely emotional and should be thrown out of discussion. This is actually a rule for science papers in my country: you throw out all non-technical adjectives and auxiliary words and if text retains its sense, it is approved. If sentences begin to appear unfinished, then these are removed too, because they have no technical meaning. We all love simple things, but many of presented techniques evolved over decades of real non-helloworld development, and not using these leads to programming errors and bloating again. All these people are not stupid — that's not 'look mom, without hands', that's professional experience.
- ianai 10y agoFeels too heavy on "donts." I imagine the motivation the desire to be heard and understood. But I also need something simple, like "keep it simple, stupid" or "first have a working product that anyone could read". Positivity >> negativity.
- dovdovdov 10y agoI guess there are 'donts' because people need help with the keep it simple part, they are quite comfortable with the stupid part.
- ianai 10y ago"nobody's grading your code by how many abstractions and topics from a textbook it employs."
- AstralStorm 10y agoThat said, people sometimes ate grading your code based on performance. Good algorithms often win over simplistic ones.
- makapuf 10y agoI'd say when you have big n, smart algorithms O(n) are better. But most of the time you have small n. better to optimize just the real big N in your program, for what you profiled, than using complex and "optimized" algos when N<1000. (I cannot retrieve the article this was taken from)
- adrianN 10y ago"It's okay for my n!" http://accidentallyquadratic.tumblr.com/ http://accidentallyquadratic.tumblr.com/
- RangerScience 10y agoThink of a circle with a dot at the center. When you define things positively - "do this, do that" - you're saying "get to the center dot, and come from anywhere on the circle". When you define things negatively - "don't do this, don't do that" - you're saying "get to anywhere on the circle, and come from the dot." "Test your code". Your code could be library code, it could be core language features, it could be framework patterns, it could be executable utilities. Ends up all the same - tested code. From anywhere, to somewhere specific. "Don't test controller actions". You can test requests, you can test at a feature level, you can test the models and functions used by the controllers. Ends up all kinds of different - no tested controllers. From somewhere specific, to anywhere. Something telling to do or not do something doesn't mean it's positive or negative; that comes from tone and presentation, not content.
- rumcajz 10y agoOne thing that comes to mind is that young people today are weaned on oo languages and may find it hard to adopt the good old-fashioned non-oo style typical for C. For example, intrusive data structures may seem like an anti-pattern to oo programmers, while they feel perfectly ok for a C programmer. On the contrary, C programmer may find non-intrusive data structures to be an anti-pattern as they require extra memory allocations.
- buserror 10y agoI disagree with quite a few of them. The title should be "Principle for C programming ON UNUX BASED SYSTEMS". C programming is quite a bit wider that this, and some of the typical points here are no-no if you want to write /portable/ C. For example, "Do not use fixed size buffers". It's all very fine, but 1) it can be exploited as well if someone managed to fudge the size you are going to allocate, and 2) on some platform, you don't have/want malloc(). So it's a lot better to have a fixed buffer and check the sizes carefully before copying into it. Another one I dislike (but it's personal preference) is the 'use struct for pointers to structs' -- well, nope, I don't like that, it's unnecessarily heavy. I typedef my structs all the time, and call them something_t, and * something_p. It's easier to rework, rename, search for and it's quicker to type so makes the source code lighter to read. I know it's not popular, and for example the kernel guidelines agree with you, but I don't. As for "no circumstances should you ever use gcc extensions or glibc extensions" well sorry, I also disagree here. I love the 'case X..Y:' syntax for example and it's been around for about a million years. It's not because the C standards prefer adding idiotic syntax instead of useful ones like this that I'm going to stick along and limp when there is a perfectly nice, clear and very readable alternative. Another one I love but can't use are the sub-functions. Now what also would have been a lovely extension if the runtime had been perfected a bit, but it was never 'finished'. Speak of easier code to read when your qsort() callback is listed /just above/ the call to qsort(). Another extension is of course the __builtins that you actually do need on modern systems. Like memory barriers, compare and swaps, ffs, popcount and so on. Of course I can have an explicit function to do it (in the case of the last 2), but that's the sort of things that ought to be in the C library anyway. So I'll use these, thanks. As far as the rest of the article about the process, your code reviewers and so on, in many places and on many projects (open source ones are a case in point) you don't have the freedom/time to do that. The rule is ' do as best as you can' -- and that ought to do it in many cases.
- brogrammer2 10y agoIt's quite common in Embedded programming to use pools of fixed size buffers. Malloc/free work on these pools.
- 10y ago
- nspassov 10y agoThese points may be especially important for C programming, but most of them really apply to programming in any language.
- CapacitorSet 10y ago>Do not use macros. Do not use a typedef to hide a pointer or avoid writing “struct”. Avoid writing complex abstractions. Keep your build system simple and transparent. Don’t use stupid hacky crap just because it’s a cool way of solving the problem. Heh, good luck avoiding the use of macros in sufficiently complex projects - sometimes C just can't use some control structures in an elegant manner without using macros or custom abstractions.
- mbel 10y agoCan you provide an example of control structures that cannot be used in elegant manner without macros? I honestly fail to think of any example. However I generally agree, that macros are pretty much unavoidable. Include guards are implemented using macro constants. It is pretty much the only portable way to force inlining (in some cases this might be necessary). Variadic macros are a easier to create that variadic functions (e.g. wrapper around fprintf for logging). And there is also the '_Generic' thing for people, who can use C11.
- fpoling 10y agoAnother unavoidable use of macros is to convert symbolic names into string literals or to enable warnings for printf wrappers in a portable code. As for include guards one has to look really hard [1] to get a compiler that does not support #pragma once. [1] - https://en.wikipedia.org/wiki/Pragma_once#Portability https://en.wikipedia.org/wiki/Pragma_once#Portability
- huhtenberg 10y ago> Do not use macros. Sir, yes, sir. I will throw away "offsetof" and "container_of" right now, just give me a moment. > Do not use a typedef to hide a pointer or avoid writing “struct” Somewhat agree with the former, but completely disagree with the latter. If there's a single thing that is not right with C is its excessive verbosity in places where none is needed. Not typedef'ing your structs forces you to use extra 7 characters per type mention for no clear benefit. To put it differently - if NOT having "struct" in front of a type name has any effect on readability/maintainability of your code, then there are deeper problems with your coding style that won't be solved by dragging "struct" around.
- hashmal 10y agointeresting points. the maintainability part is freaking important but i guess you truly realize it only when you got bitten by it several times. some other details i don't necessarily agree with, like buffer sizes if you program for embedded devices or if you have real-time constraints.
- infradig 10y agoMeh, skip on this one.
- signa11 10y agothis video: https://www.youtube.com/watch?v=443UNeGrFoM https://www.youtube.com/watch?v=443UNeGrFoM, from a talk by eskil-steenberg titled 'how i program in c' is, imho, pretty good as well.
- cperciva 10y agoAvoid magic. Do not use macros. Disagree. Use magic, especially macros, in ways such that your code becomes easier, not harder, to understand. A few examples from my own code: 1. My "elastic arrays" (https://github.com/Tarsnap/libcperciva/blob/master/datastruct/elasticarray.h https://github.com/Tarsnap/libcperciva/blob/master/datastruc... and .c) allow me to write ELASTICARRAY_DECL(STRLIST, strlist, const char *); and get a data structure STRLIST which contains an arbitrary number of strings and functions strlist_init, strlist_append, strlist_get, strlist_free, etc. for accessing the array. Compared to the non-macro approach of keeping track of the array size and resizing as needed, this makes code vastly simpler. (Of course, this sort of data structure is built into most non-C languages already.) 2. My "magic getopt" (https://github.com/Tarsnap/libcperciva/commit/53d00e5bd0478fcc89bc056d192a476fb89277a4 https://github.com/Tarsnap/libcperciva/commit/53d00e5bd0478f...) allows me to something which looks and behaves just like a standard UNIX getopt loop, except with support for --long options. Yes, the implementation is mildly insane (and needs to work around a bug in clang!), but it allows for code which is vastly simpler than other getopt-with-long-options alternatives. 3. My "cpu features support" framework (https://github.com/Tarsnap/libcperciva/blob/master/cpusupport/cpusupport.h https://github.com/Tarsnap/libcperciva/blob/master/cpusuppor...) makes use of both macros and some tricky edge cases of C object linkage rules, but makes it trivial for me to add support for new CPU features. 4. Soon to be released, the PARSENUM macro (WIP: https://github.com/Tarsnap/libcperciva/blob/parsenum-additions/util/parsenum.h https://github.com/Tarsnap/libcperciva/blob/parsenum-additio...) which allows me to write PARSENUM(&n, "1234"); PARSENUM(&x, "123.456"); PARSENUM(&s, "123", 0, 1000); where the first argument is a pointer to a variable of any integer or floating-point type to which is assigned the numeric value of the string in the second argument; for floating-point values and unsigned integers, the two-argument form range-checks the value against the bounds of the type, while the four-argument form range-checks against the provided bounds. (Basically, this is strtonum on steroids.) In all of these cases, you will never need to understand how these macros work. Instead, you can simply treat them as language extensions which allow you to write cleaner and simpler code.
- Sir_Cmpwn 10y ago>1 I'm conflicted about this one. I choose not to try and emulate generics with macros because adding language features with macros is a terrible idea. On the other hand, I recognize the problem with void*. It's a matter for debate but I definitely fall on the "don't use macros for this" side. >2 This is a case where I would rather write more code than rely on magic. You have to have this awful hacky opaque implementation in exchange for a trivial improvement in ergonimics. No thanks. >3 I mean, just look at this code. Or better yet, have someone else look at it. This is totally unreadable and unmaintainable, all for a marginal ergnomics improvement. >4 Just use strtol or strtof. Do you really run into this that often? All of these are demonstrating exactly the problem I have with a lot of C authors. You build these esoteric systems that use heaps of unmaintainable, unreadable code to provide marginal gains elsewhere.
- golergka 10y agoGreat post, but most of it is relevant for all other languages as well.
- JetSetWilly 10y ago> Use only standard features. Do not assume the platform is Linux I'll decide what platform I am targeting, thank you. I don't feel any obligation to support obscure OSes if I am just targeting linux. I might as well use useful linux-specific and GNU userland features, they are helpful.
- mfukar 10y ago"Do not assume" doesn't really mean or imply "do not target", so stop being defensive. It's good advice.
- ckastner 10y agoTargeting expresses expectations about an environment. "Do not assume" would be contradictory to those explicit expectations.
- mfukar 10y agoAnd since we can follow that thought process, we are smart enough to infer the meaning of the advice given ("do not assume") in the proper context, can we not? It's obvious to me we both can, so why the hell are you wasting our time with useless pedantry?
- ckastner 10y agoWhy are you inferring meaning when the article's author used two paragraphs and numerous examples to illustrate his point unambiguously? The article is clearly heavy on the absolutes (eg: "Under no circumstances should you ever use"), and the grandparent comment critized this, and provided a good counterexample. But you, ironically, chose to assume what the author meant by "do not assume".
- mfukar 10y agoOK, now I know you're trolling.
- Beltiras 10y agoMade me think about the line in Full Metal Jacket: "C is my programming language. There are many like it but this one is mine." https://www.youtube.com/watch?v=nkGIxGdZoYY https://www.youtube.com/watch?v=nkGIxGdZoYY
- jabot 10y ago> GNU is a blight on this Earth, do not let it infect your code. Can someone explain this sentiment to me? I know about licensing and philosophical criticisms, but are there any _technical_ faults?
- pferde 10y agoI think the author meant specifically GNU extensions to various POSIX functions, which can be a pain when trying to run code using them in non-GNU environment.
- jabot 10y agoYes, that is a good point. However I thought that "blight" implies some actual technological inferiority. If there is some, I would like to know more about that.
- mhd 10y agoIt's "All the world's a VAX" in its new form, where you depend on some language/library feature that's actually not in the standard (IIRC alloca and preprocessor extensions are common culprits). And then suddenly you're on a different platform and discover that you can't rely on that -- pretty bad if it's in a central part of your system (like trampolining functions for your toy lisp). On the other hand, you might run into the same issues if the standard support is sub par. People used to declare K&R-style functions for ages after ANSI was passed, and I wouldn't bet a central part of my system on C99.
- jabot 10y agoSo in your opinion the problem is "only" one of portability to non-gnu systems? I thought the author also implied that GNU was technologically inferior and/or problematic. That would interest me...
- mhd 10y agoProbably the ubiquitous "bloat" issue some die-hard C-heads have. But that's his prerogative, I was just pointing out that the specific context points towards portability issues.
- camgunz 10y agoI'll wade in a little. > Don't use macros. > Don't use the inline keyword > Never put code into a header I disagree with these. It's often critical to avoid a function call in hot paths, and if you don't use macros or inline you have to resort to copy/paste, which is error-prone and hampers maintainability. It's also the case that C is a rather inflexible language. Macros can be extraordinarily helpful in reducing boilerplate: in unit testing, for example. I won't argue that macro definitions are the easiest things to read (usually they're OK but they can get pretty arcane), but I do think something that cuts a file down from 8,000 lines to 1,000 is at least worth considering. Macros can also help you maintain type safety. Colin Perciva demonstrated this a little with his elasticarray, but khash is another example of using macros to dynamically create type safe data structures. It can also help the compiler optimize your code. > Don't use fixed-size buffers Everything is a fixed-size buffer until you change its size. If you malloc a buffer of 1024 bytes and read 1025 bytes of user input into it, you overflowed anyway. The principle ought to be "check your bounds", which applies whether your buffer is stack/heap. > Do not use a typedef to hide a pointer or avoid writing “struct”. I'm with you on pointer hiding (looking at you FreeType), but "struct" is just far too verbose. You don't accidentally pass things by value because the compiler will tell you you're passing the wrong type. You won't think it's actually a scalar because you have a grand total of 3 scalars in C (bool/int/float), and if you don't know the types you're working with in your functions you should probably look them up. You probably don't think this is a big issue because you don't adhere to 80 columns in your code (I looked @ your GitHub briefly), but let me tell you you run out of space real quick, and "struct" is practically meaningless. I found a good example: static void set_background(struct wl_client *client, struct wl_resource *resource, struct wl_resource *_output, struct wl_resource *surface) { vs. static void set_background(wl_client *client, wl_resource *resource, wl_resource *_output, wl_resource *surface) { These are obviously not ints, it's a lot easier to read, and it fits in terminals. "struct" is honestly just noise. > GNU is a blight on this Earth Come on now. I hate GNU indentation as much as any reasonable person, but I don't think we need to go this far. --- Unrelated: aerc looks great! I've been thinking about moving off gmail and moving more of my life back into the terminal (I used to be all mutt and IRC and now I'm gmail and hangouts :/ ), and I really like aerc's well-organized code. Nice work.
- keithnz 10y ago1) Learn Compiler Design 2) Write a Compiler for a better language 3) In new language, write a compiler for your new language 4) Retire from C programming, occasionally come to Hacker News to reminisce about C programming and ways to avoid shooting yourself in the foot
- qznc 10y agoFortunately, Walter Bright did that. Now I can simply use his language to retire from C to D. :)
- e19293001 10y agoWriting a compiler in C that can compile it's source code is for me, the best thing to do before retiring from C programming.
- pjmlp 10y agoDid 1, 2 and 4 around 20 years ago.
- zild3d 10y agoor 1) Learn Embedded Design 2) Stay in C for another few decades
- nonsince 10y agoI'm in embedded, but I have a fair measure of autonomy so I've got some Rust code on our device. If nothing else, the cross-compilation story for Rust is absolutely _beautiful_. Just stick the toolchain path in a config file somewhere.
- oleks 10y agoThese principles, at least by name, apply in general, not just to C.
- arkj 10y ago>>Avoid magic. Do not use macros What a put off!!! If you are programming in C in the 21st century then you better know what you are doing. And this whole advice is for dilettantes (no offense). C is no longer a choice language to demonstrate high level programming principles (not that you can't do it but it's not for the lazy), there's a host of other languages that do that better. But if you are interested to reach close to the machine (eg: you program needs a direct view of memory) then C is 'the' choice even today. Look at the kernel list.h [0], it's a beautiful piece of code, and how concisely it uses macros. So the real advice to those starting out in C is to be bold and get immersed in all the things that people say you should not do and then let simplicity emerge. In other words, 'simplicity' of the novice and of the experienced share the same word but are two different concepts from two different points of view. [0]https://github.com/torvalds/linux/blob/master/include/linux/list.h https://github.com/torvalds/linux/blob/master/include/linux/...
- mfukar 10y agoThat is both good and bad advice. Good because yes, programmers must quickly look at others' code and be exposed to the idioms and the anti-patterns. Bad because just by looking at something the newbies don't immediately connect it with one category or another, instruction is necessary to avoid them resorting to anti-patterns (as it is ironically the case with many things Linux).
- jackmott 10y agoI touch C only occasionally, so I'm not a guru. But I love macros. I want all languages to have macros.
- yitchelle 10y agoThis should have been shorten to "Avoid magic". This is applicable to any language, not just to C. Magic stuff are for wizards, and most of us are not.
- userbinator 10y ago"Magic" becomes obvious common-sense once you understand. The overall theme of the parent comment is that we should try to understand instead of giving up, because that's what makes us learn and become better at the language. IMHO if you want to become an expert in C and C++, you must be able to read Asm and understand what the machine is actually doing. A very relevant article on this same idea: http://www.linusakesson.net/programming/kernighans-lever/ http://www.linusakesson.net/programming/kernighans-lever/
- MrUnderhill 10y agoI've recently been reading Scott Meyers' Effective (Modern) C++ books. They are fantastic - can anyone recommend something similar for C? I.e. books that assume you're familiar with the language, but explains pitfalls and best practices in a practical way.
- fnord123 10y agoDeep C Secrets.
- krylon 10y agoThat book is great, very in-depth, yet fun to read. One caveat, though, this book is from the mid-nineties, so some parts are a little dated. Still, very much worth reading.
- tehwalrus 10y ago21st Century C is very very good. http://shop.oreilly.com/product/0636920033677.do http://shop.oreilly.com/product/0636920033677.do Enjoyable to read through, covers tools as well as the language, and a very good reference of good practise. It covers the basics and then goes into depth on a few of the things C is supposed to be bad at, demonstrating good ways to work (strings, threads, OOP, libraries). I have a copy on my bookshelf at work, and have been referring to it extensively this week (exposing a C entry point to a C++ world...) It has steered me away from some fairly silly things a couple of times! It does disagree quite strongly with the article though.
- rbehrends 10y agoThe problem with all this advice is that C lacks so many amenities of modern programming languages (no module system, no opaque types, no automatic memory management or RAII, no closures, no parametric polymorphism, no subtyping) that working around these limitations is bound to violate some of it. The same strict rules that you can afford to adhere to in other languages do not work for C: with C, the often delicate balance of tradeoffs can tip either way. > Do not use a typedef to hide a pointer or avoid writing “struct”. This really seems to fly in the face of the idea of information hiding, at least when listed as an absolute. The client of a module does not need to know whether (say) a handle is an int or a pointer. > Do not use macros. > Never put code into a header. Never use the inline keyword. This just doesn't strike me as good advice. You're creating potentially costly abstractions. For example: for (foo_init(&foo); !foo_done(&foo); foo_next(&foo)) { ... } Without macros or static inline functions, you're creating overhead. Overhead that other languages with proper module systems can avoid, but not C, so you have to work around it. Sometimes it's not an issue, sometimes this is code that you want to use in a hot loop. By not having low-overhead abstractions, you're encouraging manual inlining or hacking around their lack when writing performance-critical code (and if you aren't writing performance-critical code, why are you using C)? Macros are also the only alternative that you have in C to compensate for the lack of closures. They aren't closures, and they aren't even good macros, but cover some of the same use cases. > Do not use fixed size buffers - always calculate how much space you’ll need and allocate it. This is not exactly wrong, but it only talks about half of the problem. The alternative to fixed size buffers are manual memory management or alloca(). Manual memory management is also error-prone and alloca() can blow up the stack. It's not that people necessarily think that fixed size buffers are good: they're choosing between various pain points. Fixed size buffers with a generous upper limit that is properly enforced can make for a perfectly viable trade-off. > Keep your build system simple and transparent. This is a bit vague. What's "simple and transparent"? At some point, you'll have to deal with things like how to figure out dependencies, for example. Preprocessors and code generators are common in C projects, often to reduce common C pain points.
- GuB-42 10y agoI mostly agree, however I don't like the idea of making code easy for novices to understand as a primary goal. That's because may imply not using some powerful constructs out of fear they may not be well understood by beginners. I think it is better to imagine that the next person reading your code will be better than you and that he is going to judge you. So don't hold back, use your clever tricks, but make sure you use them correctly otherwise you will look like a fool. Also, never say never. All non-deprecated features of the language can be used : goto, inline, macros, you name it. You just need to know how to use them wisely.
- randcraw 10y agoIn case drewdevault.com has been blacklisted by your web proxy (as it is for mine), here's an alternate source: https://sircmpwn.github.io/2017/03/15/How-I-learned-to-stop-worrying-and-love-C.html https://sircmpwn.github.io/2017/03/15/How-I-learned-to-stop-...
- ziikutv 10y agoThanks for the read. Very educational. I would suggest increasing the font-weight of your bolded text. I could not differentiate the two when skimming over the article; only when I read very carefully did I notice that you had somethings bolded.
- pif 10y agoTL;DR: move on, nothing serious in this article. Just barking useless advice and spitting insulting nonsense.
- jankedeen 10y ago1. The only reason to use C these days _is_ performance and portability. Write the code to your level of expertise or use a different language to cater to the 'du jour' audience. 2. This was advice straight of Der lindens Deep C secrets back in the mid 90s. It wasn't always true then and it isn't always true now. I often use macros and don't find them a problem to understand in others code. 3. Give me a break. Except when you don't need to allocate and manage memory which is almost every time you write a tool that does one thing well. This is not a good general principle. 4. This is the way it works for me. Do it. Nope. 5. Ok, some of this is common sense writing portable code. 'GNU is a blight on this earth': "..now we see the violence inherent in the system.." 6. Yes, finally a good point but not about C per-se. 7. Ok, but this is not about C per-se. 8. Hrrmmm. A culture of blame is what produces restrictive rules like these. This article is fodder for the Rust and other anti-c devotees here to glom onto and point out all the problems with the author and his language as the ultimate straw man. To me it sounds like this person wasn't writing C in the 90s.
- deleted 10y ago[deleted]
- fish2000 10y agoDo not use magic. — Strongly agree. Do not use macros. — Absolutely I agree: I involuntarily grimace whenever I look at and/or things like Boost MPL, or the wartier corners of the Python C-API’s underbelly, etc. I only use macros as straight-up batched ⌘-C-⌘-V: #define DECLARE_IT(type, value) extern const type{ value } DECLARE_IT(int, 0); DECLARE_IT(int, 1); DECLARE_IT(float, 0.0f); // etc #undef DECLARE_IT Do not use typedefs to hide pointers […] — I cannot stand it when people do this. That asterisk is as syntactically valuable to you, the programmer, as it is essential to your program’s function. If the standard library can slap asterisks on file and directory handles than so can you (and by “you” I specifically include whoever wrote the `gzip` API among other things). […] or to avoid writing “struct” — Huh, actually I feel the opposite, I think all those “struct” identifiers are clutterific, much like excessive “typename” id’s in C++ template declarations. But so aside from the points where I totally disagree with the author, I absolutely feel the same way 100%.