11 comments

[ 3.6 ms ] story [ 39.9 ms ] thread
The problem outlined in this post is explained in chapter 2 of K&R. I sympathize with the author and I agree it's insidious but it's also a rudimentary and well known snag.
"Problem" 1 is also well-known behavior for people who actually bother to learn it properly. C being such small language, there is almost no excuse for not learning it properly if you deal with it daily. Also, some C compilers warn about signed/unsigned comparisons.

Some background on the signedness problem: http://yarchive.net/comp/ansic_broken_unsigned.html

The 2nd behavior is useful in macros, which sometimes need to do compile-time string concatenation (that might even be why it exists?).
Thanks to apple we have a compiler alternative, that actually helps with this problem.

  alistra@bialobrewy ~ % clang -Weverything 1.c
  1.c:6:8: warning: comparison of integers of different signs: 'int' and 'unsigned int' [-Wsign-compare]
          if(-1 < x)
             ~~ ^ ~
gcc also has -Wsign-compare option that warns about such comparisons.
GCC prints a similar warning with `-Wall`
actually with -Wextra

  alistra@bialobrewy ~ % gcc -Wextra 1.c
  1.c: In function ‘main’:
  1.c:6:8: warning: comparison between signed and unsigned integer expressions
  alistra@bialobrewy ~ % gcc -Wall 1.c  
  alistra@bialobrewy ~ %
Yes, for some reason in gcc, -Wall enables -Wsign-compare in C++ mode, but not in C mode. Maybe too much existing C code uses those kinds of comparisons?
The fact the code uses those kinds of comparisons, doesn't mean, that it uses it properly.
In example two there is no \0 that is being removed by the compiler to do the concatenation. In the C language this is perfectly valid:

  "Testing something" ": more";

  "Testing something"
  ": more";
This is still only considered one string, whether there are newlines in between or not. The translation unit is from the last semicolon to the next semicolon (overly simplified), so the compiler see this:

  "Testing something"": more";
Now it sees that there is no operator between the two "strings" and simply makes them a single string.
The output of "Problem 1" can actually be "yes", depending on the architecture. -1 is "all bits set" on two's complement signed integers but that's not the only integer encoding in existence. If you want "all bits set", write ~0. That's exactly all bits set and defined behaviour you can rely on in a portable program as opposed to an implementation detail.