2018-03-27

At work, I've been stuck doing ops stuff lately (mind numbingly boring), so, I've been following along with bitwise, and today I actually learned some new C things, making today not a complete waste. One of them is a C99 thing; admittedly, I haven't done much C99 in my time. The other relates to unions, which I also haven't done much with --- I've never really had much use for them. The finally is a way to print non-NULL terminated C strings (aka substrings).

C99 variadic macros

One thing Per does in bitwise is define tests that just get run all the time. When I'm working on the development side of things, I want these to display some output, but in a release build, I don't want them to display anything. I also don't want to set the NDEBUG flag, neutering assertions so I've got something like the following:

#ifndef RELEASE
#define tprint(...) do { fprintf(stderr, __VA_ARGS__); } while (false)
#else
#define tprint(...) do {} while (false)
#endif

In a function, I might have

uint64_t
that_thing(uint64_t val)
{
    return val;
}


static void
test_that_thing(void)
{
    uint64  x = 0;

    tprint("test_that_thing\n");
    x = that_thing(47);
    assert(x == 47);
    tprint("x = %lu", (long unsigned)x);
    tprint("OK\n");
}

int
main(int argc, char *argv[])
{
    test_that_thing();

    // normal program stuff
}

I've got my all target set to:

.PHONY: all
all: $(TARGET)
    ./$(TARGET)

and then I run a watch make in a terminal. Works pretty well, and the resulting program keeps its self-checks baked in.

Unions and anonymous structs

I also learned that you can use a union with an anonymous struct to add fields to a struct:

struct Thing {
    int type;
    union {
        uint64_t    val;
        struct {
            int start;
            int end;
        };
    };
};

Substrings

Printing a substring is done with:

/* substr.c */
#include <stdio.h>

int
main(void)
{
    char buf[] = "hello, world!";
    printf("%.*s\n", (int)4, buf+1);
}

Building and running this:

$ make substr
cc     substr.c   -o substr
$ ./substr
ello

This is really useful; I don't know how I never knew about it!


Tags: