Live data from Hacker News

Some dark corners of C

docs.google.com

91–100 of 175 posts

Re: Some dark corners of C

#91
post #49

Earlier quoted context omitted.

The preprocessor is a part of the standardized translation process, and if the standard says that certain things are not allowed in a well-formed C program, it does not matter at which stage the compiler is.

I'd be glad if you can pinpoint the location in the C standard where this constraint is given.

C99 Section 7.1.2.4 (on standard headers): "The program shall not have any macros with names lexically identical to keywords currently defined prior to the inclusion."

You can redefine keywords in your code, but they must not be defined when including standard headers (for obvious reasons).

Re: Some dark corners of C

#92
"What would be the smallest C program that will compile and link?"

Author got this wrong, that would be an empty file, which is what won the IOCCC for smallest self-replicating program once.

Re: Some dark corners of C

#93
post #47
post #30

Earlier quoted context omitted.

It replaces the first word with what comes after. For example, #define foo bar is roughly equivalent to s/foo/bar/g, so #define else would just remove all else keywords. I'll let you guess what it does to a program.

Not to forget #define struct union which will pack all struct members together. Gives me chills even to think about it...

The #define else one is scarier to me. #define struct union will almost certainly crash immediately on runtime, as one member's a pointer and it gets overwritten by an int or a pointer to a different type. #define else just always runs all else clauses - the code is likely still valid, it just does something very different from what the author intended.

Both of them would be a real pain to debug.

Re: Some dark corners of C

#94
post #5
post #3

#define struct union #define else That's evil. I have to do it in someone's code some day just to have some fun. But, apart from that, it's a really nice compilation. I didn't know about the compile time checks of array sizes, but I have a doubt. What if I pass to a method declared int foo(int x[static 10]) this pointer int* x = (int*) calloc(20, sizeof(int)); Does the compiler skip the check? Does it give me a warni…

Last time this came up on HN, it was thought to be a clang feature. Edit: While we're talking about dark corners, please stop casting functions that return void * . If your code lacks the declaration of the function, the compiler will assume pre ANSI-C semantics and generate code returning an int . On machines where pointers do not fit ints (basically all 64bit machines), you just silently (due to the cast there is n…

"On machines where pointers do not fit ints (basically all 64bit machines), you just silently (due to the cast there is no warning) truncated a pointer. Worse, it may work depending on the malloc implementation and how much memory you allocate."

Wow! Ugly! Scary! Another good reason to know in fine details just what cast does. At one point, my Visual Basic .NET code actually calls some old C code, and in time I will need to convert to 64 bit addressing. So, I will keep in mind that with 64 bits I have to be especially careful about pointers and C.

Re: Some dark corners of C

#95
post #94
post #5

Earlier quoted context omitted.

Last time this came up on HN, it was thought to be a clang feature. Edit: While we're talking about dark corners, please stop casting functions that return void * . If your code lacks the declaration of the function, the compiler will assume pre ANSI-C semantics and generate code returning an int . On machines where pointers do not fit ints (basically all 64bit machines), you just silently (due to the cast there is n…

"On machines where pointers do not fit ints (basically all 64bit machines), you just silently (due to the cast there is no warning) truncated a pointer. Worse, it may work depending on the malloc implementation and how much memory you allocate." Wow! Ugly! Scary! Another good reason to know in fine details just what cast does. At one point, my Visual Basic .NET code actually calls some old C code, and in time I will…

Well, the bug only appears if you didn't include the header file declaring malloc (or any other void*-returning function). If you did, there's no problem.

It's a pretty easy thing to leave out, missing a required header, but if you always compile under -Wall it'll catch this and many other problems as well.

Re: Some dark corners of C

#96
post #79

For "dark corners of C", when I was writing C code I had several serious concerns. Below I list eight such in roughly descending order on 'seriousness': First, what are malloc() and free() doing? That is, what are the details, all the details and exactly how they work? It was easy enough to read K&R, see how malloc() and free() were supposed to be used, and to use them, but even if they worked perfectly I was unsure…

I think C might make more sense if you are more familiar with assembly language. I learned C because real-mode x86 looked so fantastically ugly (looking back, a rare instance of youthful good taste). 0-terminated strings and stack allocation were quite familiar to me (though I never used stack allocation myself because it made the disassembly hard to read) and the overall model made perfect sense.

Re: Some dark corners of C

#99
post #9

I remember when the Pentium F00F bug was reported, I tested it by doing: char main[] = { 0xf0, 0x0f, 0xc7, 0xc8, 0xc3 }; (and yes, my machine -- a Pentium MMX -- hung solid and I was rather shocked!)

whoah - I find that construction astonishing. My gcc compiles it with only this warning: foo.c:2:6: warning: ‘main’ is usually a function [-Wmain] hah!

It won't execute though:

    [23] .got.plt          PROGBITS        0804954c 00054c 000014 04  WA  0   0  4
    [24] .data             PROGBITS        08049560 000560 000010 00  WA  0   0  4  
The main symbol is a relocation in .data, not .text. Which is as you would expect given that declaration. You might be able to get around that by doing something like

    unsigned char code[] = { 0xf0, 0x0f, 0xc7, 0xc8, 0xc3 };

    int main(void)
    {
        ((void (*)())code)();
        return 0;
    }
But these days NX will usually ruin the fun.

Re: Some dark corners of C

#100

"What would be the smallest C program that will compile and link?" Author got this wrong, that would be an empty file, which is what won the IOCCC for smallest self-replicating program once.

That is one of the finest examples of being technically correct--the best kind of correct. Spec is fulfilled but everybody knows the answer is useless.
Post reply on HN