Live data from Hacker News

Some C habits I employ for the modern day

unix.dog

121–130 of 162 posts

Re: Some C habits I employ for the modern day

#122

Earlier quoted context omitted.

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.

The usual solution for this is: typedef struct bla_s { ... } bla_t; Now you have a struct named 'bla_s' and a type alias 'bla_t'. For the forward declaration you'd use 'bla_s'. Using the same name also works just fine, since structs and type aliases live in different namespaces: typedef struct bla_t { ... } bla_t; ...also before that topic comes up again: the _t postfix is not reserved in the C standard :)

People getting hung up on `_t` usage being reserved for posix need to lighten up. I doubt they'll clash with my definitions and if does happen in the future, I'll change the typedef name.

Re: Some C habits I employ for the modern day

#123

Earlier quoted context omitted.

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 think that D meets Walter Bright's requirements.

I would hope so. He invented the damn language.

Re: Some C habits I employ for the modern day

#124

Earlier quoted context omitted.

D is an elegant re-imagine of C and C++. For a trivial example, typedef struct S { int a; } S; becomes simply: struct S { int a; } and unlike C: extern int foo(); int bar() { return foo(); } int foo() { return 6; } you have: int bar() { return foo(); } int foo() { return 6; } For more complex things: #include becomes: import foo;

Smoe of these are definitely nice-to-haves*, but when you're evaluating a C++ alternative, there are higher priority features to research first. How are the build times? What does its package system(s) look like, and how populated are they? What are all its memory management options? How does it do error handling and what does that look like in real world code? Does it have any memory safety features, and what are th…

Build times are quite a bit faster.

The package system is called dub.

Memory management options include:

1. stack allocation

2. malloc allocation

3. write your own allocator

4. static allocation

5. garbage collection

You can use exceptions or returns for error handling.

The biggest memory safety feature it has is length-delimited arrays. No more array overflows! The cost of it is the same as in std::vector when you do the bounds checked option. D also uses refs, relegating pointers to unusual uses. I don't know what you mean by "participating in optimizations".

(a) C doesn't have the hack that C++ has regarding the tag names. D has auto.

(b) D has much faster compile times than C++.

(c) The practical benefit is the language is much easier to master.

Re: Some C habits I employ for the modern day

#125

Earlier quoted context omitted.

The usual solution for this is: typedef struct bla_s { ... } bla_t; Now you have a struct named 'bla_s' and a type alias 'bla_t'. For the forward declaration you'd use 'bla_s'. Using the same name also works just fine, since structs and type aliases live in different namespaces: typedef struct bla_t { ... } bla_t; ...also before that topic comes up again: the _t postfix is not reserved in the C standard :)

Yes, using the same Gtk example, the way you’d forward declare GtkLabel without including gtklabel.h in your header would be: struct _GtkLabel; typedef struct _GtkLabel GtkLabel; // Use GtkLabel* in declarations

Why are you complicating things? Struct and Unions are different namespaces for a reason.

    typedef struct GtkLabel GtkLabel;
works just fine.

Re: Some C habits I employ for the modern day

#126

Earlier quoted context omitted.

D is an elegant re-imagine of C and C++. For a trivial example, typedef struct S { int a; } S; becomes simply: struct S { int a; } and unlike C: extern int foo(); int bar() { return foo(); } int foo() { return 6; } you have: int bar() { return foo(); } int foo() { return 6; } For more complex things: #include becomes: import foo;

Everything except the import looks like standard c++ since at least 98.

C++ does not allow forward references outside of structs. The point-of-instantiation and point-of-declaration rules for templates produces all kinds of subtle problems. D does not have that issue.

Yes, you absolutely can get the job done with C and C++. But neither is an elegant language, and that puts a cognitive drag on writing and understanding code.

Re: Some C habits I employ for the modern day

#128

Earlier quoted context omitted.

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…

D is an elegant re-imagine of C and C++. For a trivial example, typedef struct S { int a; } S; becomes simply: struct S { int a; } and unlike C: extern int foo(); int bar() { return foo(); } int foo() { return 6; } you have: int bar() { return foo(); } int foo() { return 6; } For more complex things: #include becomes: import foo;

Your first example doesn't make sense, because

    struct S { int a; };
is also fine and idiomatic in C. It is rather

    typedef struct S { int a; } S;
that doesn't make sense, because why would you make something opaque and expose it immediately again in the same line?

The others are ... different. I can't tell whether they are really better. The second maybe, although I like it that the compiler forces me to forward type stuff, it makes the code much more readable. But then again I don't really get the benefit of

    import foo;
vs

    #include 
.

include vs import is no difference. # vs nothing makes it clear that it is a separate feature instead of just a language keyword. < vs " make it clear whether you use your own stuff or stuff from the system. What do you do when your file contains spaces? Does import foo bar; work for including a file a single file, named "foo bar"?

Re: Some C habits I employ for the modern day

#129
post #42

Earlier quoted context omitted.

You can do such things until you have to interface with other code, eg the operating system.

So that’s an interesting case. I’d really like to keep language neutrality, because I don’t think we’re finished evolving yet. So this is a place where we need an abi. The first things we try to do is be simple…except for a terrible mistake with select, we don’t send arrays across that interface, sadly, we send c structs sometimes and I think that’s pretty horrible, because we have to try to lay them out in a compati…

As a matter of course, every structure that may have a variable size should start with a length designator. Lengths 1 to 32767 take two bytes of a designator, 32768 to 2147483647 take four bytes, larger takes 8 bytes. Realistically 62 bits should suffice for any practical case, but arbitrary-size integers are well-known, and are easy to unpack and operate on.

This may slightly increase the size of some structures, but most of the time it would not, because of the alignment padding inherent to most structures anyway. But an entire class of vulnerabilities would be gone. This doesn't even need a change in the language, even though direct syntactic support would be nice. It just takes discipline when designing APIs.

Re: Some C habits I employ for the modern day

#130

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…

As I see it, the problem with languages trying to replace C is that they not only try to fix fundamental flaws, but feel compelled to add unneeded features and break C's simplicity.

C is a simple language, but that simplicity leads to non-portable code and lots of klunky, ugly things like using the preprocessor as a substitute for conditional compilation, imports, lambdas, metaprogramming, etc.

You don't have to use unneeded features that are in D. The core language is as simple as C, to the point where it is easy to translate C to D (in fact, the compiler will do it for you!).

Post reply on HN