Live data from Hacker News

Some C habits I employ for the modern day

unix.dog

51–60 of 162 posts

Re: Some C habits I employ for the modern day

#51

> and I end up having all these typedefs in my projects I avoid doing this now. It's more trouble than it's worth and it changes your code from a standard dialect of C into a custom one. Plus my eyes are old and they don't enjoy separating short identifiers. > typedef struct { ... } String I avoid doing this. Just use `struct string { ... };'. It makes it clear what you're handling. C23 finally gave us "auto", you sh…

> > typedef struct { ... } String > I avoid doing this. Just use `struct string { ... };'. It makes it clear what you're handling. Well then imagine if Gtk made you write `struct GtkLabel`, etc. and you saw hundreds of `struct` on the screen taking up space in heavy UI code. Sometimes abstractions are worthwhile.

> Well then imagine if Gtk made you write `struct GtkLabel`, etc. and you saw hundreds of `struct` on the screen taking up space in heavy UI code. Sometimes abstractions are worthwhile.

TBH, in that case the GtkLabel (and, indeed, the entire widget hierarchy) should be opaque pointers anyway.

If you're not using a struct as an abstraction, then don't typedef it. If you are, then hide the damn fields.

Re: Some C habits I employ for the modern day

#52
post #46

Earlier quoted context omitted.

> the fatal error was not combining the array dimension with the array pointer; all it needs is a little new syntax a[...]; this won’t fix any existing code. Over time, the syntax a[] can be deprecated by convention and by compilers. You're thinking in decades. C standard committee is slower than that. This could have worked in practice, but probably never will happen in practice. Maybe people should start considerin…

The C standard committee even refused Dennis Ritchie proposal for fat pointers. https://www.nokia.com/bell-labs/about/dennis-m-ritchie/varar... Meanwhile after UNIX was done at AT&T, the C language authors hardly cared for the C standard committee in regards to the C compiler supported features used in Plan 9 and Inferno, being only "mostly" compatible, followed up having a authoring role in Alef, Limbo and Go. > The…

> Meanwhile after UNIX was done at AT&T, the C language authors hardly cared for the C standard committee in regards to the C compiler supported features used in Plan 9 and Inferno, being only "mostly" compatible, followed up having a authoring role in Alef, Limbo and Go.

> I doubt most C advocates ever reflect on this.

What would be the conclusion of this reflection? Assuming you have reflected on this, what was your conclusion?

Re: Some C habits I employ for the modern day

#53
post #49

Earlier quoted context omitted.

> Yet another C person reinventing things which C++ already has. And yet another C++ person salty that people prefer simpler things.

C23 + is hardly simpler as people advocate.

I can't think of a language that isn't simpler compared to C++

Re: Some C habits I employ for the modern day

#54

Earlier quoted context omitted.

There is some irony in someone replying to the author of the D language suggesting that maybe the D language is the real solution he's looking for.

It might be the language he is looking for, but it might not, and more likely than not is not. D is one of those odd languages which most likely ought to have gotten a lot more popular than it did, but for one reason or another, never quite caught on. Perhaps one reason is because it lacks a sense of eccentricity and novelty that other languages in its weight class have. Or perhaps it's just too unfamiliar in all the…

I'm sorry, is this an in-joke or satire or something? I can't tell really. Maybe a woosh moment, and as others have said, the GP/person you are speaking about, Walter Bright, is the creator of the D language. Maybe you didn't read your parent's post? Not saying its intentional, but it almost seems rude to keep speaking in that way about someone present in the conversation.

Re: Some C habits I employ for the modern day

#55

Earlier quoted context omitted.

> > typedef struct { ... } String > I avoid doing this. Just use `struct string { ... };'. It makes it clear what you're handling. Well then imagine if Gtk made you write `struct GtkLabel`, etc. and you saw hundreds of `struct` on the screen taking up space in heavy UI code. Sometimes abstractions are worthwhile.

The main thing I dislike about typedefs is that you can't forward declare them. If I know for sure I'm never going to need to do that then OK.

How do you mean? You can at least do things like

typedef struct foo foo;

and somewhere else

struct foo { … }

Re: Some C habits I employ for the modern day

#56
post #49

Earlier quoted context omitted.

> Yet another C person reinventing things which C++ already has. And yet another C++ person salty that people prefer simpler things.

C23 + is hardly simpler as people advocate.

> C23 + is hardly simpler as people advocate.

Well, certainly simpler than C++, at any rate.

I mean, just knowing the assignment rules in C++ is worthy of an entire book on its own. Understandably, the single rule of "assignment is a bitwise copy of the source variable into the destination variable" is inflexible, but at least the person reading the local code can, just from the current scope, determine whether some assignment is a bug or not!

In many ways, C++ requires global context when reading any local scope: will the correct destructor get called? Can this variable be used as an argument to a function (a lack of a copy constructor results in the bitwise copy for on stack, with the destructor for that instance running twice - once in the stack and again when the scope ends)? Is this being passed by reference (i.e. it might be modified by the function we are calling) or by value (i.e. we don't need to worry about whether `bar` has been changed after a call to `foo(bar)`).

Many programmers don't like holding lots of global scope in their head when working in some local scope. In C, all those examples above are clear in the local scope.

All programmers who prefer C over C++ have already tried C++ in large and non-trivial projects before walking away. I doubt that the reverse is true.

Re: Some C habits I employ for the modern day

#58

Please don’t buy into “no const”. If you’ve ever worked with a lot of C/C++ code, you really appreciate proper const usage and it’s very obvious if a prototype is written incorrectly because now any callers will have errors. No serious reusable library would expose functions taking char* without proper const usage. You would never be able to pass a C++ string c_str() to such a C function without a const_cast if that…

Where is the author advocating not using const or casting it away?

Re: Some C habits I employ for the modern day

#59
post #48
post #18

That made me smile If I find myself needing a bunch of dynamic memory allocations and lifetime management, I will simply start using another language–usually rust or C#. Now that is some C habit for the modern day... But huh, not C.

I started doing that in 1993 on MS-DOS already, thanks to C++ RAII, C felt outdated already on those days.

Arguably, 1993's C has survived better than 1993's C++.

Re: Some C habits I employ for the modern day

#60
I'm a huge fan of the 'parse, don't validate' idiom, but it feels like a bit of a hurdle to use it in C - in order to really encapsulate and avoid errors, you'd need to use opaque pointers to hidden types, which requires the use of malloc (or an object pool per-type or some other scaffolding, that would get quite repetitive after a while, but I digress).

You basically have to trade performance for correctness, whereas in a language like C++, that's the whole purpose of the constructor, which works for all kinds of memory: auto, static, dynamic, whatever.

In C, to initialize a struct without dynamic memory, you could always do the following:

    struct Name {
        const char *name;
    };

    int parse_name(const char *name, struct Name *ret) {
        if(name) {
            ret->name = name;
            return 1;
        } else {
            return 0;
        }
    }

    //in user code, *hopefully*...
    struct Name myname;
    parse_name("mothfuzz", &myname);
But then anyone could just instantiate an invalid Name without calling the parse_name function and pass it around wherever. This is very close to 'validation' type behaviour. So to get real 'parsing' behaviour, dynamic memory is required, which is off-limits for many of the kinds of projects one would use C for in the first place.

I'm very curious as to how the author resolves this, given that they say they don't use dynamic memory often. Maybe there's something I missed while reading.

Post reply on HN