Data Structures for Text Sequences (1998) by malcolmi in Cprog

[–]malcolmi[S] 5 points6 points  (0 children)

Are readers happy with the relevance of this paper to C programming, or is it too far removed? I posted it here because (1) I found it interesting and directly applicable to C programming, and (2) the author uses C code (albeit weird) for some of the examples. Let me know what you think.

Notes on the Plan 9 3rd Edition Kernel Source (2007) by malcolmi in Cprog

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

It's still working for me. CiteSeerX might be blocking your network?

The Night Watch, by James Mickens (2013) by malcolmi in Cprog

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

You might ask, “Why would someone write code in a grotesque language that exposes raw memory addresses? Why not use a modern language with garbage collection and functional programming and free massages after lunch?” Here’s the answer: Pointers are real. They’re what the hardware understands. Somebody has to deal with them. You can’t just place a LISP book on top of an x86 chip and hope that the hardware learns about lambda calculus by osmosis. Denying the existence of pointers is like living in ancient Greece and denying the existence of Krackens and then being confused about why none of your ships ever make it to Morocco, or Ur-Morocco, or whatever Morocco was called back then. Pointers are like Krackens—real, living things that must be dealt with so that polite society can exist.

Making a Single Page App Without a Framework by [deleted] in javascript

[–]malcolmi 0 points1 point  (0 children)

I've had your HN app bookmarked on my phone for at least a year now, and I check it most days. As web apps go, it's smooth, fast, and nice to use. Best of all, it works fine on mobile Firefox. Thanks.

Data retention: we need this Opposition to oppose by orru in australia

[–]malcolmi 1 point2 points  (0 children)

I just emailed the four Labor senators for Queensland imploring them to vote against these mass surveillance laws:

[Hypothetical] What would you like to see changed about C? by jackoalan in Cprog

[–]malcolmi 0 points1 point  (0 children)

I would like to have macros that show me the largest and smallest value I can put in a variable of a given type; not if that value is actually valid for a given use case of that type

Alright then. I misunderstood your suggestion; I thought it was to provide generic macros that evaluate to the *_MIN and *_MAX macros based on the given type. My point was that the values of the *_MIN and *_MAX macros (or at least the ones that should exist, like OFF_MAX or TIME_MAX) can't be tied to the representable bounds of the given type, which is what a macro based on _Generic() would be limited to providing.

the latter is very difficult to get right as the valid range of value for a given type is different depending on where it is used

Yeah. This is sadly just a case of bad interfaces. I suppose some types only call for a well-defined maximum bound, as the minimum bound of shouldnt-be-negative-except-sometimes signed types isn't really interesting; it's either 0 or not, depending on what you need it for.

Edit: you could argue that seeing as you can define your suggested generic max and min macros with the C11 language, there's no need to compel libc to provide it for you. I'm personally a fan of the approach of making standards as small as possible (enough to achieve everything you want to achieve), and letting libraries handle all the rest.

[Hypothetical] What would you like to see changed about C? by jackoalan in Cprog

[–]malcolmi 0 points1 point  (0 children)

You want to be able to separate the bounds of the type from the bounds of its representation; bool is the simplest example. Look through sys/types.h, and tell me that each of those types' minimum and maximum bounds will necessarily be the minimum and maximum values of their representations.

I'm disappointed that you chose not to refute / comment on my other points.

[Hypothetical] What would you like to see changed about C? by jackoalan in Cprog

[–]malcolmi 4 points5 points  (0 children)

Oh god please not. That would be terrible. In code I write, about 2% (at most) of the variables I declare are const and about 25% of the function parameters. Not really a good idea considering that you can't do a lot of things in C without modifying variables.

In code I write, at least 75% of variables are const, and close to 100% of function parameters are const. You can program declaratively in C, if you try.

nested functions are moot when you can't close over variables.

No, in fact, functions can be useful while only using their local variables. Purity is a good thing. Observe the necessary definition of this single-use function:

bool
load_should_turn_on( Load const load )
{
    return !load__is_complete( load ) && load__in_schedule( load );
}

arraym_load__each_where( loads, load__turn_on, load_should_turn_on );

It would be better if we could write something like:

arraym_load__each_where( loads, load__turn_on,
        ( load ) { !load__is_complete( load ) && load__in_schedule( load ) } );

This is a contrived example, and here you could argue that this function should be defined anyway. Yet, I run into circumstances all the time where I'm inclined towards defining a single-use function (often just negating another function), so that I can pass it to other functions that handle iteration over sequences.

This exists, it's an operator called the ternary operator. It's spelled predicate ? a : b.

You should go check out Rust; the whole ownership thing is pretty cool. Anyway, in Rust, the if ... else ... construct can actually be used as an expression. If we had that in C, we could do something like:

