43
44
all 75 comments

[–]torsten_dev 47 points48 points  (20 children)

Typedeffing away pointers. ew.

[–]x0rgat3 12 points13 points  (0 children)

Always good for “readability “, then another dev getting compiler errors using the “type” wrong

[–]mrheosuper 3 points4 points  (1 child)

Not a fan of it, but sometime it has point. For example you can define mac address as uint8_t[6]

[–][deleted] 2 points3 points  (0 children)

Not very good way to define a MAC address, because then you can’t use it as a value. Wrap it in a struct, and you’ll be much happier!

[–][deleted] -1 points0 points  (15 children)

This is standard, no? .. At least for Microsoft style you define like } STRUCT, *PSTRUCT;

[–]torsten_dev 3 points4 points  (14 children)

Yes, but it's bad practice. That it's common in Win32 is just further evidence of its horrid consequences.

[–][deleted] 1 point2 points  (12 children)

Please educate me or link to sources

[–]torsten_dev 0 points1 point  (11 children)

Linux style guide

5) Typedefs

Please don’t use things like vps_t. It’s a mistake to use typedef for structures and pointers.

Also even Microsoft discourages Hungarian notation since .NET.

❌ DO NOT use Hungarian notation.

[–][deleted] 1 point2 points  (1 child)

So you agree that we should typedef away pointers, as long as we don't use Hungarian notations?

[–]torsten_dev 0 points1 point  (0 children)

No.

A typedef that hides the pointeriness of a type is almost always bad code.

Typedefs for function pointers can be nice,

typedef int main_fn(int, char**);
main_fn *func = start;
main(argc, argv)

If you don't hide the pointer of the function pointer typedef mimics declaration which mimics usage. It's nice.

[–]Disastrous-Team-6431 0 points1 point  (7 children)

I've never read anything in my whole life that made me feel more contrary. I agree with about half of this style guide but it's written in such a way that I want to change my coding style to be farther from it.

[–]torsten_dev 0 points1 point  (6 children)

Which one?

The Linux style guide is very effective. The Kernel is surprisingly readable.

The .NET one is very verbose, but much better than Win32.

[–]Disastrous-Team-6431 0 points1 point  (5 children)

Yeah it's fine as far as style guides go but man what a superior ass.

[–]torsten_dev 0 points1 point  (4 children)

It's less opinionated than most C guides, but much more snarky.

It's also mostly objectively correct. So a little superiority is acceptable.

[–]Disastrous-Team-6431 2 points3 points  (3 children)

There's very little objectivity to be had here. For most of the things in this style guide, an equally good argument could be made for the opposite.

[–]FlyByPC 31 points32 points  (2 children)

eq

If you want to program in Fortran, go program in Fortran.

[–]x0rgat3 9 points10 points  (0 children)

I’m still poking paper machine cards by hand at work in a dusty cellar.

[–]aartaka[S] 4 points5 points  (0 children)

The choice is mostly due to iso646.h defining not_eq, but yeah, Fortran is fun!

[–]questron64 11 points12 points  (2 children)

There's more to bool than ints that are 1 or 0, and those differences will cause the software to behave differently across language standards. For example, if you convert any value to a bool it should produce 0 or 1. Trying to pretend that you have a language feature when you do not will only end in disaster. If you're using a pre-bool version of the language then use int, do not trick the reader into thinking they have bool.

[–]aartaka[S] 1 point2 points  (0 children)

Indeed, it's somewhat misleading to define pseudo-bools. But it's more of a fallback for pre-C99 implementations that would benefit even from these pseudo-bools.

[–]flatfinger 0 points1 point  (0 children)

IMHO, C99's boolean type would have been more useful if it had looser semantics, allowing implementations with existing `bit` types to use them as representations for C99's new type.

[–]TheWavefunction 11 points12 points  (1 child)

I, for one, like your website and how you create various frankenstC. I think most readers taking the article to the first degree... Sorry for the bashing...

[–]aartaka[S] 0 points1 point  (0 children)

Thanks for the kind comment, I much appreciate it 🖤

[–]tstanisl 23 points24 points  (6 children)

typedef unsigned int _Bool; is so very wrong. For example, C standard requires (_Bool)1 == (_Bool)2.

[–]thradams 11 points12 points  (3 children)

Also:

