Archive for the 'C' Category

Parsing the preprocessor

Thursday, June 15th, 2006

If you’ve ever run GCC’s preprocessor alone and looked at its output, you’ve seen lines like these:

# 1 "/usr/include/sys/types.h"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "/usr/include/sys/types.h"
# 66 "/usr/include/sys/types.h"
# 1 "/usr/include/sys/appleapiopts.h" 1 3 4
# 67 "/usr/include/sys/types.h" 2


# 1 "/usr/include/sys/cdefs.h" 1 3 4
# 70 "/usr/include/sys/types.h" 2

And you probably wondered what all that means. Here’s your secret decoder ring.

First, these are called “line markers” in libcpp. The format of a line marker is:

  1. A line number
  2. The path to the relevant file
  3. Flags

The flag values are:

1
Push (enter) header
2
Pop (leave) header
3
This is a system header (determined by these rules with this modification)
4
Requires extern "C" protection (determined by the same rules as above); never found without 3

Note that a pop applies to the header above (in the include stack) the one referenced in the marker.

Example:

# 66 "/usr/include/sys/types.h"
# 1 "/usr/include/sys/appleapiopts.h" 1 3 4
# 67 "/usr/include/sys/types.h" 2
  1. Fast-forward to line 66 of <sys/types.h> (nothing interesting occurs before this line).
  2. Enter <sys/appleapiopts.h>. Everything from this point until the next marker is from that header. Note that this header is a system header (3) and requires extern “C” protection (4).
  3. As it turns out, nothing interesting happened there. So the very next line is a pop marker: <sys/appleapiopts.h> is popped, so now we’re back in <sys/types.h>, now on line 67 (the line after the #include <sys/appleapiopts.h>).

The relevant code in libcpp is in directives.c. The function that parses line markers (presumably used by the compiler rather than the preprocessor itself; the preprocessor generates them) is do_linemarker. Additional include-related code is in files.c.

UPDATE 23:24 PDT: Beware of pragmas. Seems obvious now, but I didn’t think of it earlier: The preprocessor leaves #pragma directives untouched, being that they’re for the compiler rather than the preprocessor. So if you’re only looking for line markers, you may get tripped up if you don’t properly handle/ignore a pragma.

Technorati tags: , , .

Within epsilon of perfect

Monday, March 27th, 2006

(Title taken from my own assessment of my spelling.)

It’s been known for awhile that rather than directly comparing two floating-point numbers, you should instead subtract the larger from the smaller and compare the difference to some epsilon value. The reason for this is that two numbers might be very very similar, but not exactly equal. “Epsilon” in a mathematical sense means “minimum precision that you care about”. The epsilon value for money, for example, is usually 0.01 — differences lower than this are thrown away.

So of course I went scrounging in the headers, found macros named FLT_EPSILON, DBL_EPSILON, LDBL_EPSILON, and recommended to all my programmer friends that they use these constants for comparisons of floating-point values rather than == and !=.

From time to time, facts just float up to the top of my head for no obvious reason. I have a sheet taped to my wall called “Word of the Day”; when a word pops into my head like this, completely unrelated to any previous thoughts, I write it down on that sheet to look up later. I consider this a more advanced (if slow) form of self-education. They might be long-forgotten memories, or something else; I don’t know, I just write them down and look them up.

About half an hour ago, this happened to me again. Except this time, the thought was definitely a memory, of something I’d read in float.h:

/* The difference between 1 and the least value greater than 1 that is
   representable in the given floating point type, b**1-p.  */

Another thought had bubbled up with this, and it was an epiphany: Technically, this means that the expression x != (x + FOO_EPSILON) should evaluate to 1. In other words, subtracting from FOO_EPSILON isn’t necessary.

So, as is my wont, I wrote a test app. Sure enough, that expression does evaluate to 1.

So forget what I said. x != y is directly equivalent to comparison against FOO_EPSILON, and it’s easier to read, too. So just use that.

Technorati tags: , .

Pointer talk 1.2

Thursday, January 19th, 2006

the new version of the pointer talk is live.

Declarators are fun! Part II

Sunday, January 8th, 2006

One more:

6.2.5[28]:

EXAMPLE 2 The type designated as “struct tag (*[5])(float)” has type “array of pointer to function returning struct tag”. The array has length five and the function has a single parameter of type float. Its type category is array.

Declarators are fun!

Saturday, January 7th, 2006

I was reading the C99 standard (because, you know, I’m Bored) and found a couple of interesting tidbits. Read on and see…

6.7.6[3]:

EXAMPLE The constructions

  1. int
  2. int *
  3. int *[3]
  4. int (*)[3]
  5. int (*)[*]
  6. int *()
  7. int (*)(void)
  8. int (*const [])(unsigned int, ...)

name respectively the types (a) int, (b) pointer to int, (c) array of three pointers to int, (d) pointer to an array of three ints, (e) pointer to a variable length array of an unspecified number of ints, (f) function with no parameter specification returning a pointer to int, (g) pointer to function with no parameters returning an int, and (h) array of an unspecified number of constant pointers to functions, each with one parameter that has type unsigned int and an unspecified number of other parameters, returning an int.

6.7.5.3[16]:

EXAMPLE 1 The declaration

int f(void), *fip(), (*pfi)();

declares a function f with no parameters returning an int, a function fip with no parameter specification returning a pointer to an int, and a pointer pfi to a function with no parameter specification returning an int. …

See also part II.

The pointer talk, version 1.1

Sunday, January 1st, 2006

Bigger and better. The old version is still available in a zip file, if you want it.

My home page, and the pointers tutorial

Thursday, December 22nd, 2005

As some of you know, I used to have a website, but when Colin‘s server ate its own hard disk, that went away. I still have the backups, fortunately, but you can’t get to those from the internet.

As some of you also know, I have a Yahoo! account.

As probably a lot of you know, Yahoo! bought GeoCities a long while back.

So for now, until I get some better hosting lined up (suggestions?), I’ve set up web space at GeoCities. The new Domain of the Bored. Yes, there’s nothing there yet.

Except for the ever-popular pointers tutorial.

Several times now, I’ve given people a one-on-one tutorial on the nature and care and feeding of pointers in C. This spiked this month, with me giving the talk twice. So I decided to write it up and make a webpage out of it.

Enjoy the pointer talk.

UPDATE 2006-08-27: Updated the pointer-tutorial link, though I (intentionally) left the GeoCities-homepage link alone. Also added a forward link to my blog post on hosting.