As remarked in the comments, the macro definition you present does not expand to valid C code because it involves computing (char*)0 % sizeof(long)
, where the left-hand operand of the %
has type char *
. That is not an integer type, but both operands of %
are required to have integer type.
Additionally, the macro's expansion has unbalanced parentheses. That's not inherently wrong, but it makes that macro tricky to use. Furthermore, even where operator precedence yields a sensible result, usage of parentheses and extra whitespace can aid human interpretation of the code, at no penalty to execution speed, and negligible extra compilation cost.
So, I think the desired macro would be more like this:
#define SWAPINT(a,es) swaptype = ( \
((((char*)a - (char*)0) % sizeof(long)) || (es % sizeof(long))) \
? 2 \
: ((es == sizeof(long)) ? 0 : 1)) \
)
I'd consider instead writing the penultimate line as
: (es != sizeof(long))
to reduce the complexity of the expression at a slight cost to its comprehensibility. In any event, the intent appears to be to set swaptype
to:
2
if a
is not aligned on an n
-byte boundary, where n
is the number of bytes in a long
, or if es
is not an integer multiple of the size of a long
; otherwise
1
if es
is unequal to the size of a long
; otherwise
0
That's similar, but not identical, to your interpretation. Note, however, that even this code has undefined behavior because of (char*)a - (char*)0
. Evaluating that difference has defined behavior only if both pointers point into, or just past the end of, the same object, and (char *)0
does not point (in)to or just past the end of any object.
You asked specifically:
But I don't understand why type conversion is implemented, (char*)a.
That is performed because pointer arithmetic is defined in terms of the pointed-to type, so (1), a conforming program cannot perform arithmetic with a void *
, and (2) the code wants the result of the subtraction to be in the same units as the result of the sizeof
operator (bytes).
And what means of this line?
(char*)a- (char*)0)% sizeof(long)==1
That line does not appear in the macro you presented, and it is not a complete expression because of unbalanced parentheses. It appears to be trying to determine whether a
points one past an n
-byte boundary, where n
is as defined above, but again, evaluating the pointer difference has undefined behavior. Note also that for an integer x
, x % sizeof(long) == 1
evaluated in boolean context has different meaning than x % sizeof(long)
evaluated in the same context. The latter makes more sense in the context you described.