In many languages, when you are unsure of a particular detail of the language, you can often “just run it” and see what happens. This might work in another language, but in C this will almost certainly bite you. It’s too easy to to accidentally invoke “undefined behavior”, where your code might do one thing in one case, but something totally different in another, without even getting a warning from the compiler. Here are a few undefined behaviors you might not know about, along with the relevant section from the C99 spec. These aren’t just pedantic ramblings; they’re all cases that I’ve encountered on real projects out in the wild. 1. Integer Division by -1Pretty much ever C programmer knows they should avoid dividing by zero. But there is another case where division is undefined: Give it a try! :)
On most implementations, this will result in the same kind of error/exception as divide by zero. But remember, this is not an “error” it is “undefined behavior”! The runtime is just being polite when it throws the error. It really could do anything it wanted (return 0, exit silently, scream, make make demons fly out of your nose) and still be fully compliant with the C spec.
2. Upcasting PointersCasting a Actually its only undefined if your Even though these casts are undefined, most C compilers will let you get away with them for most cases. But in certain cases at higher optimization levels, you’ll probably start seeing crashes. And they’ll be weird things, like “that function works great on even elements of an array, but crashes on the odd ones.” What happens is that, because casting from a pointer of weaker alignment is undefined, the compiler will just trust that we are not doing that and use an instruction that is much faster, but requires stronger alignment. And then when you don’t pass in a properly aligned pointer, the CPU itself will throw an exception, and your program will probably crash. (Again this is all “undefined,” but this is just what happens in common implementations.) In gcc and clang, there’s a command line option that will help point these types of errors out:
Note, that you don’t even have to dereference the pointer to stumble into undefined behavior. The actual conversion is undefined. 3. Using Uninitialized VariablesThe usual assumption is that it’s only the value from an uninitialized variable that’s undefined. But actually just using the value from an uninitialized variable is undefined. For example, given something like this:
On some compilers on some optimization levels, you can get the output:
There is an excellent breakdown of why you might get this sort of behavior here
4. Dereferenceing a Null PointerPeople don’t usually think of dereferencing a null pointer as undefined behavior. They usually think of it as “causes a crash”. This is not always the case. For example, on my current project, if I dereference a null pointer, I just get the value stored in address 0. You don’t realize how awesome segfaults are until you work on a system that doesn’t have them.
|
|
来自: astrotycoon > 《C》