Live data from Hacker News

Principles for C programming

drewdevault.com

41–50 of 149 posts

Re: Principles for C programming

#41

Earlier quoted context omitted.

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

Just use strtol or strtof Which of these is more likely to have bugs? int i; if (PARSENUM(&i, s, 0, 1000)) err("Invalid input: %s", s); or int i; long l; // need a temporary long to avoid overflow char * ep; errno = 0; l = strtol(s, &ep, 0); if ((ep == s) || (*ep = '\0')) // make sure we parsed a number and don't have trailing garbage errno = EINVAL; if ((l 1000)) errno = ERANGE; if (errno) err("Invalid input: %s", s…

To be honest I would just have your library offer a function that does it your fancy way. I agree that there could be better integer parsing functions, I disagree that they should be macros.

>Not at all. The point is to have self-contained routines which Just Work in order to ensure that the rest of the code is easier to read and maintain.

Self-contained routines that are completely unmaintainable and unintelligible to anyone but you, though. Not worth it.

Re: Principles for C programming

#42
post #10

Earlier quoted context omitted.

"nobody's grading your code by how many abstractions and topics from a textbook it employs."

That said, people sometimes ate grading your code based on performance. Good algorithms often win over simplistic ones.

I'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(I cannot retrieve the article this was taken from)

Re: Principles for C programming

#43

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…

Not sure I follow.

> scalars

So you would typedef the scalars then? If you don't, then scalars will be the built-in types (which you'd presumably know well) and then all other type names will be typedef'ed structs/unions, still making it trivial to recognize them as such.

Re: Principles for C programming

#44
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

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

Re: Principles for C programming

#45

Earlier quoted context omitted.

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

Not sure I follow. > scalars So you would typedef the scalars then? If you don't, then scalars will be the built-in types (which you'd presumably know well) and then all other type names will be typedef'ed structs/unions, still making it trivial to recognize them as such.

Yes, I think typedefing scalars is fine. Typedefs are useful for abstracting the underlying storage mechanism for a scalar (so you can i.e. change it on different archictures or in a future release without breakage), not for saving yourself 6 characters of typing.

Re: Principles for C programming

#46

Earlier quoted context omitted.

Just use strtol or strtof Which of these is more likely to have bugs? int i; if (PARSENUM(&i, s, 0, 1000)) err("Invalid input: %s", s); or int i; long l; // need a temporary long to avoid overflow char * ep; errno = 0; l = strtol(s, &ep, 0); if ((ep == s) || (*ep = '\0')) // make sure we parsed a number and don't have trailing garbage errno = EINVAL; if ((l 1000)) errno = ERANGE; if (errno) err("Invalid input: %s", s…

To be honest I would just have your library offer a function that does it your fancy way. I agree that there could be better integer parsing functions, I disagree that they should be macros. >Not at all. The point is to have self-contained routines which Just Work in order to ensure that the rest of the code is easier to read and maintain. Self-contained routines that are completely unmaintainable and unintelligible…

To be honest I would just have your library offer a function that does it your fancy way.

It's not possible to have a single function do this. Not possible to have any finite number of functions do this if, like me, you want to support all floating-point and integer types.

Self-contained routines that are completely unmaintainable and unintelligible to anyone but you, though.

All of my macros are intelligible to anyone who understands the C preprocessor.

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?

Re: Principles for C programming

#47

Earlier quoted context omitted.

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

Not sure I follow. > scalars So you would typedef the scalars then? If you don't, then scalars will be the built-in types (which you'd presumably know well) and then all other type names will be typedef'ed structs/unions, still making it trivial to recognize them as such.

There are also enums, which are user defined scalar types (although I don't think this fact really affects your argument).

Re: Principles for C programming

#48

Earlier quoted context omitted.

To be honest I would just have your library offer a function that does it your fancy way. I agree that there could be better integer parsing functions, I disagree that they should be macros. >Not at all. The point is to have self-contained routines which Just Work in order to ensure that the rest of the code is easier to read and maintain. Self-contained routines that are completely unmaintainable and unintelligible…

To be honest I would just have your library offer a function that does it your fancy way. It's not possible to have a single function do this. Not possible to have any finite number of functions do this if, like me, you want to support all floating-point and integer types. Self-contained routines that are completely unmaintainable and unintelligible to anyone but you, though. All of my macros are intelligible to anyo…

>It's not possible to have a single function do this. Not possible to have any finite number of functions do this if, like me, you want to support all floating-point and integer types.

Just tack an 'i' or 'f' or 'l' on the end. Not a big deal. Literally one extra character. And you don't have to hold shift the whole time.

>All of my macros are intelligible to anyone who understands the C preprocessor.

I understand the C preprocessor fine and I have to stop and mentally decode all the crap your macros are trying to do.

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

All code is liable to have bugs. All code is liable to have performance issues. All code is liable to use an outdated syntax or features in 10 years. What if the stdlib does improve and adds functions that supplant these? What if they do so only partially? What if your functions could be improved to rely on a new stdlib function that's safer/faster/etc?

Re: Principles for C programming

#50
post #38

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…

> 'I typedef my structs all the time, and call them something_t, and * something_p’ I wish people would stop perpetuating this particular naming convention. Its in violation of POSIX which specifically reserves the entire *_t ‘namespace’. Obviously its fine if this is done on a system or environment for which this is irrelevant, but its best avoided otherwise.

The reality is that if you are creating a library you probably should prefix your types and functions anyway. And rely on the prefix to minimize collision probability. So it doesn't really matter if you put _t and the end of your type aliases. You will probably not get the collisions anyway. Unless POSIX is going to suddenly introduce mylib_array_t or something.
Post reply on HN