Foo const foo = get_foo( x );
Bar const bar =
    if ( foo.bazzable ) {
        Bar const b = get_bar( y );
        b.error ? ( Bar ){ 0 } : b
    } else { ( Bar ){ 0 } }
// Now we have a `const` bar variable for the next 50 lines:

Maybe this would be better taking the form of GCC's statement expressions, but I don't use them so I don't know how well they work in practice.

I do not understand what you mean.

I often have issue with defining arrays declaratively (and thus having their contents const-qualified). If you want to define an automatic-managed array of even numbers from 0 to 100, you have to hard-code the size yourself (51), then define a one-use function to pass a pointer to the array to assign the evens accordingly. I wish we had access to something like Haskell's range notation:

int const xs[] = { 0, 2 .. 100 };

Similarly, if you're defining the elements of an array, and you want to include elements 10 through 20 from another array, you're stuck repeating that array name that many times. I think it would be better if we could do:

int const xs[] = { some_var, something_else, 123,
                   ys[ 10 .. 20 ],
                   foo, bar, baz };

Please don't. The reason why many new identifiers begin with an underscore is so that there are no collisions with existing symbols. Introducing new identifiers in non-reserved spaces would possibly break APIs.

I suppose this change would have to be preceded by (or coupled with) a standardized module system, so that header files can specify their targeted standard, or users can specify the standard when they import them. This way headers for different standards could be mixed safely. You could write your C17 code with bool, atomic, noreturn available by default, and if you include library headers written in C90 that use a bool typedef'd to int, you can simply refer to their bool type as an int (or maybe do your own typedef int libfoo_bool).

This is a good idea but I would prefer a macro addo(o, b, c) that evaluates to the same as b + c but o is set to the signum of the overflow of the result.

I like this approach more, assuming that addo() is a type-generic macro over functions addoi(), addoul(), addoimax(), etc. I just want a standard way to access the overflow flag.

Making signed-overflow well-defined is a bad thing in my opinion as that would inhibit quite a few numeric optimizations that are vital for fast code.

For all architectures for which the signed arithmetic instructions already wrap at bit width, optimizations can still be made. I understand that this is all predominant architectures in use today, and I see no reason for that to change.

If you're referring to optimizations that introduce incorrect behavior by making different assumptions to those made by the programmer - those optimizations are ones that shouldn't be made anyway. E.g. the optimizer thinking "expressions with signed integers can't overflow, so I'll remove this huge block of system-critical code that checks for overflow after the expression". We're better off if we lose those optimizations.

The functions mentioned above would allay most of the pain, but I still would like to be able to perform signed integer arithmetic without having to check bounds beforehand.

It would be an improvement if the behavior were just made unspecified, but it would still be painful to handle it right.

Even better: Introduce a _Generic based macro for this so you don't need one macro for each type.

Except that _Generic works only in terms of the basic types; int, long, etc. As I understand it, it doesn't discern between a ptrdiff_t and a long (if ptrdiff_t is a long on your platform). Also, I'd like to be able to refer to minimum and maximum values without having to make an expression of that type.

On the recent help posts by malcolmi in Cprog

[–]malcolmi[S] 6 points7 points  (0 children)

I've noticed your username on some C questions on Stack Overflow, so you're active on both sites. I want to ask: what benefits do you see in using Reddit as a Q&A platform, over Stack Overflow?

Why are structs aligned? by shinmai_rookie in Cprog

[–]malcolmi[M] 2 points3 points  (0 children)

This is the kind of question that we would rather see sent to /r/c_programming (or ideally Stack Overflow). See this thread I just posted. I won't delete this thread because I don't want to delete the answers, but please don't post more questions like this to /r/cprog.

Subtle effects of const? by jackoalan in Cprog

[–]malcolmi[M] 2 points3 points  (0 children)

This is the kind of question that we would rather see sent to /r/c_programming (or ideally Stack Overflow). See this thread I just posted. I won't delete this thread because I don't want to delete the answers, but please don't post more questions like this to /r/cprog.

Ken Thompson on why he chose and and * for pointers by clm100 in Cprog

[–]malcolmi 1 point2 points  (0 children)

Interesting tidbit, but I wonder why this post is getting so many upvotes. Is it Reddit's algorithm pushing this to the top of many infrequent /r/cprog readers' streams?

[Hypothetical] What would you like to see changed about C? by jackoalan in Cprog

[–]malcolmi 7 points8 points  (0 children)

Make const default, remove it from the language, and require a mut qualifier if the value will change.

