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
aand assign the value1to 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=, Theifcondition 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 3The 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 FalseWhen evaluating an expression, be aware of the operator precedence and the associativity.
The result of the expression is
1if 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 Trueif ((-3 < a) < 0) if ((-3 < -1) < 0) if (1 < 0) // (-3 < 1) is True if (0) // (1 < 0) is False FalseTo 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
iis 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 2since
&&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 3Be aware of pre-increment and post increment.
++acan 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 8The 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 emptyifs orfors. - 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 DefaultThe rationale on
switchis it compares the target variable with each case and continues executing code after the matched case. If nobreakis 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 117If 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
playforever.play play play ...Abusing
gotomay 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 2The
forloop above works exactly the same as thewhileloop 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 0while (T--)may be useful when you want to repeat doing something for exactlyTtimes. - 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 0The
do-whileloop above works exactly the same as theprintf+whileloop above, they are interchangeable.The
do-whileloop 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 10Three points worth noting:
continueignores the current iteration and continue running theforloop. You can think of it as jumping to the}part of thefor.breakdirectly breaks (exits) theforloop.- There’s a final
j++before testing the exit condition. This can be useful to determine whetherbreakis executed in theforloop.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 3Some 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).
externis 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
mainfunction 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 117staticvariables’ 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#defineonly 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 10Some points worth noting:
-
trailing semicolon in
#definehas its meaning.In the case above:
int b = a + 3; int b = 117; +3;The
+3;has no affect onb, it’s just like1;. -
#definedoes 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
10You can see
#defineas 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
aloneforever.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