5

I have following c code:

#define ASSERT_ACTIVE(active) do { if (!active) return errno = 6, -1; } while (0);
#define errno (*_errno())

int someCrazyFunc (bool active) {
    ASSERT_INACTIVE (active);
    ...
}

As far as I know a #define will simply place replacement text in place of the specified identifier.

I like to know:

  • What does return errno = 6, -1; means? is that returns two values in one return statement?
  • What is the meaning of replacement code (*_errno()) = 6
AaA
  • 3,600
  • 8
  • 61
  • 86
  • @Mysticial I agree and I hate it, but it is part of code that passed to me to debug! :'( – AaA Oct 24 '12 at 02:13
  • I think this is a most lovely construct. Would not use it in production code because it is too difficult and out of the norms however it is quite nice. Unless _errno() returns a bad pointer in which case it could be most embarrassing! – Richard Chambers Oct 24 '12 at 02:20
  • 1
    That said, there are better (more readable) ways to write this macro... – Mysticial Oct 24 '12 at 02:27
  • Note that including the trailing `;` in the definition of `ASSERT_ACTIVE` renders the `do {} while(0)` construct ineffective. – caf Oct 24 '12 at 02:51
  • @RichardChambers, it might be a lovely construct, but as far as it does not have a productive use as you call it, I don't like it at all, it supposed to increase readability of code, but so far it reduces it. – AaA Oct 24 '12 at 03:30

2 Answers2

9

There isn't a second value - a return statement returns exactly one value. In the statement:

return errno = 6, -1;

The return value is the result of the expression errno = 6, -1. This is an expression using the comma operator - it is parsed as (errno = 6), -1, which evaluates to -1 and assigns 6 to errno as a side-effect. So this means that it's equivalent to the two statements:

errno = 6;
return -1;

Assuming that _errno() is a function returning a pointer - for example it has a return type of int * - then the expression (*_errno()) = 6 assigns the value 6 to the object pointed to by the return value of the function. It would be equivalent to code similar to:

int *p = _errno();
*p = 6;

errno is often defined like this in order to give each thread in a multi-threaded implementation its own errno. The function _errno() in this case would return a pointer to the current thread's errno variable.

caf
  • 233,326
  • 40
  • 323
  • 462
1

That is not actually a second value to the return statement, it's the comma operator. What it does is to evaluate the expressions on both sides of the comma, but "return" only the value of the second expression.

So what return errno = 6, -1; does is evaluate the expressions errno = 6 and -1 separately and then give back the result of the second expression -1, which will then be used by return.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621