Post

Let me C - Types, Operators, Expressions and Control Flow

Variable names

The conventions (not enforced, but expected)

  • Underscore-leading names are conventionally avoided in your own code. Names starting with _ are often used by library implementations for internal names (like _iob in old standard library headers).
  • Lowercase for variables, and reserve all-uppercase for symbolic constants (things defined via #define)
1
2
#define MAXLINE 1000
int lineCount;

Data Type and Sizes

TypeMeaning
chara single byte, holds one character in the local character set
intan integer, typically reflects the “natural” size of integers on the host machine
floatsingle-precision floating point
doubledouble-precision floating point

Qualifiers

You can modify int (and in older code, sometimes implicitly drop the word int itself) with:

1
2
3
4
short int x;      // often written just "short x;"
long int count;   // often written just "long count;"
unsigned int u;
unsigned long bignum;

Example

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int main(void)
{
    printf("char: %zu bytes\n", sizeof(char));
    printf("short: %zu bytes\n", sizeof(short));
    printf("int: %zu bytes\n", sizeof(int));
    printf("long: %zu bytes\n", sizeof(long));
    printf("float: %zu bytes\n", sizeof(float));
    printf("double: %zu bytes\n", sizeof(double));
    return 0;
}
1
2
3
4
5
6
7
# Output
char: 1 bytes
short: 2 bytes
int: 4 bytes
long: 8 bytes
float: 4 bytes
double: 8 bytes

Note: | Specifier | Expects | |———–|———| | %d | int | | %u | unsigned int | | %ld | long | | %lu | unsigned long | | %zu | size_t (unsigned) |

Constants

Suffixes for type

1
2
3
long int y = 123456789L;   // 'L' or 'l' suffix = long
unsigned int u = 42U;      // 'U' or 'u' suffix = unsigned
unsigned long ul = 42UL;   // both combined

Octal

1
int x = 010;   // this is octal 10 = decimal 8, NOT ten!

Hexadecimal

1
int x = 0x1A;   // hex 1A = decimal 26

Character Constant

1
char c = 'A';   // 'A' is really just the integer 65 (in ASCII)
Escape SequenceMeaning
\aAlert (bell) character
\bBackspace
\fFormfeed
\nNewline
\rCarriage return
\tHorizontal tab
\vVertical tab
\\Backslash
\?Question mark
\'Single quote
\"Double quote
\oooOctal number (1 to 3 digits: 0-7)
\xhhHexadecimal number (one or more digits)

Enumeration

It is a way to declare a list of named integers constants.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* Automatic values starting from 0 */
enum boolean { NO, YES };

/* Explicit values */
enum escapes { 
    BELL = '\a', 
    BACKSPACE = '\b', 
    TAB = '\t', 
    NEWLINE = '\n' 
};

/* Starting from 1 */
enum months { JAN = 1, FEB, MAR, APR, MAY, JUN,
              JUL, AUG, SEP, OCT, NOV, DEC };

Here is a gotcha:

1
enum colors { RED, GREEN = 5, BLUE };

Note: Value of Red is 0, Green is % and Blue is 6

Use case:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>

/* Declare an enumeration for days of the week.
   SUN starts at 0 by default, and each subsequent
   name auto-increments by 1. */
enum weekday { SUN, MON, TUE, WED, THU, FRI, SAT };

int main(void)
{
    enum weekday today;   // declare a variable of type "enum weekday"

    today = WED;          // assign it one of the enum constants

    printf("Today's numeric value is: %d\n", today);

    if (today == SAT || today == SUN)
        printf("It's the weekend!\n");
    else
        printf("It's a weekday.\n");

    return 0;
}
1
2
3
# Output
Today's numeric value is: 3
It's a weekday.

Type Conversion

In C’s usual arithmetic conversions, when two operands of different types are used in an expression, the “lower” type gets converted up to the “higher” type before the operation happens — conversion works its way up this ladder.

PriorityType
1 (highest)long double
2double
3float
4unsigned long
5long
6unsigned int
7 (lowest)int

Explicit Conversion : The Cast Operator

Let’s look at this example:

1
2
3
4
int sum = 7;
int count = 2;

float average = sum / count;   // What do you expect this to print?

Even though average is a float, the expression sum / count is computed entirely in integer arithmetic first (since both operands are int), and integer division truncates any fractional part. So sum / count evaluates to 3 (not 3.5), and then that 3 gets converted to 3.0 when stored into average. The fractional information is already lost by the time the float conversion happens.

The Fix:

1
float average = (float) sum / count;

Here, (float) sum explicitly converts sum to a float first. Now, since one operand of / is a float, the usual arithmetic conversion rule kicks in and promotes count to float as well — so the division itself happens in floating-point, giving 3.5, and that is what’s stored in average.

Increment and Decrement Operators

  • ++n or –n (Prefix) Change happens before the value is used
  • n++ or n–(Postfix) Change happens after the value is used
1
2
3
4
5
6
7
8
9
#include <stdio.h>

main() {
    int n = 5;

    printf("n++   = %d\n", n++);   /* prints 5, then n becomes 6 */
    printf("++n   = %d\n", ++n);   /* n becomes 7, then prints 7 */
    printf("n     = %d\n", n);     /* final value of n */
}

Bitwise Operator

OperatorName
&bitwise AND
\|bitwise OR
^bitwise XOR (exclusive or)
<<left shift
>>right shift
~one’s complement (bitwise NOT)

Assignment Operator

OperatorMeaning
+=x = x + y
-=x = x - y
*=x = x * y
/=x = x / y
%=x = x % y
<<=x = x << y
>>=x = x >> y
&=x = x & y
^=x = x ^ y
\|=x = x \| y

Conditional Operator

1
2
3
/* Ternary Operator */

expr1 ? expr2 : expr3

How it works: expr1 is evaluated first as a condition. If it’s true (nonzero), the whole expression evaluates to expr2. If it’s false (zero), the whole expression evaluates to expr3. Only one of expr2 or expr3 is ever actually evaluated - not both.

Without conditional Operator

1
2
3
4
5
6
int a = 10, b;

if (a >= 0)
    b = a;
else
    b = -a;

With Conditional Operator

1
int b = (a >= 0) ? a : -a;

Precedence and Order of Evaluation

When in doubt use paranthesis.

OperatorsAssociativity
() [] -> .left to right
! ~ ++ -- + - * (type) sizeof (unary)right to left
* / %left to right
+ -left to right
<< >>left to right
< <= > >=left to right
== !=left to right
&left to right
^left to right
\|left to right
&&left to right
\|\|left to right
?:right to left
= += -= *= /= %= &= ^= \|= <<= >>=right to left
, (comma operator)left to right

Control Flow

1. If-Else

1
2
3
4
if (expression)
    statement1
else
    statement2

2. Else-If

1
2
3
4
5
6
7
8
if (expression1)
    statement1
else if (expression2)
    statement2
else if (expression3)
    statement3
else
    statement4

3. Swtich

1
2
3
4
5
6
7
8
9
10
switch (expression) {
    case const1:
        statements
        break;
    case const2:
        statements
        break;
    default:
        statements
}

4. Loops- While and For

1
2
3
4
5
initialization;
while (condition) {
    statement
    increment;
}
1
2
for (initialization; condition; increment)
    statement

Example:

1
2
3
4
5
6
int count = 0;

while (count < 5) {
    printf("%d\n", count);
    count++;
}
1
2
3
for (int count = 0; count < 5; count++) {
    printf("%d\n", count);
}

5. Loop- Do-while

1
2
3
do
    statement
while (expression);

Notice the ; at the end this time - unlike while and for, the do-while loop is terminated with a semicolon, since the loop effectively ends on the while (expression) line.

The key difference: with while and for, the condition is checked before the body runs - so the body might execute zero times. With do-while, the condition is checked after the body runs - so the body always executes at least once, no matter what.

6. Break and Continue

1
2
3
4
5
6
for (int i = 0; i < 10; i++) {
    if (i == 5)
        break;          // exit the loop entirely
    printf("%d\n", i);
}
// prints 0 1 2 3 4, then stops completely
1
2
3
4
5
6
for (int i = 0; i < 5; i++) {
    if (i == 2)
        continue;       // skip printing for i == 2, but keep looping
    printf("%d\n", i);
}
// prints 0 1 3 4  (2 is skipped, loop still runs to completion)

7. Goto and Labels

1
2
3
goto label;
...
label: statement

Example:

1
2
3
4
5
6
7
8
9
10
11
int i = 0;

loop:
    if (i >= 5)
        goto done;
    printf("%d\n", i);
    i++;
    goto loop;

done:
    printf("finished\n");
This post is licensed under CC BY 4.0 by the author.