Live data from Hacker News

Principles for C programming

drewdevault.com

81–90 of 149 posts

Re: Principles for C programming

#81
post #80

Earlier quoted context omitted.

>My memory is rusty - aren't those features "protected" against accidental usage, with something like "#define GNU_SOURCE" needed before you include the headers? Or is that protection insufficient? They are "protected", yes, but their mere presence encourages people to use them. There's no reason to use asprintf, but glibc makes it available so some software uses it. That software is now non-portable. >On the coding…

> They are "protected", yes, but their mere presence encourages people to use them. There's no reason to use asprintf, but glibc makes it available so some software uses it. That software is now non-portable. I think asprintf is useful - it replaces an ugly "malloc-realloc-snprintf-loop"... On exposing non-portable functions/features: - OpenBSD does it (pledge) - Freebsd/NetBSD do it (kqueue) - ... I'm certain other…

>I think asprintf is useful - it replaces an ugly "malloc-realloc-snprintf-loop"...

Well, implement it yourself then. It's really not hard to live without, though. I don't know about this loop you're talking about but I just do this:

    int len = snprintf(NULL, 0, "fmt", ...);
    char *foo = malloc(len + 1);
    snprintf(foo, len, "fmt", ...);
Easy to wrap that up in your own asprintf function if you would find that useful. And in practice writing a lot of these functions is going to happen anyway when someone ports your non-portable code to another system.

Re: Principles for C programming

#82

Earlier quoted context omitted.

> 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…

>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. The benefit is to readability. You should treat structs differently from scalar…

Surely a simple naming convention such as a capital letter for compound types is sufficient?

Re: Principles for C programming

#83
post #71
post #59

Earlier quoted context omitted.

> More to the point, why do they need to be maintainable? When was the last time you maintained the strtof function in your C library? A few years ago. https://sourceware.org/bugzilla/show_bug.cgi?id=15744 Acting like you can get anything done right in C simply because it's self-contained is proven wrong every day. It's good practice, yes, but doesn't magically (we like this word now) make us immune to error. Everyth…

> we can't just replace broken pieces of code with the same simplicity we can replace a broken fridge. Sure we can. Recompile glibc, dynamic linking, pow. I wouldn't say that bug you referenced is a strike against C; it could happen in any language that was locale-aware and parsing floats. For what it's worth, these macros in libcperciva are perfectly readable and maintainable: #define ELASTICARRAY_DECL(type, prefix,…

> Sure we can. Recompile glibc, dynamic linking, pow.

Oh, so I have to maintain glibc. That's the alternative, we are in complete agreement.

> I wouldn't say that bug you referenced is a strike against C; it could happen in any language that was locale-aware and parsing floats.

I was responding to a very specific (and pointed) question.

> For what it's worth, these macros in libcperciva are perfectly readable and maintainable:

I'm not contesting that, they might be. The one you list looks fine at a glance, but that doesn't prove anything.

Re: Principles for C programming

#84
I'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.

Re: Principles for C programming

#85
post #79

>>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…

That 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).

Re: Principles for C programming

#86
post #64

> 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.

"Do not assume" doesn't really mean or imply "do not target", so stop being defensive. It's good advice.

Targeting expresses expectations about an environment. "Do not assume" would be contradictory to those explicit expectations.

Re: Principles for C programming

#87
The 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.

Re: Principles for C programming

#88
I 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.

Re: Principles for C programming

#89
post #5
post #4

All 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/omstd... It's an output module for rsyslog that logs to stdout. I wanted to gouge my eyes out.

This 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.

While 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.

Re: Principles for C programming

#90
post #79

>>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…

I touch C only occasionally, so I'm not a guru. But I love macros. I want all languages to have macros.
Post reply on HN