C Module 0: Introduction
Accept assignment and create repository https://classroom.github.com/a/a4GETg5n
Deadline: Thursday 9/10 at 11:00PM.
Objectives
The goal of this module is:
- To introduce the syntax of basic C: variables, assignment, operators, and control flow.
- To practice building C programs using the Linux command line.
History
A brief history of C:
- Developed in 1972 at AT&T Bell Labs by Dennis Ritchie and Brian Kernighan.
- Primary purpose: provide a higher-level programming language than assembly in which to write Unix.
- Why the name C?
- Classic book: “The C Programming Language” by Kernighan and Ritchie.
- Since then:
- C has gone through many changes.
- Original C is called “K&R C”
- ANSI defined a standard in 1989, now called ANSI C89.
- Most common: update in 1999 called ANSI C99.
- Current: As of October 2018, “C18” became the current standard replacing ANSI C11.
- See The Development of the C Language, a history of C written by
Dennis Ritchie
Why learn C?
Highlights of C:
- C has many high-level programming features, but also let’s you work at the lowest level (manipulating bits).
- C is amenable to compiler optimization: compiled C code is
generally very efficient. - C gives the programmer a lot of freedom in accessing memory
and hardware. - Most operating systems, embedded systems are written in C.
- A lot of open-source projects are written in C.
The world of C:
Software development in C usually involves using additional C-related tools.
Tools for programming:
- Development environments, e.g.,
Eclipse, Emacs
- Debuggers, e.g.
gdb
- Useful tools/libraries, e.g.,
lex
andyacc
- Tools for managing projects, e.g.,
make
,ant
- Tools for configuring software, e.g.,
autoconf
. - Tools for GUI development:
tk/tcl
,QT
,GTK
. - Scripting languages:
perl
,awk
.
Open-source software:
- GNU-Linux is written in C, as are most tools from GNU.
- Most open-source projects today are written in C - see www.sourceforge.net
- Open-source projects tend to use the
gcc
compiler (itself an open-source project) and related tools.
Going from Java to C
For a Java programmer:
- C’s syntax is similar.
- Large parts of C will appear to be a subset of Java.
- But …
- C has pointers, with a lot of freedom to manipulate them (direct memory access).
- C has less type-checking than Java.
- C’s variable declarations can look strange.
- C provides no support for objects.
- C has function declarations.
- C has a
preprocessor language
that’s processed before compilation.
- The programming experience in C:
- Because of the additional freedom in the language, it’s much easier to create errors.
- There’s less help from the compiler, and no help from the runtime system.
- You need to use a debugger to track pointer errors.
-
C’s freedom in programming allows one to construct some highly unreadable code. For example, here is one winning entry from the International Obfuscated C Code Contest:
int i;main(){for(;i["] < i;++i){--i;}"];read('-'-'-',i+++"hell\ o, world!\n",'/'/'/'));}read(j,i,p){write(j/p+p,i---j,i/i);}
(It prints “Hello world!” to the screen).
HelloWorld in C
Here is the classic HelloWorld program in C:
#include <stdio.h>
int main()
{
printf("Hello World!\n");
}
Note:
- The
#include
command is a preprocessor directive to load thestdio
library. - Execution starts in a function (method) called
main
:- There are other signatures for
main
as we will see
- There are other signatures for
- The
printf
method is used for screen output. - The “newline” character
\n
is explicitly required.
Exercise 0.1: Use the
HelloWolrd.c
in your repository to write your first C program mimicking the one above, but with a more creative message. PressRepl.it
button to have a web browser editor to write, compile, and execute the code.
To compile with Repl.it, and any other command line terminal (we will do this with Visual Studio Code too) that has the gcc tools installed:
gcc -o hello HelloWorld.c
This produces an executable called hello
which can be executed as:
> ./hello
Some compiling options:
- With the same contents, we could re-name (or copy) the file to
whatever.c
and compile as:
cp HelloWorld.c whatever.c
gcc -o helloworld whatever.c
(Note the case-sensitivity).
- We could also create an executable with any name:
gcc -o strangeThing HelloWorld.c
(The -o
option lets you specify the name of the executable.)
- The simplest form on invoking the gcc C compiler is:
> gcc HelloWorld.c
This produces an executable called a.out
(by tradition).
And don’t forget to commit your changes!!
C-related languages
Languages related to C:
- C++:
- C++ is “mostly” a superset of C, offering support for objects.
gcc
can compile C++ as well - this is useful for projects that combine C and C++.
- Objective C:
- Another C enhancement to support objects.
- Popular on Apple/MAC platforms.
- C#
- Microsoft’s answer to Java.
- Many other experimental variations: TinyC, Cyclone, D.
Reserved words and identifiers
C’s 37 reserved words:
auto enum restrict unsigned
break extern return void
case float short volatile
char for signed while
const goto sizeof _Bool
continue if static _Complex
default inline struct _Imaginary
do int switch
double long typedef
else register union
Note: None of these may be used as identifiers.
By category:
- Data type keywords (11):
char, double, enum, float, int, struct, union, void, _Bool, _Complex, _Imaginary
- Data type modifiers (9):
auto, const, long, register, short, signed, static, unsigned, volatile
- Data type definition (1):
typedef
- Control-flow keywords (12):
break, case, continue, default, do, else, for, goto, if, return, switch, while
- Compiler directives (3):
extern, inline, restrict
- Memory allocation (1):
sizeof
Identifiers in C:
- For use as variable or function names.
- Rules:
- Any combination of letters, digits and underscore.
- Must begin without a digit.
- Case is significant:
int myAge;
is different from
int MyAge;
- Identifiers may be arbitrarily long, but only first 31 characters are significant. Thus, all compilers will distinguish between
int abcdefghijklmnopqrstuvwxyz12345;
and
int abcdefghijklmnopqrstuvwxyz12346;
but compilers are not guaranteed to distinguish between
int abcdefghijklmnopqrstuvwxyz123456;
and
int abcdefghijklmnopqrstuvwxyz123457;
- Note: only the first 8 characters are significant for functions in external files.
- Convention:
- Old C convention: use underscore’s to separate out “meaning” as in:
num_courses_taken = compute_num_courses_taken(student_ID);
- The modern convention is to use Java’s style:
numCoursesTaken = computeNumCoursesTaken(studentID);
- Summary of convention:
- Start a variable or function name with a lowercase letter.
- Use uppercase letters to mark new “meaning” within identifier.
- Avoid using numbers if possible.
- Use small identifiers (usually, one letter) for loop variables, temporary computations, e.g.,
for (i = 0; i < 10; i++) { A[i] = B[i] * C[i]; }
Compilation and basic compiler errors
C programs are case-sensitive. The following program will not compile:
#include <stdio.h>;
Int main ()
{
}
This is because the C reserved word int
is mis-spelt as Int
.
Exercise 0.2: Type up and compile the above program in the
Exercise2.c
file. What is the compiler error reported? Write your answer in theREADME.md
file!
About C compiler errors:
- Depending on the C compiler you use, you will get more or less useful errror messages.
- In general, the C compiler is going to be much less helpful than a Java compiler, which will make the identification of compiler errors harder.
Exercise 0.3 What is the error produced by compiling this program?
#include <stdio.h>
int Main ()
{
}
Exercise 0.4 What is the error produced by compiling this program?
#include <stdio.h>
int main ()
{
Printf("Hello World!\n");
}
Let’s revisit helloworld and point out some syntactic features:
- First, the program:
#include <stdio.h>
int main ()
{
printf("Hello World!\n");
}
- C’s only reserved word in this program:
int
. - There are two function (method) names:
main, printf
. - We see curly brackets as delimiters for the function
main
. - The semi-colon (
;
) ends a statment. - Parentheses for are used for enclosing method parameters (arguments).
- A string literal,
Hello World!
is enclosed in double-quotes.
Next, let us get accustomed to errors produced by the compiler when the syntax is incorrect.
Exercise 0.5 What errors are reported by the compiler with this program?
#include <stdio.h> int main ( // Forgot the matching right parenthesis { printf ("Hello World!\n"); }
Exercise 0.6 What errors are reported by the compiler with this program?
#include <stdio.h> int main () { printf ("Hello World!\n); // Forgot the matching right quote (") }
Exercise 0.7 What errors are reported by the compiler with this program?
#include <stdio.h> int main () { printf ("Hello World!\n") // Forgot the semi-colon. }
Exercise 0.8 What errors are reported by the compiler with this program?
#include <stdio.h> int main () { printf ("Hello World!\n"); // Missing brace
Exercise 0.9 What errors are reported by the compiler with this program?
#include <stdio.h> main () { printf ("Hello World!\n"); }
Exercise 0.10: What kind of a compiler error do you get if you try to use a reserved word as an identifier? Use a reserved word to declare an integer identifier.
Comments
There are two types of comments in ANSI C99:
- Inline comments, using
//
that comment out everything up to the end of the line. - Block comments, using ` /* ` and ` */ ` that comment out everything in between.
Consider this example:
#include <stdio.h>
/* This is a block comment. Everything between the begin-comment symbol
and the end-comment symbol is ignored by the compiler. It is conventional
to use a separate line for the end-comment symbol.
*/
// This is an in-line comment.
int main (/* A strange place for a block comment */)
{
printf ("Hello World!\n"); // Another inline comment.
}
Include’s
The first line, and perhaps the next few, typically have #include
’s.
-
For our
helloworld.c
example, we had#include <stdio.h>
- We will later understand how to work with multiple files and libraries, but for now think of this as including some library/API functionality that we can use.
-
The typical
#include
’s we will need are:#include <stdio.h> #include <math.h> #include <stdlib.h> #include <string.h>
- Important:
- To avoid clutter, our examples will not necessarily have these
#include
’s. - When you write your code, make sure to have these “include” lines be the first lines in your program.
- To avoid clutter, our examples will not necessarily have these
-
Thus, for example, we might describe our
helloworld.c
example asint main () { printf("Hello World!\n"); }
with the understanding that the actual file will look like
#include <stdio.h> #include <math.h> #include <stdlib.h> #include <string.h> int main () { printf ("Hello World!\n"); }
Data types
About C’s data types:
- There are basic types:
int, char, float, double, void
. - There are type modifiers:
const, short, long, signed, unsigned
. - C99 has additional types:
_Bool, _Complex, _Imaginary
. - There are two complexities with regard to C’s types:
- The type rules are somewhat complicated.
- Variable declarations can be made complicated (if desired).
- Storage sizes are not standard: for example an
int
can be either:- 2 bytes: -32,768 to 32,767
- 4 bytes: -2,147,483,648 to 2,147,483,647
Integer types
Type | Typical storage size | Range | Print specifier |
int | 2 or 4 bytes | -32,768 to 32,767 (2 bytes) -2,147,483,648 to 2,147,483,647 (4 bytes) | %d |
unsigned int | 2 or 4 bytes | 0 to 65,535 (2 bytes) 0 to 4,294,967,295 (4 bytes) | %u |
short | 2 bytes | -32,768 to 32,767 | %d |
unsigned short | 2 bytes | 0 to 65,535 | %u |
long | 4 bytes | -2,147,483,648 to 2,147,483,647 | %ld |
unsigned long | 4 bytes | 0 to 4,294,967,295 | %lu |
long long | 8 bytes | -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 | %lld |
unsigned long long | 8 bytes | 0 to 18,446,744,073,709,551,615 | %llu |
Let’s look at an example:
int main ()
{
int numDaysInYear = 365;
long int numStarsInUniverse = 2000000000L;
unsigned long long int largestIntegerInC = 18446744073709551615LLU;
printf ("numDaysInYear = %d\n", numDaysInYear);
printf ("numStarsInUniverse = %ld\n", numStarsInUniverse);
printf ("largestIntegerInC = %llu\n", largestIntegerInC);
}
Exercise 0.11: Implement the above. What happens if you omit the “L” or “LLU” when declaring numStarsInUniverse and largestIntegerInC? What happens if you use %d for the largestIntegerInC print statement?
Note:
- Where to declare variables:
- Prior to C99, all variables had to be declared either at the top of a function, or globally (outside any function).
- Since ANSI C99, variables can also be declared inside blocks, as in:
int main () { int numDaysInYear = 365; printf ("numDaysInYear = %d\n", numDaysInYear); if (numDaysInYear < 366) { long int numStarsInUniverse = 2000000000L; printf ("Thank your lucky %ld stars\n", numStarsInUniverse); } else { unsigned long long int numStarsInUniverse = 1844674407370955161ULL; printf ("Thank your lucky %llu stars\n", numStarsInUniverse); } }
- Two commonly used declarations in other languages (Java, C++) were NOT permitted in older versions of C:
- Declaration in a for-loop:
int main () { int i; for (i=0; i<10; i++) { // Allowed. printf ("i=%d\n", i); } for (int j=0; j<10; j++) { // Not allowed in C89\. j needs to be declared at the top. printf ("j=%d\n", j); } }
- Declare as needed:
int main () { int numDaysInYear = 365; // Allowed. printf ("numDaysInYear = %d\n", numDaysInYear); long int numStarsInUniverse = 2000000000L; // Not allowed. printf ("Number of stars = %ld stars\n", numStarsInUniverse); }
- To make matters confusing, some compilers will allow both types of declarations (for-loop, as-needed) above.
- To be safe, you can follow ANSI C89 and always declare every needed variable at the top of the method or as a global.
-
Variables can be initialized and declared in one statement, or declared and initialized separately:
#include <stdio.h> // Declaration and assignment. int numDaysInYear = 365; int main () { // Declaration. long int numStarsInUniverse; printf ("numDaysInYear = %d\n", numDaysInYear); // Assignment. numStarsInUniverse = 2000000000L; printf ("numStarsInUniverse = %ld\n", numStarsInUniverse); }
For variety, we have declared
numDaysInYear
as a global variable. - ANSI C99 has added the
long long
type, not available in C89 or earlier. -
The
int
reserved word may be left out if modifiers are present:int main () { int numDaysInYear = 365; long numStarsInUniverse = 2000000000L; unsigned long long largestIntegerInC = 18446744073709551615ULL; printf ("numDaysInYear = %d\n", numDaysInYear); printf ("numStarsInUniverse = %ld\n", numStarsInUniverse); printf ("largestIntegerInC = %llu\n", largestIntegerInC); }
- The letter
L
is appended to the end of along
constant. - The letter
LL
is appended to the end of along long
constant. - The letter
U
is appended to the end of anunsigned
constant, e.g.,LLU
.
Screen output: (HW)
- The
printf
library function is used for output to the screen. -
The arguments to
printf
are:printf (_format-string [zero or more variables]_)
- The format string needs to specify all variables that follow the format string:
- The idea is,
printf
will look at additional arguments only based on what’s in the format string. - In the first
printf
above, the%d
symbol specifies an integer. - Similarly,
%ld
specifies along
and%llu
specifies anunsigned long long int
.
- The idea is,
-
The format string can specify any number of variables, separated by arbitrary text, for example:
int main () { int numDaysInYear = 365; long int numStarsInUniverse = 2000000000L; unsigned long long int largestIntegerInC = 18446744073709551615ULL; printf ("numDaysInYear = %d numStarsInUniverse = %ld largestIntegerInC = %llu\n", numDaysInYear, numStarsInUniverse, largestIntegerInC); }
- The format string can also specify the amount of space to reserve for the printed number by using %Nd, where N is a number indicating how much space to use:
HW Exercise 0.12 Adjust the amount of space used in the printf call. What happens if x has more digits than are reserved? What happens if it has fewer digits?
Floating-point types:
Type | Typical storage size | Range | Print specifier | Approximate precision |
float | 4 bytes | 1.2 x 10-38 to 3.4 x 1038 | %f | 6 decimal places |
double | 8 bytes | 2.3 x 10-308 to 1.7 x 10308 | %lf | 15 decimal places |
long double | 10 bytes | 3.4 x 10-4932 to 1.1 x 104932 | %LG | 19 decimal places |
Consider this example:
Exercise 0.13: What print command would you use to print PI with a reserved width of 10 characters and only one digit after the decimal place? Does the reserved width include the decimal point and “e+” notation characters?
Note:
-
The letter
F
is appended to the end of a “decimal” type constant:float PI = 3.141F;
-
Floating point constants can also be specified in exponent format:
double doublePI = 314.159265E-2;
- The letter
L
is used for along double
constant. - The print format string specifies both the total width of the field and the number of digits that follow the decimal point.
- Use
%e
in the format string for exponent format.
HW Exercise 0.14: It’s a common error to mistype the format string. What happens when you reverse the %d and %f specifiers in the program above?
Character types:
Type | Typical storage size | Range | Print specifier |
char | 1 byte | -128 to 127 | `%c` |
unsigned char | 1 byte | 0 to 255 | none |
signed char | 1 byte | -128 to 127 | none |
Consider this example:
int main ()
{
char letter = 'a';
unsigned char letter2 = 'b';
signed char letter3 = 'c';
printf ("letter = %c\n", letter);
printf ("letter2 = %c\n", letter2);
printf ("letter3 = %c\n", letter3);
}
Note:
- Generally pronounced “char” (like charred meat) or “car”
- Characters are used to represent either letters or small numbers. The letter symbols you are used to are converted from numbers using the ASCII standard.
- When assigning to a letter, you must use single quotes around the letter.
- There is no special print-format specifier for
signed
andunsigned
char. char
variables are also used to access memory on a byte-by-byte basis, as we will see shortly.
HW Exercise 0.15 What happens if you use double quotes when assigning a char? What happens if you put multiple letters within single quotes?
HW Exercise 0.16 Use the ASCII table above to assign c1 and c2 to numeric values that represent your initials. Then print them using both the %d and %c format specifiers.
Casting
Consider this example:
int main ()
{
int i = 5;
long j = 6;
double d = 3.141;
j = i; // Works fine. Implicit cast from int to long.
d = i; // Works fine. Implicit cast from int to double
i = j; // May not compile.
i = d; // May not compile.
d = 3.141;
i = (int) j; // Compiles. Explicit cast from long to int.
i = (int) d; // Compiles. Explicit cast from double to int.
// Cast's can be used in any expression:
printf ("The int part of d=%lf is %d\n", d, (int) d);
}
Note:
- To assign a variable higher in the cast hierarchy to one lower, an explicit cast is required.
-
An explicit cast is the desired type in parentheses placed before the target of the cast:
i = (int) d;
- Many compilers don’t warn you if you are “down” casting: this is a common source of error.
- The implicit cast hierarchy is:
short
→int
→unsigned int
→long
→unsigned long
→long long
→float
→double
→long double
- Use an explicit cast in any assignment down the hierarchy.
Exercise 0.17: Use the editor below to find out what this program will print out.
int main () { printf ("%lf\n", ( (double) (int) 3.141 ) ); }
Operators and expressions
An example with arithmetic operators
int main ()
{
double x = 6, y = 5;
int i = 8, j = 5;
// Standard: plus, minus, multiple, divide
printf ("x+y=%lf\n", x+y); // Prints 11.0
printf ("x-y=%lf\n", x-y); // Prints 1.0
printf ("x*y=%lf\n", x*y); // Prints 30.0
printf ("x/y=%lf\n", x/y); // Prints 1.2
// Integer divide and remainder:
printf ("i/j=%d\n", i/j); // Prints 1
printf ("i mod j=%d\n", i%j); // Prints 3
// Post and pre-increment:
printf ("i++ = %d\n", i++); // Prints 8
printf ("++j = %d\n", ++j); // Prints 6
// Assignment shortcut example.
i += j;
printf ("i=%d\n", i); // Prints 15
}
An example with bitwise operators
int main ()
{
int a = 9;
int b = 4;
printf ("a&b = %d\n", a&b); // Bitwise AND: Prints 0
printf ("a|b = %d\n", a|b); // Bitwise OR: Prints 13
printf ("a^b = %d\n", a^b); // Bitwise EOR: Prints 13
printf ("~a = %d\n", ~a); // Complement: Prints -10
printf ("b << 1 = %d\n", (b << 1)); // Left shift by 1: Prints 8
printf ("b >> 2 = %d\n", (b >> 2)); // Right shift by 2: Prints 1
}
An example with boolean operators
int main ()
{
double x = 5, y = 6, z = 6;
int result;
printf ("x < y = %d\n", (x < y)); // Prints 1 (true)
printf ("x <= y = %d\n", (x <= y)); // Prints 1
printf ("y > z = %d\n", (y > z)); // Prints 0 (false)
printf ("y >= z = %d\n", (y >= z)); // Prints 1
printf ("x == y = %d\n", (x == y)); // Prints 0
printf ("y == z = %d\n", (y == z)); // Prints 1
printf ("x != y = %d\n", (x != y)); // Prints 1
result = (x < y);
printf ("result=%d\n", result); // Prints 1
if (result == 1) { // Equality comparison.
printf ("x < y\n");
}
else {
printf ("x >= y\n");
}
// Prints "x < y"
}
Note:
- In C, boolean operators result in
1
(indicating “true”) or0
(indicating “false”). - These results can be assigned to
int
-compatible variables.
Boolean types: (HW)
- C originally did not provide any boolean types.
- There are now four ways of working with boolean’s:
-
Use the original approach of
1
and0
:int main () { double x = 5, y = 6; int result = (x < y); if (result == 1) { printf ("x < y\n"); } else { printf ("x >= y\n"); } }
-
Define your own boolean types using the pre-processor:
#define boolean int #define true 1 #define false 0 int main () { double x = 5, y = 6; boolean result = (x < y); if (result == true) { printf ("x < y\n"); } else { printf ("x >= y\n"); } }
-
Use a recent addition to the standard C library:
#include <stdio.h> #include <stdbool.h> int main () { double x = 5, y = 6; bool result = (x < y); if (result == true) { printf ("x < y\n"); } else { printf ("x >= y\n"); } }
-
Use the new C99
_Bool
type:#include <stdio.h> #include <stdbool.h> int main () { double x = 5, y = 6; _Bool result = (x < y); if (result == true) { printf ("x < y\n"); } else { printf ("x >= y\n"); } }
-
- We recommend using the
stdbool
package, as shown in (3) above.
HW Exercise 0.18 : Put the following code into the editor below. What does it print out? What is its significance?
int main () { int k = 13; int i; for (i=0; i < 8; i++) { printf ("%d ", (k % 2)); k >>= 1; } printf ("%\n"); }
Constants (HW)
There are two ways of defining constants in C:
-
The simple and traditional way is to use the preprocessor:
#define PI 3.14159 int main () { double radius = 5.0; printf ("Area of Circle with radius %lf is %lf\n", radius, PI*radius*radius); }
-
Another way is to use the
const
modifier that makes a variable immutable:const double PI = 3.14159; int main () { double radius = 5.0; printf ("Area of Circle with radius %lf is %lf\n", radius, PI*radius*radius); }
The latter approach is more general, and can be applied to function parameters as well:
HW Exercise 0.19 What happens when you try to modify one of the const variables? Is this a compile-time or a run-time error?
Control flow
An overview of C’s control flow statements via examples:
int main ()
{
int i = 1;
// if-statement:
if (i == 0) {
printf ("i is zero\n");
}
// if-statement with compound expression:
if ( (i >= -1) && (i <= 1) ) {
printf ("-1 <= i <= 1\n");
}
// if-else combination
if (i == 1) {
printf ("one\n");
}
else if (i == 2) {
printf ("two\n");
}
else {
printf ("larger than two\n");
}
// Variation of if-else above:
if (i == 1) {
printf ("one\n");
}
else {
if (i == 2) {
printf ("two\n");
}
else {
printf ("larger than two\n");
}
}
// Equivalent switch statement:
switch (i) {
case 1: {
printf ("one\n");
break;
}
case 2: {
printf ("two\n");
break;
}
default: {
printf ("larger than two\n");
}
}
// for-loop example:
printf ("Numbers 0 through 9: \n");
for (i=0; i < 10; i++) {
printf (" %d\n", i);
}
// while-loop equivalent:
printf ("Numbers 0 through 9: \n");
i = 0;
while (i < 10) {
printf (" %d\n", i);
i++;
}
// do-while equivalent:
printf ("Numbers 0 through 9: \n");
i = 0;
do {
printf (" %d\n", i);
i++;
} while (i < 10);
// Example of using "break"
printf ("Numbers 0 through 9: \n");
i = 0;
while (1) {
if (i == 10) {
break;
}
printf (" %d\n", i);
i++;
}
printf ("Odd numbers less than 10:\n");
i = 0;
while (1) {
// If we've reached the limit, break out of the loop.
if (i == 10) {
break;
}
// If it's an even number, skip to next iteration of loop.
if (i % 2 == 0) {
i++;
continue;
}
// Print odd number.
printf (" %d\n", i);
i++;
}
}
Note:
- Between a for-loop and a while-loop, use a while-loop only if the while-loop is easier to write.
- Similarly, prefer a while-loop over an equivalent do-while.
- ANSI C99 allows declaration of the for-loop variable in the for-loop:
for (int i=0; i < 10; i++) {
// ...
}
Versions prior to C99 do not. For compatibility with many textbooks, we will declare variables at the top.
Exercise 0.20 : There is a bug in this code! Why won’t it print “i is not 5” like the developer expected? Is this a compile-time or run-time error?
int main(void) { int i = 10; if (i = 5) printf ("i is equal to 5"); else printf("i is not 5"); return 0; }
Exercise 0.21 : Without running it, what is the error in the following code?
int i = 10; while (i >= 1) printf ("i=%d\n", i); i--;
Now for some practice with control loops…
Use this code window to solve the exercises below.
HW Exercise 0.22 : Use for-loops to print “hourglasses” of different sizes. For example, here is the size=3 glass:
X------------X X--------X X----X XX X----X X--------X X------------X
and here is the size=5 one:
X----------------X X------------X X--------X X----X XX X----X X--------X X------------X X----------------X X--------------------X
Then, repeat using only while-loops. Paste your code for both versions into your README file.
Submission Instructions
Do your work in a repository created using the link at the beginning of the page.
- Answer all of the exercise questions above in your
README.md
file. - We suggest you edit the file directly in the GitHub web editor, but alternatively you can clone the repository to your computer or replit.
- Submit your assignment by committing your
README.md
file to your git repository (and pushing to GitHub if you are not editing through its website). - You should check the contents of the
README.md
file through the GitHub website to ensure that it has all of your correct content!
Your work will be graded out of 20 points. 1 point will be for the style/formatting of your Markdown (e.g., use appropriate markdown code blocks and headings), and the remaining 19 points will be for completing the exercises fully.