Live data from Hacker News

Principles for C programming

drewdevault.com

21–30 of 149 posts

Re: Principles for C programming

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

> 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

Re: Principles for C programming

#22
post #5

Earlier quoted context omitted.

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.

> 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

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

Re: Principles for C programming

#23

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

It's quite common in Embedded programming to use pools of fixed size buffers. Malloc/free work on these pools.

I tend to find fixed size buffers easier to conceptualize than dynamically allocated buffers. Tend to find that even with most modern language C#/Java I still see developer use fixed size buffer even within enterprise apps.

So I think there is something to be said with the whole movement of books/expert advice advocating against fixed size buffers/enum's to use more dynamic memory models when people in the trade are still using enum and static sizes. Anecdotally I've seen it more use of it now than any time in the past.

Re: Principles for C programming

#24
post #18

Earlier quoted context omitted.

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

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

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

Re: Principles for C programming

#25
Avoid 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/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/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/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-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.

Re: Principles for C programming

#26
post #5

Earlier quoted context omitted.

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.

I 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?

Because stdout is a FILE *. What he should have used is STDOUT_FILENO.

Re: Principles for C programming

#27
post #5

Earlier quoted context omitted.

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.

I 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?

indeed, it's just a naive example but wouldn't something like

    int written = write(STDOUT_FILENO, toWrite, len);
    if (written != len) 
        { ...
be simpler ?

Re: Principles for C programming

#28

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

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

Re: Principles for C programming

#29

Avoid 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/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 string…

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

Re: Principles for C programming

#30

Avoid 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/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 string…

As a webdeveloper that likes to use C rarely for private things: I like that "elastic arrays" thing.
Post reply on HN