Operators
The bitwise operators &, |, ^, and ~ operate on integers thought of as binary numbers or strings of bits. The & operator is bitwise AND, the | operator is bitwise OR, the ^ operator is bitwise exclusive-OR (XOR), and the ~ operator is a bitwise negation or complement. (&, |, and ^ are ``binary'' in that they take two operands; ~ is unary.) These operators let you work with the individual bits of a variable; one common use is to treat an integer as a set of single-bit flags. You might define the 3rd (2**2) bit as the ``verbose'' flag bit by defining#define VERBOSE 4Then you can ``turn the verbose bit on'' in an integer variable flags by executing
flags = flags | VERBOSE; or flags |= VERBOSE;and turn it off with
flags = flags & ~VERBOSE; or flags &= ~VERBOSE;and test whether it's set with
if(flags & VERBOSE)
The left-shift and right-shift operators << and >> let you shift an integer left or right by some number of bit positions; for example, value << 2 shifts value left by two bits.
The ?: or conditional operator (also called the ``ternary operator'') essentially lets you embed an if/then statement in an expression. The assignment
a = expr ? b : c;is roughly equivalent to
if(expr) a = b; else a = c;Since you can use ?: anywhere in an expression, it can do things that if/then can't, or that would be cumbersome with if/then. For example, the function call
f(a, b, c ? d : e);is roughly equivalent to
if(c) f(a, b, d); else f(a, b, e);(Exercise: what would the call
g(a, b, c ? d : e, h ? i : j, k);be equivalent to?)
The comma operator lets you put two separate expressions where one is required; the expressions are executed one after the other. The most common use for comma operators is when you want multiple variables controlling a for loop, for example:
for(i = 0, j = 10; i < j; i++, j--)
A cast operator allows you to explicitly force conversion of a value from one type to another. A cast consists of a type name in parentheses. For example, you could convert an int to a double by typing
int i = 10; double d; d = (double)i;(In this case, though, the cast is redundant, since this is a conversion that C would have performed for you automatically, i.e. if you'd just said d = i .) You use explicit casts in those circumstances where C does not do a needed conversion automatically. One example is division: if you're dividing two integers and you want a floating-point result, you must explicitly force at least one of the operands to floating-point, otherwise C will perform an integer division and will discard the remainder. The code
int i = 1, j = 2; double d = i / j;will set d to 0, but
d = (double)i / j;will set d to 0.5. You can also ``cast to void'' to explicitly indicate that you're ignoring a function's return value, as in
(void)fclose(fp);or
(void)printf("Hello, world!\n");(Usually, it's a bad idea to ignore return values, but in some cases it's essentially inevitable, and the (void) cast keeps some compilers from issuing warnings every time you ignore a value.)
There's a precise, mildly elaborate set of rules which C uses for converting values automatically, in the absence of explicit casts.
The . and -> operators let you access the members (components) of structures and unions.