Live data from Hacker News

Obvious things C should do

digitalmars.com

91–100 of 310 posts

Re: Obvious things C should do

#91

Earlier quoted context omitted.

How does it break the C Standard? > how to deal with functions that may not terminate or take rather long to execute Control-C, the same as when running any executable that shouldn't be taking that long. It doesn't solve the halting problem :-/

So a single typo DDoSes the entire Red Hat buildbot fleet?

You set a timeout, like in any robust CI.

Re: Obvious things C should do

#92

Header files are one of the things I miss the most about languages that aren't C. Having a very clear distinction between public and private, and interface and implementation is one of my favourite things about C code (at least the way I write it). Being able to just read through a library's .h files to know how to use it is really nice. Typically, my .h files don't really look like my .c files because all the docume…

I don't really program in C much so please correct me if I am wrong. There is a flaw in header files in that they work the exact same for dynamic vs static linking, right? If I am making a library in C for static linking, I need to put my internal details in the header file if I want the user's compiler to be able to use those details. But putting them in the header files also means they are part of the public interf…

That is less about header files, and more about how machine code works.

If you want to have some abstract type where you don't let people know anything about the innards, but you do have an explicit interface which enumerates what you can do with it, then yes - you can only really pass around pointers to these things and people outside your abstraction can only pass references not values.

If you want people to be able to pass your abstract type by value (among other things), then either you need to let them know how big the thing is (an implementation detail) or you have to expose the copy implementation in such a way that it could be inlined (more implementation details).

Sometimes, the "pure abstraction" approach is best where you only ever deal with pointers to things, and other times the "let's pretend that people do the right thing" approach is best. I don't see this as a header file thing though.

Re: Obvious things C should do

#93
post #79

I write unit tests for my C code all that time. It's not difficult if you use a good build system and if you are willing to stomach some boilerplate. Here is one test from my "test suite" for my npy library: void test_load_uint8() { npy_arr *arr = npy_load("tests/npy/uint8.npy"); assert(arr->n_dims == 1); assert(arr->dims[0] == 100); assert(arr->type == 'u'); npy_free(arr); } int main(int argc, char *argv[]) { PRINT_…

You will be pleased to know that you are not the only one who does this.

I previously went down the rabbit hole of fancy unit test frameworks, and after a while I realised that they didn't really win much and settled on something almost identical to what you have (my PRINT_RUN macro has a different name, and requires the () to be passed in - and I only ever write it if the time to run all the tests is more than a second or so, just to make it really convenient to point the finger of blame).

The thing that I do which are potentially looked upon poorly by other people are:

1) I will happily #include a .c file that is being unit tested so I can call static functions in it (I will only #include a single .c file)

2) I do a tiny preprocessor dance before I #include to make sure NDEBUG is not defined (in case someone builds in a "release mode" which disables asserts)

Re: Obvious things C should do

#94
Compile time unit tests are as bad of an idea as "unused import/variable/result" errors (rather than warnings). They're "nanny features" that take control away from the developer and inevitably cause you to jump through bureaucratic hoops just to get your work done.

These kinds of build-failing tests are great for your "I think I'm finished now" build, but not for your "I'm in the middle of something" builds (which are what 99% of your builds are).

It's like saying "You can't use the table saw until you put the drill away!"

Re: Obvious things C should do

#95
post #57

Earlier quoted context omitted.

Thanks for taking the time to respond! I have a few followup questions if thats ok: > You are correct in that the source code to the function being evaluated must be available to the compiler. This can be done with #include. I do it in D with importing the modules with the needed code. > D's strategy is to separate the parse from the semantic analysis. I suppose it is a hair slower, but it also doesn't have to recomp…

> Is a translation unit the same as in C, but since you're #including the file you would expect multiple compilations of a re-included C file? woudnt this bloat the resulting executable (/ bundle in case of a library) I think the idea is that compiling a translation unit produces two outputs, the object code (as it currently does), and an intermediate representation of the exported declarations, that could be basical…

> This is trivial if your build system detects changes based on content (like, say, bazel), but if it uses timestamps (like make) then the compiler needs to ensure the timestamp isn't updated when the declarations don't change.

This is where the traditional distinction of "compiler vs Make" makes things harder; you want dependencies tracked at the "declaration" level, rather than the file level. If the timestamp _and_ content of the exported declarations file change, but none of the _used_ declarations changed, then there's no more compilation to be done. At best with file level tracking your build system will invoke the compiler for every downstream dependency, and they can decide if there's any more work to be done.

