Gotcha (programming)

From Wikipedia, the free encyclopedia

In programming, a gotcha is a feature of a system, a program or a programming language that works in the way it is documented but is counter-intuitive and almost invites mistakes because it is both enticingly easy to invoke and completely unexpected and/or unreasonable in its outcome.

Contents

[edit] Gotchas in the C programing language

[edit] Equality operator

The classic gotcha in C is the fact that

if (a=b) code;

is syntactically valid and sometimes even correct. It puts the value of b into a and then executes code if a is non-zero. What the programmer probably meant was

if (a==b) code;

which executes code if a and b are equal. To avoid this gotcha, it is recommended to keep the constants in the left side of the comparison, i.e. 42 == meaning_of_life rather than meaning_of_life == 42.

[edit] Function calls

Example from computer languages such as C:

#include<stdio.h>
foo() {
   printf("42");
}
#if 0 
/* This function declaration is INCORRECT. There have to be parentheses.
 * If you want to see the compiler error message, please remove the whole #if and #endif lines
 */
bar {
}
#endif
main() {
    foo; /* does NOTHING, it just gets the address of the function foo and does nothing with it. */
    foo(); /* prints 42 */
}

[edit] Gotchas in the C++ programing language

[edit] Initializer lists

In C++, it is the order of the class inheritance and of the member variables that determine the initialization order, not the order of an initializer list:

#include <iostream>
 
class CSomeClass
{
 public:
  CSomeClass(int n)
  {
   std::cout << "CSomeClass constructor with value ";
   std::cout << n << std::endl;
  }
};
 
class CSomeOtherClass
{
 public:
  CSomeOtherClass() //In this example, despite the list order,
  : obj2(2), obj1(1) //obj1 will be initialized before obj2.
  {
   //Do nothing.
  }
 private:
  CSomeClass obj1;
  CSomeClass obj2;
};
 
int main(void)
{
 CSomeOtherClass obj;
 return 0;
}

[edit] Gotchas in Ruby programing language

[edit] Iterating Range

Ruby has a data type called Range; an object of this type constitutes a set of everything between the start and end of the range (including or not including the limits, depending on additional conditions). Since Range is a subclass of Enumerable, one would intuitively expect that iterating a valid Range object will give you every single object in that set, from start to end. This expectation turns out to be incorrect:

irb(main):001:0> (1..3).each { |i| puts i }
1
2
3
=> 1..3
irb(main):002:0> (3..1).each { |i| puts i }
=> 3..1
irb(main):003:0>

[edit] Returns from the block

return statement returns from the context it was defined in, not from the context it's currently executed in. For example:

def boo()
  transaction do
    ...
    return if(something)
    ...
  end
end

One might expect that return would allow the transaction to be properly closed, but unfortunately that's not the case -- the code in transaction() taking care of that will never be executed if something=true.

[edit] External links

Look up gotcha in
Wiktionary, the free dictionary.