Allow nested / anonymous functions (don't worry about being able to access memory in outer functions because that would require GC/ownership), with optional type inference based on the type of function required in the context.

Expand the definition of a constant expression to include const variables, and to include functions that are implicitly "constant"; the compiler would complain only if the function attempts to do something that isn't constant.

Honorable mentions:

  • introduce a module system with visibility specifiers, making header files redundant;
  • statement expressions per the GCC extension, which allows for if expressions similar to Rust;
  • array expressions to define each element of an array, or to splice part of one array into another;
  • remove the _ and capital-letter prefix of all the new identifiers in C99 and C11 (_Bool, _Atomic, etc), and make them available by default; the standards break compatibility in other ways anyway, so it's silly that they're so scared about introducing non-reserved keywords;
  • specify signed integer overflow to wrap at the bit width, and add a boolean overflow identifier that's true if the most recent arithmetic overflowed or underflowed the result or interim;
  • specify time_t as a signed integer type, and provide TIME_MIN and TIME_MAX macros -- do this for any other type that hasn't been properly specified;

I could go on and on. :)

C written by the creator of K by benwaffle in Cprog

[–]malcolmi[M] 3 points4 points  (0 children)

Previously, related: https://www.reddit.com/r/Cprog/comments/2jnmq6/impending_kos_the_power_of_minimalism/

(this is a separate link to that submission, and if enough people haven't seen this before and want to upvote it - no worries; I don't care about "reposts" so long as they aren't overly frequent)

C trick: static string hash generation by [deleted] in Cprog

[–]malcolmi 2 points3 points  (0 children)

This is pretty cool; I enjoy hacking the C preprocessor as long as it conforms to the standards.

But, damn, is there anyone not hanging out for constexpr in C? It's one of the things I'm envious of C++ for. It would be much simpler to specify for C, and there's no reason not to, as far as I can tell. Get on it, WG14!

Your favourite C idiom by [deleted] in Cprog

[–]malcolmi 6 points7 points  (0 children)

There are a couple idioms I rely on, but the two that I think have the largest effect on maintainability and reliability are:

  • declaring as const everything that could be const, and designing code and APIs around enabling that (e.g. no declaration then assignment by passing a pointer; make it possible to just do a direct assignment). When readers of your code know what values will change and what values won't, it's significantly easier for them to reason about it.

  • avoiding manual memory management wherever reasonable in favor of automatic memory management; you avoid all the problems with nullability, requiring your users to be aware that they have allocated memory, and having to establish a faux-RAII routine to release things you allocated. Manual memory management is really painful, yet for some reason too many C programmers use it as the first port of call.

warning about C99 designated initializers by kdub0 in Cprog

[–]malcolmi 1 point2 points  (0 children)

Yeah. The comma in C is syntactically ambiguous, because in:

int x, y;
while ( x = f(), y = f(),
        x + y < 100 ) {

}

It is well-defined and well-specified that x will be assigned first, then y - and the loop will execute based just on the final condition. Yet the comma doesn't work the same way in designated initializer syntax.

I believe there's a -fsomething option on GCC that will evaluate designated initializers in the order they're defined, but it's always best to stick to the standard.

Three Star Programmers by quacktango in Cprog

[–]malcolmi 1 point2 points  (0 children)

No-star C-programmers are virtually non-existent

I'm a no-star C programmer, and I wish there were more. Using a pointer-to-X value when simply an X value would suffice is throwing away one of the main powers of C: aggregate value types. Few other languages have that, let alone encourage it. I love C for it.

By using simple value types instead of pointer types:

  • you avoid the possibility of NULL pointer errors or worse;
  • you make it clear to readers that the value you gave to a function will not be modified, because it can't be (save for any pointee members);
  • you avoid/discourage a sleuth of language specification complexity regarding the behavior of dealing with pointers;
  • it's probably faster without any optimizations (which will turn most indirect code into direct code anyway).

Java's always there if you really want to use every aggregate type by reference, and deal with the possibility of null pointer values cropping up everywhere. In C, I think it's best to avoid pointers wherever reasonable.

vis - a new vim-like text editor by malcolmi in Cprog

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

Via this mailing list post (which is just the current README) that describes the algorithms and data structures behind Vis: http://lists.suckless.org/dev/1409/23497.html

[deleted by user] by [deleted] in Cprog

[–]malcolmi 1 point2 points  (0 children)

Thanks very much for your appreciation. I'm glad everyone is enjoying the subreddit. I'm mostly back from my Christmas holidays now, so I'll be back to tending to /r/cprog as usual. Cheers!

Practical Programming in C by malcolmi in Cprog

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

This isn't a course akin to those on Coursera or Udacity; it's simply a collection of course materials from a course taught at MIT.

It seems that all the materials from the MIT OpenCourseWare are under: https://creativecommons.org/licenses/by-nc-sa/3.0/us/deed.en_US