The build system would need to know which declarations are used (and what a declaration is) to do better.

Re: Obvious things C should do

#96
post #74

Earlier quoted context omitted.

> identifiers in the body of a function aren't resolved until the function itself is executed (if ever) and at the point everything in the module scope has been defined Yes, so within a function you can refer to things that are defined later in the module. Isn't that's a "forward reference", even if the details are slightly different from how they work in D?

[flagged]

You're right, it's not the same mechanism. But in this particular context it has the same effect - it allows you to define functions in a source file in arbitrary order.

Re: Obvious things C should do

#97

Earlier quoted context omitted.

I don't really program in C much so please correct me if I am wrong. There is a flaw in header files in that they work the exact same for dynamic vs static linking, right? If I am making a library in C for static linking, I need to put my internal details in the header file if I want the user's compiler to be able to use those details. But putting them in the header files also means they are part of the public interf…

That is less about header files, and more about how machine code works. If you want to have some abstract type where you don't let people know anything about the innards, but you do have an explicit interface which enumerates what you can do with it, then yes - you can only really pass around pointers to these things and people outside your abstraction can only pass references not values. If you want people to be abl…

I disagree with you on this. In another language with explicit public / private separation, the compiler can have access to the internal layout of a type (and thus optimise on it) without letting the developer mess around with it directly. I am assuming static compilation of course. Across a dynamic boundary, I would expect this compiler to behave like a normal C compiler and not use that layout.

In a header file, the information for the compiler and the user are the exact same which means you can't reduce your public interface without straight up hiding more of yourself.

Re: Obvious things C should do

#98
post #35

> Evaluating Constant Expressions The examples are quite simple in the article but I believe more complex cases would significantly degrade the compiler speed (and probably the memory footprint as well) and would require a VM to leverage this. Which is probably assumed "too complex" to go into the standard. I'm not saying it's impossible, but I kind of understand why this would not go into any kind of standard. > Imp…

> I believe more complex cases would significantly degrade the compiler speed (and probably the memory footprint as well) and would require a VM to leverage this.

I'm pretty sure most production grade c compilers already do some level of compiler time evaluation for optimization. And C already has constant expressions.

I think a bigger hurdle would be that the compiler needs access to the source code of the function, so it would probably be restricted to functions in the same translation unit.

And then there is the possibly even bigger people problem of getting a committee with representives from multiple compilers to agree on the semantics of such constant evaluation.

Re: Obvious things C should do

#99

Header files are one of the things I miss the most about languages that aren't C. Having a very clear distinction between public and private, and interface and implementation is one of my favourite things about C code (at least the way I write it). Being able to just read through a library's .h files to know how to use it is really nice. Typically, my .h files don't really look like my .c files because all the docume…

> Header files are one of the things I miss the most about languages that aren't C. Having a very clear distinction between public and private, and interface and implementation is one of my favourite things about C code (at least the way I write it).

I always found this argument baffling, because the way some other language solve this problem is with tooling, which is a much better way to do it in my opinion.

Take Rust for example. You want to see the interface of a given library and see how to use it? Easy. Type in `cargo doc --open` and you're done. You get a nice interface with fully searchable API interface with the whole public API, and it's all automatic, and you don't have to manually maintain it nor have to duplicate code between your header and your source file.

Re: Obvious things C should do

#100
post #79

I write unit tests for my C code all that time. It's not difficult if you use a good build system and if you are willing to stomach some boilerplate. Here is one test from my "test suite" for my npy library: void test_load_uint8() { npy_arr *arr = npy_load("tests/npy/uint8.npy"); assert(arr->n_dims == 1); assert(arr->dims[0] == 100); assert(arr->type == 'u'); npy_free(arr); } int main(int argc, char *argv[]) { PRINT_…

Your function looks like it's doing I/O, which won't work at compile time test. Here's an example of a unittest for the ImportC compiler:

    struct S22079
    {
        int a, b, c;
    };

    _Static_assert(sizeof(struct S22079){1,2,3} == sizeof(int)*3, "ok");
    _Static_assert(sizeof(struct S22079){1,2,3}.a == sizeof(int), "ok");
The semantics are checked at compile time, so no need to link & run. With the large volume of tests, this speeds things up considerably. The faster the test suite runs, the more productive I am.
Post reply on HN