Live data from Hacker News

C puzzles

gowrikumar.com

51–60 of 97 posts

Re: C puzzles

#51
post #22

Earlier quoted context omitted.

Huh??? Can you please elaborate on that? Because that makes no sense to me at all.

If all { and } are on their own lines, then it modestly simplifies the ability to visually scan from one to its match because they appear on the same column with nothing between them.

But if your code is properly indented then you can do the same thing with the first character in the line containing the open brace:

    if (foo) {
    |   blah;
    |   blah;
    |   blah;
    |   blah;
    |   blah;
    |   blah;
    |   blah;
    |   blah;
    |   blah;
    }

Re: C puzzles

#52
post #14

Earlier quoted context omitted.

There's no #include first, so you get an implicit prototype for malloc. With an implicit prototype, the function is assumed to return int. The cast then converts the returned int to int*. This works on 32-bit where int is the size of a pointer, but on 64-bit with 32-bit ints, the top half of the pointer gets chopped off and you end up with a nonsense value. This is why it's considered bad form to cast the result of m…

Oh so he meant to say Intel 64/amd64. IA-64 is Intel Itanium. I just skipped it because I know nothing about IA-64 at all.

He might have meant IA-64. The problem is likely to appear on any 64-bit architecture where int is smaller than a pointer, which is most (or all?) of them. Depending on the compiler and such, big discussion below if you're interested in boring details.

Re: C puzzles

#53

That IA-64 one is really puzzling, anyone know what the heck is happening?

It didn't work (as in crash) for me:

  % uname -a
  FreeBSD 10.1-RELEASE FreeBSD 10.1-RELEASE #0 r274401: Tue Nov 11 21:02:49 UTC 2014     root@releng1.nyi.freebsd.org:/usr/obj/usr/src/sys/GENERIC  amd64
  % gcc -o foo foo.c
  foo.c: In function 'main':
  foo.c:4:17: warning: incompatible implicit declaration of built-in function 'malloc' [enabled by default]
       p = (int*)malloc(sizeof(int));                 ^
  % ./foo
  %
This is with GCC 4.8.5

Re: C puzzles

#54

I really dislike his choice of coding style. Compare: int CountBits (unsigned int x ) { static unsigned int mask[] = { 0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF } ; int i ; int shift ; /* Number of positions to shift to right*/ for ( i =0, shift =1; i > shift) & mask[i]); return x; } as opposed to: int countBits (unsigned int x) { static unsigned int mask[] = { 0x55555555, 0x33333333, 0x0F0F0F0F, 0x0…

Arguing about style?

I really thought that as a species we had decided it was a preference thing.

Re: C puzzles

#55
post #14

That IA-64 one is really puzzling, anyone know what the heck is happening?

There's no #include first, so you get an implicit prototype for malloc. With an implicit prototype, the function is assumed to return int. The cast then converts the returned int to int*. This works on 32-bit where int is the size of a pointer, but on 64-bit with 32-bit ints, the top half of the pointer gets chopped off and you end up with a nonsense value. This is why it's considered bad form to cast the result of m…

Close. Sign extension. But this is a C puzzle, so I'd get away with "undefined behaviour".

Re: C puzzles

#56
post #33
post #28

Earlier quoted context omitted.

Do you mean that the cast in the code gets compiled out?

No. The int to int * truncation does not happen, the cast does not matter. What matters is the `int *p' which is 64-bit on 64-bit systems, so the compiler will just move the returned value in RAX into wherever p is, so no truncation happens, even without the cast. Look at the generated assembly, you'll see what I mean.

The question asks about IA-64 (Itanium) and IA-32. You're talking about the RAX register which is x86-64.

If you call malloc without a prototype in scope, bad things can happen. Just because it happens to work out OK with the platform and compiler that you tested doesn't mean that it will work everywhere or that it will keep working in the future.

Re: C puzzles

#57
post #50
post #49

Earlier quoted context omitted.

Doesn't happen for me. Both GCC and Clang compile it fine.

Strange. Here's my erroring code: int main() { int* p; p = (int*)wrapped_malloc(sizeof(int)); *p = 10; return 0; } void *wrapped_malloc(int size) { return malloc(size); } And the actual error: test.c:9:11: error: conflicting types for 'wrapped_malloc' void *wrapped_malloc(int size) { ^ test.c:4:19: note: previous implicit declaration is here p = (int*)wrapped_malloc(sizeof(int)); Are you doing anything differently?

Try putting wrapped_malloc above main. Or at least declaring it above main.

Re: C puzzles

#58

Fun stuff , thanks for posting it. I've been getting back into C lately, iterating through implementing common algorithms from scratch. In spite of the kinds of easy to make mistakes that are highlighted on the site, I'm finding it to be a lot of fun - not having my hand held by frameworks that try to stop me from shooting myself in a foot is refreshing and brings back that feeling of "I can build whatever the hell I…

You know, I have a love/hate relationship with C kind of like what you described. In general I hate how hard it is to use and how easy it is to make gigantic mistakes in it. But on the other hand it's so raw and pure that it makes it a fun challenge. Recently I decided to write a SNES-era video game in C using SDL2, so we'll see how that goes. Maybe my mind will change as I make progress on that front.

Re: C puzzles

#59
post #57
post #50

Earlier quoted context omitted.

Strange. Here's my erroring code: int main() { int* p; p = (int*)wrapped_malloc(sizeof(int)); *p = 10; return 0; } void *wrapped_malloc(int size) { return malloc(size); } And the actual error: test.c:9:11: error: conflicting types for 'wrapped_malloc' void *wrapped_malloc(int size) { ^ test.c:4:19: note: previous implicit declaration is here p = (int*)wrapped_malloc(sizeof(int)); Are you doing anything differently?

Try putting wrapped_malloc above main. Or at least declaring it above main.

If it's above main then there's no longer an implicit prototype and you're no longer replicating the problem.

Re: C puzzles

#60
post #55
post #14

Earlier quoted context omitted.

There's no #include first, so you get an implicit prototype for malloc. With an implicit prototype, the function is assumed to return int. The cast then converts the returned int to int*. This works on 32-bit where int is the size of a pointer, but on 64-bit with 32-bit ints, the top half of the pointer gets chopped off and you end up with a nonsense value. This is why it's considered bad form to cast the result of m…

Close. Sign extension. But this is a C puzzle, so I'd get away with "undefined behaviour".

Where does sign extension occur here?
Post reply on HN