Live data from Hacker News

Principles for C programming

drewdevault.com

121–130 of 149 posts

Re: Principles for C programming

#121
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'm coding in C89 because I'm writing software for industrial embedded controllers. Future maintainers of this software are more likely to be electronic engineers than programmers, so "keep it simple and don't use magic" is actually extremely good advice.

That said, my code does use a couple of macros, but only to do stuff that would be very long-winded and/or impossible without, and using malloc at all is very much frowned upon: storage should either be declared ahead of time in special .var files, or on the stack.

Re: Principles for C programming

#122
post #108
post #61

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

One of the most evil parts is /etc/nsswitch.conf that injects at runtime arbitrary shared libraries implementing various parts of GNU C library. That leads to proliferation of undocumented file formats and protocols that are hidden behind library interfaces. For example, Linux still does not have a sane DNS resolver interface that is useful without GNU-C library. With move to containers that lead to many issues like…

> One of the most evil parts is /etc/nsswitch.conf that injects at runtime arbitrary shared libraries implementing various parts of GNU C library. That leads to proliferation of undocumented file formats and protocols that are hidden behind library interfaces.

Are you opposed to dynamically linked libraries in general? Or do you simply oppose using them for name resolution? And how would you propose implementing NIS, LDAP/Kerberos, etc. without them (and without recompiling the libc itself)?

> For example, Linux still does not have a sane DNS resolver interface that is useful without GNU-C library. With move to containers that lead to many issues like inability to resolve link-local names etc.

Valid criticism. But that's not the GNU peoples' fault, IMHO - I mean, they have a working libc, it's not their fault that containers don't work with other libcs. (Or do i misunderstand you?)

Re: Principles for C programming

#123

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

I think these are just basic general principles, not unbreakable rules. Keep them in mind but break them when you really have too. Like the quote at the beginning says, avoid doing stupid things, but don't refrain from doing clever things when you have to.

Re: Principles for C programming

#125
post #76

1) 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

Did 1, 2 and 4 around 20 years ago.

Re: Principles for C programming

#126
post #76

1) 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

or

1) Learn Embedded Design

2) Stay in C for another few decades

Re: Principles for C programming

#127
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'm coding in C89 because I'm writing software for industrial embedded controllers. Future maintainers of this software are more likely to be electronic engineers than programmers, so "keep it simple and don't use magic" is actually extremely good advice. That said, my code does use a couple of macros, but only to do stuff that would be very long-winded and/or impossible without, and using malloc at all is very much…

Yeah, in general I agree with the article, the 'malloc all your memory' part is something I disagree with heavily. Outside of the fact that many malloc and calloc implementations don't particularly deal well with integer overflow[0], it introduces non-determinism into your code. MISRA C even forbids the use of dynamic memory allocation.

In fact, the environments where C shines oftentimes won't even have a dynamic allocator...

[0] Try allocating ((size_t)-1) bytes. Quite a few implementations will give you a pointer back! They'll add some space for a header, or round up the size to the nearest n-byte boundary. This problem's compounded by the fact people assume passing unsanitized input to malloc effectively sanitizes it.

Re: Principles for C programming

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

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

Re: Principles for C programming

#129

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…

I doubt getting confused between structs and scalars is a problem in practice. It surely never has been for me.

For me this is cargo cult maintainability: it has the sound of a good advice, but doesn't seem grounded in reality.

Re: Principles for C programming

#130
post #122
post #108

Earlier quoted context omitted.

One of the most evil parts is /etc/nsswitch.conf that injects at runtime arbitrary shared libraries implementing various parts of GNU C library. That leads to proliferation of undocumented file formats and protocols that are hidden behind library interfaces. For example, Linux still does not have a sane DNS resolver interface that is useful without GNU-C library. With move to containers that lead to many issues like…

> One of the most evil parts is /etc/nsswitch.conf that injects at runtime arbitrary shared libraries implementing various parts of GNU C library. That leads to proliferation of undocumented file formats and protocols that are hidden behind library interfaces. Are you opposed to dynamically linked libraries in general? Or do you simply oppose using them for name resolution? And how would you propose implementing NIS,…

NIS, LDAP etc should have used a unix socket interface to talk system daemons using well-defined API. This is what happens in practice in any case, but it is done over hidden protocols unusable outside glibc.

As for the resolver, then consider that on Ubuntu/Fedora etc. there is hack to set the nameserver in /etc/resolv.conf to 127.0.0.1 which runs a local caching resolver. However this is broken for local name resolution with multiple interfaces as DNS replies do not include interface name. So in a better world glibc simply talks to a system daemon using well-defined protocol. Instead right now to expose, say mdns into containers, one has to spend too much efforts with various hacks even if one does use glibc in a container application.

Post reply on HN