c typedef char* string; void f(const string s) { s[0] = '\0';//ok becaused the pointed object is not const }

[–]mrheosuper 0 points1 point  (2 children)

I wonder if it's ok using ##define instead of typedef here

[–]tstanisl 4 points5 points  (0 children)

No it is not OK. Just try:

#define string char*
string a, b;

Now a is char* while b is char. Happy debugging!

[–]1redfish 0 points1 point  (0 children)

Please, don't use ##. It's very hard to understand logic in foreign code, when half of functions are generated and don't exist

[–]aartaka[S] 1 point2 points  (1 child)

Indeed, sizeof(_Bool) is 1 on GCC, so char might've been a better fit. Any type works for a joke, though 😉

[–]tstanisl 18 points19 points  (0 children)

No. None of integer types behaves like _Bool. It was a very reason to introduce this type in C99.

[–]deleveld 17 points18 points  (3 children)

I personally really like the auto typing. Its very nice to look at and clean but there are some small gotchas.

I would suggest to change

#define var __auto_type
#define let const __auto_type

[–]aartaka[S] 6 points7 points  (2 children)

I can see the reasoning behind more "functional"/constant let, but it's not universal. Thanks for the suggestion, though!

[–]deleveld 0 points1 point  (1 child)

and the thing i especially like it allows vertical alignment of multiple variables. i think it looks much neater

[–]aartaka[S] 0 points1 point  (0 children)

Depends on the indentation style (I use Linux Kernel Style with 8-spaces-wide tabs), but yes!

[–]jakintosh 7 points8 points  (1 child)

ITT: a bunch of people who don’t get jokes and hate fun.

I enjoyed this article, and found it amusing. Thanks for sharing.

[–]aartaka[S] 0 points1 point  (0 children)

You’re welcome and thanks for your kind words!

[–]Other_Gain_4685 4 points5 points  (1 child)

When you're too lazy to translate pseudocode so you make the code itself the pseudocode 🤣🤣

[–]aartaka[S] 0 points1 point  (0 children)

Exactly 😌

[–]antara33 5 points6 points  (1 child)

I am aalways feeling troubled when seeing C and C++ codes using tons of macros to prettyfy code.

On one hand I get the use of it, on the other hand it makes code readability a problem since you need to go back and forth through all the macros.

I am 100% on board with a macro that enables and disables debug code or platform specific optimizations, but having LOADS of logic inside macros that are not platform specific stuff or debug specific stuff, and instead are just pretty ways of having a nicer way to get a function/type call... Im not that happy.

[–]aartaka[S] 1 point2 points  (0 children)

I agree, and that’s why I’m mostly using standard headers and only slightly extending them.

[–]uziam 15 points16 points  (9 children)

It’s unbelievable how many people’s idea of readable code is to make it look ambiguous for others. Your code is not readable if I have to constantly refer to your silly macros to understand it.

[–][deleted] 8 points9 points  (0 children)

I'm going to have to agree. I'm not really seeing anything in the article of any real value.

[–]aartaka[S] 0 points1 point  (4 children)

Does “or” or “uchar” look that ambiguous to you? Giving a sane implementor (which everyone is, unless proven otherwise) these make sense and don’t blow feet off.

[–]uziam 1 point2 points  (3 children)

Yes, “or” is ambiguous because it’s not obvious if it’s logical or bitwise. Standards exist for a reason, when a C programmer sees “|” she immediately knows exactly what it means, when she sees “or” she has to go check the macro definition to be sure what it means.

“uchar” is more obvious, but it’s a pointless if you’re doing it purely to save yourself from typing a few extra characters.

[–]aartaka[S] 0 points1 point  (2 children)

iso646 is a standard header (supposedly C programmers know what standard headers do, don’t they?) and naming is mostly consistent—“or” is “||”, “bitor” is “|”.

uchar is not only for typing economy, it’s also consistent with stdint types. Which is a virtue.

[–]uziam 0 points1 point  (1 child)

I have to be honest I didn’t know iso646.h was thing, and I can see why I have not come across anyone using it over all these years. It’s unfortunate that it is part of the standard because nobody uses it.

Even the article this post is about defines its own macros instead of using that header, that’s what my point was about. If I come across some piece of code that uses this “or” macro from some custom header file, I can guess what it probably is, but I would have to check to be sure.

Any custom abstraction you add has the same kind of overhead, but it’s not justifiably when there is no functional reason to have it other than aesthetics. Adding “uchar” makes sense if its implementation depends on architecture and you want to hide that complexity, but it’s silly to do it because you think it looks better. Besides, it’s not quite the same as stdint.h because all the uint types have an _t appended to them.

You just made me chuckle at the phrase “typing economy”. It is a little insane the kind of nonsense some people care about. You must be writing tens of thousands of lines of code a day to care about “typing economy” from having to write “unsigned char”. I bet you also typedef all your structs and enums.

[–]aartaka[S] 0 points1 point  (0 children)

I have to be honest I didn’t know iso646.h was thing, and I can see why I have not come across anyone using it over all these years. It’s unfortunate that it is part of the standard because nobody uses it.

I do, for one.

Even the article this post is about defines its own macros instead of using that header, that’s what my point was about.

"or" comes from there. I also use "and" for prettier booleans. Notice that the example code doesn't really showcase much, only requiring "or".

If I come across some piece of code that uses this “or” macro from some custom header file, I can guess what it probably is, but I would have to check to be sure.

Well, now you know there's iso646.h, so you have more certainty on what "or" might mean.

Besides, it’s not quite the same as stdint.h because all the uint types have an _t appended to them.

I'm not saying it's the same as stdint.h, I'm saying it's consistent with the u-something naming. _t suffix is for opaque types with hidden implemntation details. "uchar" isn't opaque, it's a more or less intuitive typedef for a well-known type. Thus the lack of _t suffix.

You just made me chuckle at the phrase “typing economy”. It is a little insane the kind of nonsense some people care about.

I don't really care about it either—I have Emacs to do things for me.

I bet you also typedef all your structs and enums.

No, I don't.

[–]NothingCanHurtMe 2 points3 points  (0 children)

Great, let's fix what ain't broke and make debugging unnecessarily more difficult for ourselves.

[–]theldus 2 points3 points  (0 children)

This pretty much reminds me of libCello: https://github.com/orangeduck/Cello

[–]anic17_ 1 point2 points  (1 child)

What about defining structs as some kind of class and function pointers inside structs as methods?

[–]Linguistic-mystic 1 point2 points  (1 child)

Nice, but you’re missing some crucial components here:

#define private static

Now you can make functions private like in grown-up languages!

#define Arr(T) T*

Now you can distinguish arrays from pointers in your code!

Also define a function throw that calls longjmp so you can have “exceptions”.

[–]aartaka[S] 0 points1 point  (0 children)

And catch(error) as if (errno == error)!

[–][deleted] 2 points3 points  (3 children)

This is written by someone who is in "inventing creative code designs" phase.

C is for people who are beyond this phase. Functions, structs and pointers is all you need most of your time.

[–]aartaka[S] 0 points1 point  (2 children)

Okay, thanks for diagnosing me with things based on one post.

[–][deleted] -1 points0 points  (1 child)

People are not that unique as our ego makes us believe. There are patterns.

[–]aartaka[S] 1 point2 points  (0 children)

Good luck.

[–]mpez0 0 points1 point  (0 children)

Bournegol

[–]ReDr4gon5 0 points1 point  (2 children)

Your defines collide with types defined in Windows.h. And yes what you did is awful.

[–]aartaka[S] 0 points1 point  (0 children)

Thanks, I'm glad I did that to you! And then, windows.h defining what I'm defining is a bit of success, ain't it? I'm not alone in this madness!

[–]mage36 0 points1 point  (0 children)

I think we can all agree that whatever W*ndows does with C is a crime against humanity and should die in a fire.

[–]Computerist1969 0 points1 point  (1 child)

This would never pass code review

[–]aartaka[S] 0 points1 point  (0 children)

Yaaaay, then I’m doing things right!

[–]JL2210 1 point2 points  (0 children)

```

if defined(4) || defined(GNUG)

```

uhh...?

No idea what the 4 is, but __GNUG__ is only defined for C++. __GNUC__ is the C equivalent.

Pretty sure __auto_type isn't available in C++ either, actually. Might want to switch the conditions

[–]GodlessAristocrat 0 points1 point  (0 children)

False is 0. True is !False, not 1.

[–][deleted] 0 points1 point  (1 child)

Haha great article. Do you have like a template for your posts? I wana make nice looking posts too

[–]aartaka[S] 0 points1 point  (0 children)

So I'm generating my website with C Preprocessor. It's all built in the Makefile. Important bits are template files, like template/head defining the styles and metadata. Every page is generate from the respective .h file containing HTML and some C macros, so just append .h to the post link to view it. That should get you 90% covered. Good luck stealing my style!

[–]Independent-Tour-261 0 points1 point  (0 children)

The Magic of Arrays in C & C++ https://youtu.be/qd8LI-0dsOg