Basic Syntaxes of C
Review of common syntaxes and concepts.
Shortcut for Quick Review:
Operators
- Explain the following code.
int a; a = 1;
Click to expand Answer
✔️ Answer
We declare the variable
a
and assign the value1
to it.Note that
=
is the assignment operator, not the equal sign we used to see in math.In math textbooks, the above operation is often written as:
\[a:=1\]In algorithm textbooks, the operation is often notated as:
\[a\leftarrow 1\] - What is the result of the following code?
#include <stdio.h> int main(void) { int a = 0; if (a = 5) puts("a is 5"); return 0; }
Click to expand Answer
✔️ Answer
a is 5
==
is not=
, Theif
condition is satisfied for anything else than0
. The code above is like:if (a = 5) // a becomes 5 if (a) // Read from a if (5) True
-
What is the result of the following code?
#include <stdio.h> int main(void) { int a = 1, b = 2; a = b = 3; printf("%d %d\n", a, b); return 0; }
Click to expand Answer
✔️ Answer
3 3
The right operand is evaluated first, so it can be seen as:
a = (b = (3)) // (a, b) == (1, 2) a = (3) // (a, b) == (1, 3) 3 // (a, b) == (3, 3)
- What is the result of the following code?
#include <stdio.h> int main(void) { int a = -1; puts("a is -1"); if (-3 < a < 3) puts("-3 < a < 3 is True"); else puts("-3 < a < 3 is False"); if (-3 < a < 0) puts("-3 < a < 0 is True"); else puts("-3 < a < 0 is False"); return 0; }
Click to expand Answer
✔️ Answer
a is -1 -3 < a < 3 is True -3 < a < 0 is False
When evaluating an expression, be aware of the operator precedence and the associativity.
The result of the expression is
1
if True, otherwise0
.In this part, it can be seen as:
if ((-3 < a) < 3) if ((-3 < -1) < 3) if (1 < 3) // (-3 < -1) is True if (1) // (1 < 3) is True True
if ((-3 < a) < 0) if ((-3 < -1) < 0) if (1 < 0) // (-3 < 1) is True if (0) // (1 < 0) is False False
To achieve the correct result, consider using
if (-3 < a && a < 0)
. - What is the result of the following code?
#include <stdio.h> #define MAX 5 int main(void) { int i, a[MAX] = {1, 2, 3, 4, 5}; for (i = 0; i < 1000000; i++) { if (i < MAX & a[i] < 3) { printf("%d\n", a[i]); } } return 0; }
Click to expand Answer
✔️ Answer Undefined Behavior. (May result in segmentation fault) Assume
i
is 10. The if condition is evaluated as:if ((i < MAX) & (a[i] < 3)) if ((10 < 5) & (a[i] < 3)) if (0 & (a[i] < 3)) if (0 & (a[10] < 3)) if (0 & (??? < 3)) // ??? here indicates an invalid memory access. Undefined Behavior.
If
&
is changed to&&
, the code’s result will be:1 2
since
&&
has short-circuit evaluation. - What is the result of the following code?
#include <stdio.h> #define MAX 100 int main(void) { int i, top = -1, len = 0; int a[MAX], b[MAX]; for (i = 1; i < 4; i++) { a[++top] = i; b[len++] = i; } for (i = 0; i < len; i++) { printf("a[%d] is %d\n", i, a[i]); printf("b[%d] is %d\n", i, b[i]); } return 0; }
Click to expand Answer
✔️ Answer
a[0] is 1 b[0] is 1 a[1] is 2 b[1] is 2 a[2] is 3 b[2] is 3
Be aware of pre-increment and post increment.
++a
can be seen as:a += 1 return a;
a++
can be seen as:int tmp = a; a += 1; return tmp;
By the way, you’ve just implemented the push operation of the Stack data structure!
- What is the result of the following code?
#include <stdio.h> int main(void) { printf("The size of char is %zu\n", sizeof(char)); printf("The size of short is %zu\n",sizeof(short)); printf("The size of int is %zu\n", sizeof(int)); printf("The size of long is %zu\n", sizeof(long)); printf("The size of long long is %zu\n", sizeof(long long)); printf("The size of unsigned long long is %zu\n", sizeof(unsigned long long)); printf("The size of float is %zu\n", sizeof(float)); printf("The size of double is %zu\n", sizeof(double)); return 0; }
Click to expand Answer
✔️ Answer The answer should be something like:
The size of char is 1 The size of short is 2 The size of int is 4 The size of long is 4 The size of long long is 8 The size of unsigned long long is 8 The size of float is 4 The size of double is 8
The numbers may vary depending on your compiler and hardware. The C99 standard only defines the minimum size of each variable type. So the maximum size may vary depending on the implementation.
Conditional Statement
- What is the result of the following code?
#include <stdio.h> int main(void) { int a = 3; if (a < 0); { puts("a < 0?"); } return 0; }
Click to expand Answer
✔️ Answer
a < 0?
A semicolon after
if
,while
,for
, … can be seen as a{}
. To avoid bugs, it may be better to just use{}
instead of;
for emptyif
s orfor
s. - What is the result of the following code?
#include <stdio.h> int main(void) { int a = 3; switch(a) { case 1: puts("1"); case 2: puts("2"); case 3: puts("3"); case 4: puts("4"); case 5: puts("5"); default: puts("Default"); } return 0; }
Click to expand Answer
✔️ Answer
3 4 5 Default
The rationale on
switch
is it compares the target variable with each case and continues executing code after the matched case. If nobreak
is specified before the next case, it’ll continue executing and won’t jump out theswitch
.We’ll use
case ?: ... break;
most of the time. - What is the result of the following code?
#include <stdio.h> int main(void) { int a, b = 0, c; c = ((a=3<4)*4>5?7:(b=5)<<1%10>8?117:87); printf("%d %d %d\n", a, b, c); return 0; }
Click to expand Answer
✔️ Answer
1 5 117
If you didn’t get the answer right, it’s totally okay. The code above is a piece of bad code.
Keep in mind that:
... ? ... : ...
(The short-hand notation ofif
) may be suitable in some cases, but often it just decreases the readability.- If you’re not sure with the operator precedences, adding redundant parentheses is totally fine.
A student asked me how the code above work, so I’ll just show it:
c = ((a=3<4)*4>5?7:(b=5)<<1%10>8?117:87) c = ((a=1)*4>5?7:(b=5)<<1%10>8?117:87) // a becomes 1 c = (1*4>5?7:(b=5)<<1%10>8?117:87) c = (4>5?7:(b=5)<<1%10>8?117:87) c = (0?7:(b=5)<<1%10>8?117:87) c = ((b=5)<<1%10>8?117:87) // b becomes 5 c = (5<<1%10>8?117:87) c = (5<<1>8?117:87) c = (10>8?117:87) c = (1?117:87) c = 117 // c becomes 117 117
- What is the result of the following code?
#include <stdio.h> int main(void) { play: puts("play"); goto play; return 0; }
Click to expand Answer
✔️ Answer Print
play
forever.play play play ...
Abusing
goto
may easily make your program unmaintainable. But it might be useful when you want to break out a deep, nested loop.
Loops
- What is the result of the following code?
#include <stdio.h> int main(void) { int i = 0; while (i < 3) { printf("%d\n", i); i++; } for (int j = 0; j < 3; j++) { printf("%d\n", j); } return 0; }
Click to expand Answer
✔️ Answer
0 1 2 0 1 2
The
for
loop above works exactly the same as thewhile
loop above, they are interchangeable. - What is the result of the following code?
#include <stdio.h> int main(void) { int T = 3; while (T--) printf("T is %d\n", T); printf("final T is %d\n", T); T = 3; while (--T) printf("T is %d\n", T); printf("final T is %d\n", T); return 0; }
Click to expand Answer
✔️ Answer
T is 2 T is 1 T is 0 final T is -1 T is 2 T is 1 final T is 0
while (T--)
may be useful when you want to repeat doing something for exactlyT
times. - What is the result of the following code?
#include <stdio.h> int main(void) { int T = 0; do { printf("%d\n", T); } while (T--); int T2 = 0; printf("%d\n", T2); while(T2--) { printf("%d\n", T2); } return 0; }
Click to expand Answer
✔️ Answer
0 0
The
do-while
loop above works exactly the same as theprintf
+while
loop above, they are interchangeable.The
do-while
loop may be rarely seen, but it can be useful when asking for inputs.The following code read inputs until the user enters a positive number. If the input is invalid, the program will continue to ask for valid input.
do { puts("Please enter a positive number"); scanf("%d", &input); } while (input < 0); // Continue the program.
- What is the result of the following code?
#include <stdio.h> int main(void) { int i, j; for (i = 0; i <= 100; i += 10) { printf("i is %d\n", i); for (j = 0; j < 10; j++) { if (j % 2) continue; printf("j is %d\n", j); } if (!(i % 10)) break; } printf("final i is %d\n", i); printf("final j is %d\n", j); return 0; }
Click to expand Answer
✔️ Answer
i is 0 j is 0 j is 2 j is 4 j is 6 j is 8 final i is 0 final j is 10
Three points worth noting:
continue
ignores the current iteration and continue running thefor
loop. You can think of it as jumping to the}
part of thefor
.break
directly breaks (exits) thefor
loop.- There’s a final
j++
before testing the exit condition. This can be useful to determine whetherbreak
is executed in thefor
loop.for (int i = 0; i < N; i++) { if (...) break; } if (i == N) { puts("break didn't occur"); }
Scope and Lifetime of Variables
We’ll only discuss variables in a single file.
These concepts in multiple files are much more complicated, they’ll be covered in the final project.
- What is the result of the following code?
#include <stdio.h> int a; void func(int a) { printf("%d\n", a); { extern int a; printf("%d\n", a); } printf("%d\n", a); a = 4; printf("%d\n", a); } int main(void) { printf("%d\n", a); int a = 1; printf("%d\n", a); { int a = 2; printf("%d\n", a); } printf("%d\n", a); { extern int a; printf("%d\n", a); } printf("%d\n", a); a = 3; printf("%d\n", a); func(a); printf("%d\n", a); return 0; }
Click to expand Answer
✔️ Answer
0 1 2 1 0 1 3 3 0 3 4 3
Some points worth noting:
- The initial value of global variables is 0.
- Local (auto) variables have indeterminate initial value if not specified, and if they have the same name, the local variable is accessed instead of the global variable (variable scope).
extern
is used mostly in multiple files, to access variables in another file. In this case, it is used to access the global variable.- A variable can only be accessed in the brackets (
{}
) it is declared in (variable lifetime). when outside the bracket, the variable is released. - The rules in the
main
function are the same in other functions.
- What is the result of the following code?
#include <stdio.h> int a = 117; void func1() { int a = 0; a++; printf("func1 a is %d\n", a); } void func2() { static int a = 0; a++; printf("func2 a is %d\n", a); } void func3() { static int a; a = 0; a++; printf("func3 a is %d\n", a); } int main(void) { for (int i = 0; i < 3; i++) func1(); for (int i = 0; i < 3; i++) func2(); for (int i = 0; i < 3; i++) func3(); printf("main a is %d\n", a); return 0; }
Click to expand Answer
✔️ Answer
func1 a is 1 func1 a is 1 func1 a is 1 func2 a is 1 func2 a is 2 func2 a is 3 func3 a is 1 func3 a is 1 func3 a is 1 main a is 117
static
variables’ value persist throughout the entire lifetime of the program. However, its scope is still limited in the brackets{}
.
Compiler Preprocessor (#define
)
- What is the result of the following code?
#include <stdio.h> int a = 0; #define a b int a = 1; int main(void) { printf("a is %d\n", a); printf("b is %d\n", b); #undef a printf("a is %d\n", a); printf("b is %d\n", b); return 0; }
Click to expand Answer
✔️ Answer
a is 1 b is 1 a is 0 b is 1
#define
only affects tokens. (e.g. variables) - What is the result of the following code?
#include <stdio.h> int a = 10; int func() { printf("%d\n", a); } #define a 117; int main(void) { int b = a + 3; printf("%d\n", b); func(); return 0; }
Click to expand Answer
✔️ Answer
117 10
Some points worth noting:
-
trailing semicolon in
#define
has its meaning.In the case above:
int b = a + 3; int b = 117; +3;
The
+3;
has no affect onb
, it’s just like1;
. -
#define
does not follow your program flow, since the replacement is done before compile.
-
- What is the result of the following code?
#include <stdio.h> #define ADD(X, Y) X+Y int main(void) { int result; result = 2 * ADD(1, 2) * 4; printf("%d\n", result); return 0; }
Click to expand Answer
✔️ Answer
10
You can see
#define
as replacing tokens. So if you want it to get the answer24
, you should add parentheses#define ADD(X, Y) (X+Y)
. - What is the result of the following code?
#include <stdio.h> #define ever (;;) #define forever(x) \ for ever { puts(x); } int main(void) { forever("alone"); return 0; }
Click to expand Answer
✔️ Answer Print
alone
forever.alone alone alone ...
for(;;)
runs forever.
For the next assignment, we’ll review some basic recursions.
Epilogue
Photo Credit: on Oppressive Silence site by Ethan Vincent.
Comments