syntax highlight

Monday 29 March 2010

Operator sizeof (AKA Reading Berkeley's FM, take II)

Last time I told you about an evil snipet I found on Oracle Berkeley DB's manual:

  skey->size = sizeof((struct student_record *)pdata->data)->last_name;

And we concluded it's trying to... well, dereference a number. And yet it compiles. What the hell is going on there?

The answer here is in the subtleties of the sizeof operator. That's right, operator, not function. Plus is an operator. Less is an operator. * is a (unary) operator. sizeof is a unary operator too. The relevance of this is that operators can behave in more bizzare ways than functions do. In this case there's a difference between this two lines:

  MyClass x;
  int a = sizeof(MyClass);
  int b = sizeof(x);

A very subtle difference. Can you spot it? a and b will have the exact same value, rest assured. The difference is in the operator itself: sizeof MUST have parenthesis when applied to a type name, yet parenthesis are optional when applied to an instance of a datatype, so this code is legal:

  MyClass x;
  int a = sizeof(MyClass);
  int b = sizeof x;

Oh, wait, the fun doesn't stop there: sizeof also has bizarre precedence order, meaning it won't get applied as you expect it. So, this is valid too:

  struct MyClass { int y; } x;
  int b = sizeof x->y;

Can you see where we are going? Knowing that sizeof will be applied last lets you write something like this too:

  void *ptr = ...
  int b = sizeof((X*)ptr)->y;

Which means nothing else than "store in b the size of member y in struct X. It should be easy to see why BDB's example does compile, and why did I spend half an hour trying to understand the reason it compiled fine.

By using some more casts and a clever arangement of parenthesis you can come up with a great job security device.

Friday 26 March 2010

Reading Berkeley's FM

I got this from Oracle Berkely DB's FM:

  skey->size = sizeof((struct student_record *)pdata->data)->last_name;

Take a good look at that pice of code:

  a_number = sizeof((T*)pdata->data)->last_name;

Again:

  a_number = sizeof(Whatever)->field;

Wait a minute. typeof(sizeof(x)) == const unsigned int. Right? So, again:

  a_number = 42->field;

There's no way that first line can compile. Go and check it (in the example, not the last line please). I'll wait. Done? Yeap, I was surprised to, it does indeed compile. Mi first reaction towards this discovery went something like this:

What is going on there? It took me a while to figure out how evil Berkely 's manual can be. The answer next time.

Thursday 25 March 2010

I hate Berkeley

Polymorphism taken to 11:
SQL Term Oracle Berkeley DB Equivalent
Database Environment
Table Database
Tuple/row Key/data pair
Secondary index Secondary database

WTF ORACLE, WTF.

Tuesday 23 March 2010

You know you're a geek...

... when you try to log in to your homebanking account using admin:admin (*) (**)


(*) Alt take: a geek with weak passwords, yeah. My pin is 1234 and I'll never change it.

(**) Replace homebanking with gmail, linkedin and $LATEST_NETWORKING_FAD and you're most likely mental. (***)

(***) Replace mental with (*) to obtain a Moebious post.

/Delirious posting mode, deactivate!

Thursday 18 March 2010

Cofeeeeeee


int main() {
	otl_connect db;
	otl_connect::otl_initialize();
	db.rlogon("whatever");

	int cuarentaydos;
	const char *sql = "select 42 drom dual";
	otl_stream stmt(1, sql, db);

	if (!stmt.eof()) stmt >> cuarentaydos;
	std::cout << "En la base 42 == " << cuarentaydos << "n";
	db.logoff();
}

I spent half an hour looking for the error. How come drom is not a standard sql keyword? Damn!