What is the value of variable x as a result of the following C# statement

The example below shows the structure of a very simple C program along the lines of our “Hello World” example from last class. It’s annotated to describe the different parts of the program.

Show
/* Everything inside these slash-star characters is a "comment"
 * that will be ignored by the compiler. */

#include "ic210.h"  /* This line "includes" code needed to standard things
                     * such as input/output and handling strings.
                     * Later we'll use the system-provided libraries instead,
                     * but to start out you just need to include ic210.h
                     * at the top of every program you write. */

int main() {  /* The "main" tells the compiler where your program should start.
               * For now, all of our code will go between the { following
               * main() and the } at the end of the file. */

  fputs("Hello, world!\n", stdout); 
    /* fputs is a standard C library function (provided through ic210.h)
     * to print out a string of characters. The "Hello, world\n" is the
     * string to be printed. stdout is the name of the output stream that
     * goes to the terminal. For now, we will always just use stdout.  */

  return 0;  /* The return code indicates to the operating system whether our
              * program worked correctly or not. The standard is that
              * a return code of 0 means "everything worked". */

} /* This is the matching "close brace" for the { following main() above. */

In the early part of the course, the C statements that comprise your program are listed between the { }’s in the body of the “main function”. Just as with JavaScript, these statements are executed one after the other from top to bottom.

Strings can be printed to “standard out” (which is the terminal window) using the function

int x;
x = 3;
x = 200;
6. There are different functions to print different types of things like numbers, as we will see soon.

Also notice that every statement inside the main function MUST end with a semicolon. C ignores all code comments

int x;
x = 3;
x = 200;
7 and it also treats all “whitespace” (spaces or newlines) as the same. So you need to put semicolons in to indicate where each statement ends. Even if it seems obvious to you from looking at the code, it’s not obvious to the computer!

Here is a slightly longer example that illustrates the main concepts from this unit. See if you can figure out what it does just by looking at the code. Feel free to copy to a text file, compile, and run it yourself!#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }This is a simple program, but there is a lot going on! For the first time, we have to save some pieces of information and retrieve them later. The variables int x; x = 3; x = 200;8 and int x; x = 3; x = 200;9 are used for that purpose. Also notice that they have different types — int x; x = 3; x = 200;8 is a writenum(1/2, stdout); writenum(13 % 4, stdout);1 whereas int x; x = 3; x = 200;9 is an writenum(1/2, stdout); writenum(13 % 4, stdout);3. And finally, the program makes a decision based on whether the age is at least 21, using an if statement.We’ll now get into all of those elements in greater detail.

Suppose I want to compute something like \((523 - 248)^3\). I can do this with C, but “^” doesn’t mean exponentiation in C, so instead I would need to write:

writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);

This is a bit of a hassle. Normally we would think of first computing (523 - 248), then taking the resulting value and cubing it. Hopefully we think something like: “let x be (523 - 248) and compute x*x*x.” We need a variable in which to store the value (523 - 248)!

So we try creating the following program:
#include "ic210.h"

int main() {
  x = 523 - 248;
  writenum(x*x*x, stdout);
  return 0;
}

When we compile this, we get an error message like

  error line 4: 'x' is an undeclared identifier

What the compiler is saying is this: “x??? you never told me there was going to be an x!” If you want to use x to store the value (523 - 248), you need to first tell the compiler that the name x is going to stand for a number - this is called declaring the variable x.

The statement

writenum(1/2, stdout);
writenum(13 % 4, stdout);
4 declares that x is a variable of type int, which means that it’s a variable that can stand for a (positive or negative) integer number. The type of a variable tells you what kind of data objects, such as an integer or real number or something else …, can be stored in the variable. There are a number of different types in C, and we will use many of them in this course.

The

writenum(1/2, stdout);
writenum(13 % 4, stdout);
5 operator assigns a value to the variable x. So to make the program above work, we just add a declaration of variable
writenum(1/2, stdout);
writenum(13 % 4, stdout);
6 of type
writenum(1/2, stdout);
writenum(13 % 4, stdout);
3 before the assignment:

#include "ic210.h"

int main() {
  int x;                   // DECLARE x of type int
  x = 523 - 248;           // ASSIGN x to the difference 
  writenum(x*x*x, stdout); // PRINT x cubed
  fputs("\n", stdout);     // print a newline at the end
  return 0;                // success!
}

Once x has been declared as a variable of type int, it can be used in the program just like a normal number, either to print or to use in arithmetic expressions, like

writenum(1/2, stdout);
writenum(13 % 4, stdout);
8, which does both.

What really goes on here is that space in your computer’s memory is allocated for one object of type

writenum(1/2, stdout);
writenum(13 % 4, stdout);
3, and given the name x. When you ask for the value of x (by involving it in an arithmetic expression or by trying to print it) the computer fetches a copy of the value from memory. When you use the
writenum(1/2, stdout);
writenum(13 % 4, stdout);
5 operator, the computer takes the value on the right hand side, and copies it into the space reserved for x.

Thus, strange sequences like:

int x;
x = 3;
x = 200;

… make perfect sense to the compiler — even if the second line is a complete waste of time. After the statement

writenum(1/2, stdout);
writenum(13 % 4, stdout);
4, space is reserved for x, though we have no idea what actual value is in there - at this point x is uninitialized. The statement
01
2 copies the value 3 into the space reserved for x. Finally, the statement
01
3 copies the value 200 into the space reserved for x, thus overwriting the 3 that had been there previously. Think of
writenum(1/2, stdout);
writenum(13 % 4, stdout);
6 as being the name of a box into which
writenum(1/2, stdout);
writenum(13 % 4, stdout);
3 values can be written.

Actually, there is one other type besides these five, which is the type of 016 and 017. These are streams that you can read or write to, but there’s not much more to say about them for a few more weeks. We’ll sort of ignore streams as types until there’s something more that we can do with them.As you might have expected, writenum(1/2, stdout); writenum(13 % 4, stdout);3 is not the only type of variable that we are allowed to have. Let’s look at a few more of the most important types that we can use in C. As the course goes on, we will see even more types, and we’ll even eventually see how to define types of our own! But for now, we’ll stick to writenum(1/2, stdout); writenum(13 % 4, stdout);3, writenum(true && false, stdout); writenum(!(false || true), stdout);0, writenum(true && false, stdout); writenum(!(false || true), stdout);1, writenum(true && false, stdout); writenum(!(false || true), stdout);2, and writenum(1/2, stdout); writenum(13 % 4, stdout);1:writenum(1/2, stdout); writenum(13 % 4, stdout);3The writenum(1/2, stdout); writenum(13 % 4, stdout);3 stands for integers. This type is the real workhorse of computing. As with integers, there are no fractions, but unlike integers there are limits on both the positive and negative ends (in the billions of billions on a typical PC today).If you just write a number like writenum(true && false, stdout); writenum(!(false || true), stdout);6 in your program, which is called a literal, it is interpreted as an writenum(1/2, stdout); writenum(13 % 4, stdout);3 by default.operation(s)Commentswritenum(true && false, stdout); writenum(!(false || true), stdout);8, writenum(true && false, stdout); writenum(!(false || true), stdout);9, #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }00all more or less work as you’d expect#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }01Division is tricky, since fractions aren’t involved. Any fractional part leftover after division is [simply chopped off (truncated)]{sty le=“color:red;font-weight:bold”}. This leads to some odd “identities”. For example:If writenum(1/2, stdout); writenum(13 % 4, stdout);6 is the writenum(1/2, stdout); writenum(13 % 4, stdout);3 5, and #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }04 is the writenum(1/2, stdout); writenum(13 % 4, stdout);3 2, then #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }06 is 2!This will trick you at some point or another, I promise.#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }07This is the “modulus” operator. #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }08 returns the remainder when a is divided by b. So, for example, 5 % 3 is 2. The signs of numbers change the sign of the result (try 5 % -3, -5 % 3, and -5 % -3).The #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }07 operator is surprisingly important. Please look at the Minutes and Seconds program to see an example of why!Quick check: What’s the output of the following code snippet?writenum(1/2, stdout); writenum(13 % 4, stdout);01Explanation: The first #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }10 rounds down to give #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }11, and the second one takes the remainder of 13 divided by 4, which is #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }12. There is no space between the #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }11 and the #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }12 because we didn’t tell the program to put any space there!writenum(true && false, stdout); writenum(!(false || true), stdout);0Actually, doubles are only a “simulation” of real numbers because most numbers can only be approximated by a double, analogous to the way we approximate 1/3 as the 6-digit decimal 0.333333.A writenum(true && false, stdout); writenum(!(false || true), stdout);0 is a decimal number, which mathematicians would call a real number and which we might more accurately call a floating-point number.(The term “double” actually comes from “double-precision floating point”.)We saw that a literal number like #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }17 in your program automatically becomes an writenum(1/2, stdout); writenum(13 % 4, stdout);3, but if there’s a decimal place in the literal such as #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }19, that will be a writenum(true && false, stdout); writenum(!(false || true), stdout);0 by default.operation(s)Commentswritenum(true && false, stdout); writenum(!(false || true), stdout);8, writenum(true && false, stdout); writenum(!(false || true), stdout);9, #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }00, #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }01All pretty much do the right thing.(Yes, even division by zero works! It produces a special double value to represent infinity!)#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }25, #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }26, #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }27, etc.Part of the standard math libraryHere is some online documentation on that library.To use the math library, you have to add a line #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }28 at the top of your program and compile with the #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }29 flag to gccwritenum(true && false, stdout); writenum(!(false || true), stdout);1Characters and integers and (approximations of) real numbers are objects that you probably expect to want to compute with. Boolean values are perhaps not as obvious to you. A boolean value is either true or false, yes or no, one or zero.These are critical to computing because, as we’ll soon discuss, much of programming comes down to decision making, and true/false - yes/no - 1/0 boolean values are our decisions. We’ll discuss Boolean Logic in more detail later, but here are the basic operations.operation(s)Comments#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }31The logical AND operator. For bool’s a and b, #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }32 is true if both are true and false otherwise.#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }33The logical OR operator. For bool’s a and b, #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }34 is false if both are false and true otherwise.#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }35The NOT or “negation” operator. #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }36 is false if #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }37 is true, and #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }36 is true if #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }37 is false.The words #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }40 and #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }41 can be used in your programs to represent boolean values. However, bools are generally printed as 0 or 1 unless you do the printing yourself. This is (in part) because the C language originally did not have any bool type, and instead people used writenum(1/2, stdout); writenum(13 % 4, stdout);3s, with 0 meaning false and 1 meaning true.Quick check: What is the output of the following code snippet?writenum(true && false, stdout); writenum(!(false || true), stdout);#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }0writenum(true && false, stdout); writenum(!(false || true), stdout);2The writenum(true && false, stdout); writenum(!(false || true), stdout);2 stands for character. These are letters or numbers, or stranger things … for example there is a “bell character”. Writing it causes your computer to beep!writenum(true && false, stdout); writenum(!(false || true), stdout);2 literals are written inside single quotes, so for example the writenum(true && false, stdout); writenum(!(false || true), stdout);2 a is written inside a program as #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }47.Unusual “characters”, like tabs or newlines, use “escape codes”. They are identified by a backslash. Tab is #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }48, and newline is #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }49.We can use the function #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }50 to print out single characters. For example, the following code snippet:#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }1will produce the output#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }2Operations on writenum(true && false, stdout); writenum(!(false || true), stdout);2’s will be more important later on.writenum(1/2, stdout); writenum(13 % 4, stdout);1The types we’ve seen so far (writenum(1/2, stdout); writenum(13 % 4, stdout);3, writenum(true && false, stdout); writenum(!(false || true), stdout);0, and writenum(true && false, stdout); writenum(!(false || true), stdout);2) are all built-in types. This means that they are part of the core language rather than part of some library. The last type we’ll talk about today, the type writenum(1/2, stdout); writenum(13 % 4, stdout);1, is not a built-in type, it is defined in our library #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }57. It is used for strings of characters, like we’ve already seen many times. For example #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }58, quotes and all, is a string literal.Because writenum(1/2, stdout); writenum(13 % 4, stdout);1 is not a built-in type, none of the built-in operators like writenum(true && false, stdout); writenum(!(false || true), stdout);8 or #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }00 work with strings. Instead, we have to use library functions! Some rather useful functions for strings can be used from the #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }57 library, such as:#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }63: sets string #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }64 equal to #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }65#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }66: returns the length of string #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }67#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }68: returns #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }40 if the two strings are exactly the same, and #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }41 otherwise.

In some programming languages variables have to begin with funny characters. Such a character is usually referred to as a “sigil”. In bash scripting variables begin with a “$”, which is a common sigil. Perl has many sigils, including $, @ and %. For better or for worse, C doesn’t do that to us.http://xkcd.com/1306/Variables in C consist of three things: a name, a type, and a value. We’ve just discussed the type writenum(1/2, stdout); writenum(13 % 4, stdout);3 above, and the #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }72 of the variable is dependent on what the program computes or what the user types in, controlled of course according to the type. But what about the name? That’s up to us as programmers!There are some rules about variable names in C. A variable name must begin with a letter (lowercase or uppercase) or an underscore ( _ ). It may be any length you want (although anything after the first 32 characters will be ignored) but it can only contain letters, digits, and the underscore. Except in special situations, the use of the underscore to begin a variable name should be avoided. There are a special class of names called keywords, which are reserved for use by C, and you may not use one of them to name a variable. Examples of keywords are writenum(1/2, stdout); writenum(13 % 4, stdout);3 and #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }74. (A complete list can be found on this page.There are also names that you could choose for variables, but which are already used for important things. Examples of this are #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }75 and int x; x = 3; x = 200;6. The problem with using such a name is that it creates ambiguity. For example, what would happen with the following:#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }3As it turns out, the compiler will assume that both 017’s refer to your new writenum(true && false, stdout); writenum(!(false || true), stdout);0 and you won’t be able to use 017 for reading. As we proceed, it will (hopefully!) become obvious what cannot be used as variable names.C distinguishes between uppercase and lowercase. As a result, #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }80 and #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }81 will be considered different variable names. A very common mistake that beginning programmers make is to be sloppy in writing variable names, sometimes using capitals and sometimes not. It is not good programming practice to use two variable names that are spelled the same except for capitalization because it leads to errors. Your source code will be easier for mere mortals to understand (interpret this to mean the instructor grading your programs) if you use meaningful variables names.

So far, we’ve been declaring all of our variables at the beginning of the #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }75 with statements such as#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }4then assigning them values later, with statements like#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }5In fact this corresponds to what really happens in the computer: when your #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }75 starts, space is reserved in memory (allocated) to store writenum(1/2, stdout); writenum(13 % 4, stdout);6 and #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }04. Notice that the compiler really needs to know the types here so it knows how many bytes to allocate for each one! In this case, you would get 4 bytes for writenum(1/2, stdout); writenum(13 % 4, stdout);6 and 8 bytes for #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }04.But there’s a potential pitfall here, which is that you can access the variables before they are ever assigned a value. For example, the following program:#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }6This program will actually compile (although it should generate a warning message), but we can’t say what will get printed on the second line. It just depends on whatever happens to be sitting around in your computer’s memory wherever those 4 bytes for writenum(1/2, stdout); writenum(13 % 4, stdout);6 are allocated. It will most likely be 0, but we really can’t say! It’s what’s called undefined behavior — and it means that our program has a bug, a mistake.As we get into more complicated programs, this kind of mistake is actually a pretty common one to make. So I recommend that you save yourself from undefined behavior and just assign variables for values as soon as they are declared, like so:#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }7In fact, there’s a shortcut to doing this in C, which is that you can declare and assign all in the same line, like so:#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }8However, it’s important to remember that this is really doing two things at once, declaring and assigning.Another shortcut is that you can declare (and optionally assign) multiple variables all on the same line, separated by commas, as long as they have the same type, such as:#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }9I personally (Dr. Roche) don’t like doing multiple declarations on one line, because of some things that show up later when we get to arrays. But there are other good reasons to program this way also; it’s a personal choice.I want to emphasize that all of the above about whether to assign right after you declare, and whether to do it on one line or as two separate statements, are all examples of some of the options we have when programming. There are always multiple correct ways to write a program, and we as programmers get to decide exactly how we want to do it. Sometimes there isn’t just one “best” way, just some good ways to do it (and usually some bad ways to do it too!). Even the examples on this website, are just showing you one good way of solving the problem; it doesn’t mean that there aren’t other equally good solutions as well!

Note: I strongly recommend that you review the class on Digital Data from the si110 website. You are expected to understand about bits and bytes, binary-to-decimal and decimal-to-binary conversion, and how the ASCII table defines a mapping between characters and bytes. What’s here in the notes is just a brief overview of that. Here’s a link to a full ASCII table.

You’ve probably heard terms like bits and bytes used in connection with computers, and you’ve probably heard people say that inside a computer everything is 0’s and 1’s. If not, I’ll say it now: Inside a computer everything is 0’s and 1’s! (A bit is just a 0/1 value.) But how can all of these things —

writenum(true && false, stdout);
writenum(!(false || true), stdout);
2s,
writenum(1/2, stdout);
writenum(13 % 4, stdout);
3s, and
writenum(true && false, stdout);
writenum(!(false || true), stdout);
0s — be represented by zeros and ones? Our understanding of types will really depend on being able to answer these questions.

First we’ll look how 0’s and 1’s suffice to represent any integer number, then we’ll look at other types of objects. When we deal with numbers we use the decimal number system, i.e. the base 10 number system. This means that all our numbers (lets look at non-negative integers for now) look like sequences of decimal digits, which are numbers in the range [0,9]. A number like 3027 is short-hand:writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);0Or, for another example,writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);1In the binary number system we have the same idea, but the base is now 2 rather than 10. So, binary digits are in the range [0,1], and now 1011 has a different interpretation. In binary it is short-hand for:writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);2So, in binary the decimal number 11 is represented as 1011. The binary number 1001 = 2^3 + 1 = 9, for another example. With four bits, i.e. four binary digits, we can represent any number from 0 up to 15 (which is 2^3 + 2^2 + 2^1 + 2^0). With four decimal digits I can represent from 0 up to 9999, i.e. from 0 up to 10000 - 1. So we need more bits than decimal digits, but given enough bits we can represent any number we care to. Using k-bits, we can represent the numbers from 0 up to 2^k - 1.

The memory of a computer is simply one long sequence of bits. However, these bits are organized into chunks of 8 called bytes. To emphasize, a byte consists of 8-bits. In a byte, we can represent the numbers from 0 to 255.The type writenum(true && false, stdout); writenum(!(false || true), stdout);2 is one way of interpreting a byte of memory. For example, the byte 01100001 is interpreted as the character #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }37. This interpretation of bytes as characters is called the ASCII encoding, and this table, for example, shows you the whole thing. Interpreting 01100001 as a number in binary, we get the number 97, and if you look up 97 in the table, you’ll see that it corresponds to the character #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }37.Already we see one of the fundamental ideas behind computing, different types of objects may be represented by treating sequences of 0’s and 1’s in different ways. That’s why C needs to keep track of the types of objects, so it knows how to interpret the contents of the chunk of memory associated with each object.

A full writenum(1/2, stdout); writenum(13 % 4, stdout);3 on your PC consists of 4 bytes, or 32 bits, so it can represent pretty big numbers. We’re not going to get into the question of how negative numbers are represented in binary. Essentially an writenum(1/2, stdout); writenum(13 % 4, stdout);3 looks like the binary number representation we just talked about, but in 32 bits.Technically, the int 5 could be represented aswritenum((523 - 248) * (523 - 248) * (523 - 248), stdout);3… or it could be represented aswritenum((523 - 248) * (523 - 248) * (523 - 248), stdout);4… depending on what’s referred to as as the “endianness” of the underlying machine. That particular distinction is beyond the scope of this course, but you will encounter it in subsequent CS/IT course.So, The writenum(1/2, stdout); writenum(13 % 4, stdout);3 5 is represented in the computer as:writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);3… where I’ve broken things up into bytes to make it all a little clearer.A writenum(true && false, stdout); writenum(!(false || true), stdout);0 takes up 8 bytes, or 64 bits. The format is more complex, however, and we will not go over it here, except to say that it is a binary version of the familiar scientific notation. However, instead of a base of 10, it uses a base of two. (Example: 12 is represented as 1.5 x 2^3.) Let it suffice to say that the writenum(true && false, stdout); writenum(!(false || true), stdout);0 1.0 is represented by the following 64 bits:writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);6There are many other numerical types that use more or less bits. For example, writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);00 is a 16-bit integer, writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);01 is a 32-bit decimal number, and writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);02 is a 64-bit integer. But please forget about all that for now; we can safely stick to writenum(1/2, stdout); writenum(13 % 4, stdout);3 and writenum(true && false, stdout); writenum(!(false || true), stdout);0 for the entirety of this class!

One thing we will want to do with every type is reading in and writing out, referred to commonly as I/O. Here are the functions provided by the

#include "ic210.h"

int main() {
  /* Read name into a variable */
  fputs("What is your name? ", stdout);
  cstring name;
  readstring(name, stdin);

  /* Read age into a variable */
  fputs("How old are you now? ", stdout);
  int age = readnum(stdin);

  /* Make a crucial decision */
  if (age >= 21) {
    fputs(name, stdout);
    fputs(" can... rent a car!\n", stdout);
  } 
  else {
    fputs("Sorry, no fun for ", stdout);
    fputs(name, stdout);
    fputs(" (yet).\n", stdout);
  }

  return 0;
}
57 library for input and output on each type:

  • Integers

    writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
    7
  • Doubles

    writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
    8
  • Characters

    writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
    9
  • Strings

    #include "ic210.h"
    
    int main() {
      x = 523 - 248;
      writenum(x*x*x, stdout);
      return 0;
    }
    0

We’ve already seen how to output information from a program using int x; x = 3; x = 200;6 and #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }10. In C (and in many other places) we refer to an output stream, the idea being that each thing we write goes out sequentially in the order we write it.In exactly the same way, we read from an input stream. Just as the standard output stream that prints to the terminal is called 016, the standard input stream is called 017.Code#include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }1User Types#include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }2Effectwritenum(1/2, stdout); writenum(13 % 4, stdout);6 gets the value 12.0, #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }04 gets the value writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);12.Notice that the syntax of the writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);13 command is slightly different than writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);14. That has to do with the fact that writenum(true && false, stdout); writenum(!(false || true), stdout);0 is a built-in type whereas writenum(1/2, stdout); writenum(13 % 4, stdout);1 is only available through the #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }57 library.Both writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);14 and writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);13 skip any whitespace (spaces, tabs, and newlines) before they start actually reading. A writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);13 command will read everything up to the next whitespace, whereas writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);14 will stop reading as soon as it sees anything that’s not part of a number (such as a letter or a comma).Here’s a slightly more tricky example:Code#include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }3User Types#include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }4Effectwritenum(1/2, stdout); writenum(13 % 4, stdout);6 gets the value 12.0, #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }67 gets the value writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);24 as a string, but reading #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }04 causes an error because the letters F isn’t part of a valid number.Putting this together, we can construct a very simple program Addition Calculator, which reads in two numbers from the user and adds them together. Notice that the variable that contains the sum of the two numbers input by the user is actually called writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);26. This is just to enhance the readability of my code. I could’ve called the variable “George” and it would’ve worked just the same.Let’s look at a more useful example. The following input:#include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }5seems to be spread over several lines and composed of different elements - numbers, strings, and characters. However, it is in fact just one long line of characters, and by reading data we move through this line of characters called an input stream. Suppose, for example, we ran the code#include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }6with the above as input. Then, because whitespace is skipped and writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);14 stops when it hits a non-numeric character, the values that end up in each of these variables are as follows:writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);28writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);29writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);30writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);31writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);32writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);33#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }64writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);35writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);36writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);37writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);38writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);39writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);40writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);33#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }65writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);43

You might have noticed that the I/O operations for

writenum(1/2, stdout);
writenum(13 % 4, stdout);
3s and
writenum(true && false, stdout);
writenum(!(false || true), stdout);
0s are the same (at least in the
#include "ic210.h"

int main() {
  /* Read name into a variable */
  fputs("What is your name? ", stdout);
  cstring name;
  readstring(name, stdin);

  /* Read age into a variable */
  fputs("How old are you now? ", stdout);
  int age = readnum(stdin);

  /* Make a crucial decision */
  if (age >= 21) {
    fputs(name, stdout);
    fputs(" can... rent a car!\n", stdout);
  } 
  else {
    fputs("Sorry, no fun for ", stdout);
    fputs(name, stdout);
    fputs(" (yet).\n", stdout);
  }

  return 0;
}
57 library):
writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
14 and
#include "ic210.h"

int main() {
  /* Read name into a variable */
  fputs("What is your name? ", stdout);
  cstring name;
  readstring(name, stdin);

  /* Read age into a variable */
  fputs("How old are you now? ", stdout);
  int age = readnum(stdin);

  /* Make a crucial decision */
  if (age >= 21) {
    fputs(name, stdout);
    fputs(" can... rent a car!\n", stdout);
  } 
  else {
    fputs("Sorry, no fun for ", stdout);
    fputs(name, stdout);
    fputs(" (yet).\n", stdout);
  }

  return 0;
}
10. But how can this be?

Well, technically

writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
14 and
#include "ic210.h"

int main() {
  /* Read name into a variable */
  fputs("What is your name? ", stdout);
  cstring name;
  readstring(name, stdin);

  /* Read age into a variable */
  fputs("How old are you now? ", stdout);
  int age = readnum(stdin);

  /* Make a crucial decision */
  if (age >= 21) {
    fputs(name, stdout);
    fputs(" can... rent a car!\n", stdout);
  } 
  else {
    fputs("Sorry, no fun for ", stdout);
    fputs(name, stdout);
    fputs(" (yet).\n", stdout);
  }

  return 0;
}
10 only operate on
writenum(true && false, stdout);
writenum(!(false || true), stdout);
0s. But since every
writenum(1/2, stdout);
writenum(13 % 4, stdout);
3 can also be represented as a
writenum(true && false, stdout);
writenum(!(false || true), stdout);
0, the C compiler does the conversion back and forth for us automatically without us even noticing.

We can also practice these kinds of conversions ourselves:

#include "ic210.h"

int main() {
  x = 523 - 248;
  writenum(x*x*x, stdout);
  return 0;
}
7

Although a

writenum(true && false, stdout);
writenum(!(false || true), stdout);
2 represents a single character like
#include "ic210.h"

int main() {
  /* Read name into a variable */
  fputs("What is your name? ", stdout);
  cstring name;
  readstring(name, stdin);

  /* Read age into a variable */
  fputs("How old are you now? ", stdout);
  int age = readnum(stdin);

  /* Make a crucial decision */
  if (age >= 21) {
    fputs(name, stdout);
    fputs(" can... rent a car!\n", stdout);
  } 
  else {
    fputs("Sorry, no fun for ", stdout);
    fputs(name, stdout);
    fputs(" (yet).\n", stdout);
  }

  return 0;
}
47 or
writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
56, we know that these characters are actually represented by numbers in the range from 0 up to 127. When doing conversions with type
writenum(true && false, stdout);
writenum(!(false || true), stdout);
2, they get treated as integers equal to their ASCII value. For example, calling

#include "ic210.h"

int main() {
  x = 523 - 248;
  writenum(x*x*x, stdout);
  return 0;
}
8

would cause 100 to be printed, which is the ASCII value for a lowercase d.

Interestingly, C doesn’t know how to do arithmetic with

writenum(true && false, stdout);
writenum(!(false || true), stdout);
2 types directly, but it is happy to automatically convert them to ints and do integer arithmetic! This turns out to be convenient because the ASCII values are in a meaningful order. Consider
writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
59 for example. Looking at the ASCII table, we see that
writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
60 corresponds to the number 98, and
#include "ic210.h"

int main() {
  /* Read name into a variable */
  fputs("What is your name? ", stdout);
  cstring name;
  readstring(name, stdin);

  /* Read age into a variable */
  fputs("How old are you now? ", stdout);
  int age = readnum(stdin);

  /* Make a crucial decision */
  if (age >= 21) {
    fputs(name, stdout);
    fputs(" can... rent a car!\n", stdout);
  } 
  else {
    fputs("Sorry, no fun for ", stdout);
    fputs(name, stdout);
    fputs(" (yet).\n", stdout);
  }

  return 0;
}
47 to the number 97. The C compiler treats this as the
writenum(1/2, stdout);
writenum(13 % 4, stdout);
3 subtraction problem 98 - 97, which evaluates to 1. In fact, the letters of the alphabet appear in order, so that a is 97, b is 98, …, z is 122.

Things get even more interesting when we try to do arithmetic with different types. What should it mean to multiply a

writenum(true && false, stdout);
writenum(!(false || true), stdout);
0 and an
writenum(1/2, stdout);
writenum(13 % 4, stdout);
3? The compiler knows how to convert between these two types, but it only knows how to multiply one type by another number of the same type. So if we have code like
writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
65, should it do the multiplication as two doubles or as two ints?

For arithmetic, types are always converted in the direction that gives the most precision - this is referred to as type promotion - which in this case means that the

writenum(1/2, stdout);
writenum(13 % 4, stdout);
3 is converted (or promoted) to a double, and the operation is performed on two doubles. It wouldn’t make nearly as much sense the other way round, would it?

This kind of type conversion is called implicit because it happens automatically behind the scenes, without you doing anything directly. We have seen it in assignment, in calling I/O routines, and in doing arithmetic. The C compiler always assumes (often wrongly!) that the programmer knows what they’re doing and really means what they write. So the compiler will implicitly convert whatever types it knows how in order to make your program work, using the rule of type promotion.

We also have explicit type conversion, where the programmer says exactly what the type should be. Suppose, for example, that

writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
67 and
writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
68 are
writenum(1/2, stdout);
writenum(13 % 4, stdout);
3s,
writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
68 being the larger. We’d like to print out the value of
writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
71. Well,

#include "ic210.h"

int main() {
  x = 523 - 248;
  writenum(x*x*x, stdout);
  return 0;
}
9

will just print out zero! (Make sure you know why!) We’d like to get some fractional value, in other words, we’d like these values treated as

writenum(true && false, stdout);
writenum(!(false || true), stdout);
0s. To explicitly convert them to
writenum(true && false, stdout);
writenum(!(false || true), stdout);
0s first we’d write:

  error line 4: 'x' is an undeclared identifier
0

The

writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
74 before the value
writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
67 indicates that we want to convert
writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
67 to a double first, and then do the division. Now the compiler is dividing a double by an int, so it will promote the other argument,
writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
77, to a double as well, before doing the actual division.

Special note for bools. The

writenum(true && false, stdout);
writenum(!(false || true), stdout);
1 type is the smallest one, being only a single byte in storage and only having the value of 0 or 1. But it is not treated like the other integer types when you convert to a bool.

Instead, when converting to

writenum(true && false, stdout);
writenum(!(false || true), stdout);
1 only, the value 0 (or
writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
80 for char) becomes
#include "ic210.h"

int main() {
  /* Read name into a variable */
  fputs("What is your name? ", stdout);
  cstring name;
  readstring(name, stdin);

  /* Read age into a variable */
  fputs("How old are you now? ", stdout);
  int age = readnum(stdin);

  /* Make a crucial decision */
  if (age >= 21) {
    fputs(name, stdout);
    fputs(" can... rent a car!\n", stdout);
  } 
  else {
    fputs("Sorry, no fun for ", stdout);
    fputs(name, stdout);
    fputs(" (yet).\n", stdout);
  }

  return 0;
}
41, and anything else becomes
#include "ic210.h"

int main() {
  /* Read name into a variable */
  fputs("What is your name? ", stdout);
  cstring name;
  readstring(name, stdin);

  /* Read age into a variable */
  fputs("How old are you now? ", stdout);
  int age = readnum(stdin);

  /* Make a crucial decision */
  if (age >= 21) {
    fputs(name, stdout);
    fputs(" can... rent a car!\n", stdout);
  } 
  else {
    fputs("Sorry, no fun for ", stdout);
    fputs(name, stdout);
    fputs(" (yet).\n", stdout);
  }

  return 0;
}
40. This is a simple rule, but it can be a little confusing when you compare it to integer conversion which does truncation. For example, casting the double value
writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
83 to an
writenum(1/2, stdout);
writenum(13 % 4, stdout);
3 does truncation and gives you 0, which if further casted to a
writenum(true && false, stdout);
writenum(!(false || true), stdout);
1 would be
#include "ic210.h"

int main() {
  /* Read name into a variable */
  fputs("What is your name? ", stdout);
  cstring name;
  readstring(name, stdin);

  /* Read age into a variable */
  fputs("How old are you now? ", stdout);
  int age = readnum(stdin);

  /* Make a crucial decision */
  if (age >= 21) {
    fputs(name, stdout);
    fputs(" can... rent a car!\n", stdout);
  } 
  else {
    fputs("Sorry, no fun for ", stdout);
    fputs(name, stdout);
    fputs(" (yet).\n", stdout);
  }

  return 0;
}
41 of course. But casting the double value
writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
83 directly to a
writenum(true && false, stdout);
writenum(!(false || true), stdout);
1 gives
#include "ic210.h"

int main() {
  /* Read name into a variable */
  fputs("What is your name? ", stdout);
  cstring name;
  readstring(name, stdin);

  /* Read age into a variable */
  fputs("How old are you now? ", stdout);
  int age = readnum(stdin);

  /* Make a crucial decision */
  if (age >= 21) {
    fputs(name, stdout);
    fputs(" can... rent a car!\n", stdout);
  } 
  else {
    fputs("Sorry, no fun for ", stdout);
    fputs(name, stdout);
    fputs(" (yet).\n", stdout);
  }

  return 0;
}
40, since
writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
83 does not equal 0.

Some Quick Conversion Rulesint → double : This does exactly what you’d expect.double → int : This simply truncates the value, meaning that whatever’s after the decimal point just gets chopped. You can get in trouble if the double value is too big.int → char : if the int is in the range 0-127 the char value is determined by the ASCII table;char → int : the int value is determined by the ASCII table;bool → int or double: the result will be either 0 or 1anything → bool:
#include "ic210.h"

int main() {
  /* Read name into a variable */
  fputs("What is your name? ", stdout);
  cstring name;
  readstring(name, stdin);

  /* Read age into a variable */
  fputs("How old are you now? ", stdout);
  int age = readnum(stdin);

  /* Make a crucial decision */
  if (age >= 21) {
    fputs(name, stdout);
    fputs(" can... rent a car!\n", stdout);
  } 
  else {
    fputs("Sorry, no fun for ", stdout);
    fputs(name, stdout);
    fputs(" (yet).\n", stdout);
  }

  return 0;
}
41 if it’s 0, otherwise anything nonzero becomes
#include "ic210.h"

int main() {
  /* Read name into a variable */
  fputs("What is your name? ", stdout);
  cstring name;
  readstring(name, stdin);

  /* Read age into a variable */
  fputs("How old are you now? ", stdout);
  int age = readnum(stdin);

  /* Make a crucial decision */
  if (age >= 21) {
    fputs(name, stdout);
    fputs(" can... rent a car!\n", stdout);
  } 
  else {
    fputs("Sorry, no fun for ", stdout);
    fputs(name, stdout);
    fputs(" (yet).\n", stdout);
  }

  return 0;
}
40

Almost everything in a C program is an expression. An expression is textual piece of source code that can be evaluated to produce an object that has a type and value. The most familiar expressions are arithmetical. For example, if

writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
93 is an
writenum(1/2, stdout);
writenum(13 % 4, stdout);
3 that’s been assigned the value 4,
writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
95 is an expression of type
writenum(1/2, stdout);
writenum(13 % 4, stdout);
3 and value 14.

Often the value of an expression cannot be determined until the program is run. For example, in the code below

  error line 4: 'x' is an undeclared identifier
1

… what is the value of the expression

writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
97? Well, it depends what the user enters for input. That’s something that cannot be known until the program is run. However, the type of the expression
writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
97 is something we do know before running the program: it’s
writenum(1/2, stdout);
writenum(13 % 4, stdout);
3. This is always true in the C programming language, and because of it C is said to be a “statically-typed” language.

The library calls we have been making to do I/O are also expressions. For example,

#include "ic210.h"

int main() {
  x = 523 - 248;
  writenum(x*x*x, stdout);
  return 0;
}
00 is an expression of type
writenum(true && false, stdout);
writenum(!(false || true), stdout);
2. However, note that some library calls, such as
#include "ic210.h"

int main() {
  x = 523 - 248;
  writenum(x*x*x, stdout);
  return 0;
}
02, don’t have any type. It depends on the function!

Even assignments in C, such as

#include "ic210.h"

int main() {
  x = 523 - 248;
  writenum(x*x*x, stdout);
  return 0;
}
03, are technically expressions as well. In this case, the type of
#include "ic210.h"

int main() {
  x = 523 - 248;
  writenum(x*x*x, stdout);
  return 0;
}
04 is the same as the type of
writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
93 (
writenum(1/2, stdout);
writenum(13 % 4, stdout);
3 in this case), and the value is the same as whatever it gets assigned to (5 in this case). But usually it’s a good idea not to use assignments as expressions, and just let them stand by themselves. That’s not because it’s incorrect or an error to use assignments as expressions, but it’s something that is easy to get confused about (or to confuse others who may read your code!).

At this point it may seem like everything’s an expression, but that’s not true. For example, anything with a ‘;’ (semicolon) at the end is a statement, not an expression. So while

#include "ic210.h"

int main() {
  x = 523 - 248;
  writenum(x*x*x, stdout);
  return 0;
}
07 is an expression as used in
#include "ic210.h"

int main() {
  x = 523 - 248;
  writenum(x*x*x, stdout);
  return 0;
}
08 will evaluate to 12, the statement
#include "ic210.h"

int main() {
  x = 523 - 248;
  writenum(x*x*x, stdout);
  return 0;
}
09 as a line of code ending in a semicolon is not an expression. Declarations of variables, something like
#include "ic210.h"

int main() {
  x = 523 - 248;
  writenum(x*x*x, stdout);
  return 0;
}
10 for example, are not expressions - regardless of whether the ; is there. Still, most things are expressions, and understanding this fact and being able to identify the types and values of expressions are key to understanding C … and most any other programming language.

If you can wait and not be tired by waiting,
  Or being lied about, don’t deal in lies,

Or being hated, don’t give way to hating,
 And yet don’t look too good, nor talk too wise …

- Rudyard Kipling, “If”

Now we’re ready to learn about a very powerful construct in any programming language, the if statement.

The ability to make decisions and react to different input is a key part of the power of computers. For example, we would certainly expect it to be possible to write a program that reads in a number and writes “even” if the number is even, and “odd” if the number is odd. In C (as in English!) “if” is the key to expressing this.

  error line 4: 'x' is an undeclared identifier
2Of course we’ve got to figure out some C that will do the “k is even” for us. What’s inside the ()’s in an
#include "ic210.h"

int main() {
  x = 523 - 248;
  writenum(x*x*x, stdout);
  return 0;
}
22 statement needs to be an expression that evaluates to a number. If the expression is not equal to zero, then the first block of code (code surrounded by {}’s forms a block) is executed. Otherwise the block following the
#include "ic210.h"

int main() {
  x = 523 - 248;
  writenum(x*x*x, stdout);
  return 0;
}
23 is executed. This is called the test condition.

A number is even if 2 divides it evenly, i.e. if its remainder when divided by 2 is 0. So for

writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);
93 to be even,
#include "ic210.h"

int main() {
  x = 523 - 248;
  writenum(x*x*x, stdout);
  return 0;
}
25 must be zero. We can test this using the
#include "ic210.h"

int main() {
  x = 523 - 248;
  writenum(x*x*x, stdout);
  return 0;
}
26 operator. A single “=” in C is used for assigning values to variables, whereas a double “=” (i.e. 
#include "ic210.h"

int main() {
  x = 523 - 248;
  writenum(x*x*x, stdout);
  return 0;
}
26) is used to test whether two values are equal. A “
#include "ic210.h"

int main() {
  x = 523 - 248;
  writenum(x*x*x, stdout);
  return 0;
}
26” expression evaluates to an
writenum(1/2, stdout);
writenum(13 % 4, stdout);
3 value that is either 1 if the two values are equal, or 0 if they are not equal. In general, the C language specifies that
#include "ic210.h"

int main() {
  /* Read name into a variable */
  fputs("What is your name? ", stdout);
  cstring name;
  readstring(name, stdin);

  /* Read age into a variable */
  fputs("How old are you now? ", stdout);
  int age = readnum(stdin);

  /* Make a crucial decision */
  if (age >= 21) {
    fputs(name, stdout);
    fputs(" can... rent a car!\n", stdout);
  } 
  else {
    fputs("Sorry, no fun for ", stdout);
    fputs(name, stdout);
    fputs(" (yet).\n", stdout);
  }

  return 0;
}
11 can be used to indicate something is “false”, whereas any number other than 0 can be used to indicate something is “true”. (And
#include "ic210.h"

int main() {
  /* Read name into a variable */
  fputs("What is your name? ", stdout);
  cstring name;
  readstring(name, stdin);

  /* Read age into a variable */
  fputs("How old are you now? ", stdout);
  int age = readnum(stdin);

  /* Make a crucial decision */
  if (age >= 21) {
    fputs(name, stdout);
    fputs(" can... rent a car!\n", stdout);
  } 
  else {
    fputs("Sorry, no fun for ", stdout);
    fputs(name, stdout);
    fputs(" (yet).\n", stdout);
  }

  return 0;
}
12 is the most convenient number other than 0!)

Thus

#include "ic210.h"

int main() {
  x = 523 - 248;
  writenum(x*x*x, stdout);
  return 0;
}
32 is the test condition we need to replace “k is even” in the code above and make it work.

We might consider solving the above problem in a slightly different way: We’ll assign a variable the value #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }33 if writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);93 is even and #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }35 otherwise. Then, after the if-statement, we’ll do the printing. We might implement it like this: error line 4: 'x' is an undeclared identifier3However, when we try to compile this the compiler complains that #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }67 is an “undeclared identifier”, which is exactly what it would say if we’d never defined #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }67 at all! Well, as far as the compiler is concerned when it processes the “#include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }38” statement, we haven’t defined #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }67. The problem is caused by the scope of variables in C.In C, a variable only exists from the point at which it is declared to the #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }40 that closes off the innermost block in which it was declared. So the #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }67 that we define inside the else-block is invisible, is unknown, does not exist outside of that else-block. In particular, this is true for our int x; x = 3; x = 200;6-statement. The scope of a variable is the portion of the code that “sees” the variable, i.e. that knows it exists. The scope of a variable ends with the innermost block in which it was defined.To fix up this version of our even/odd program, we simply need to move the declaration of #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }67 outside of the if/else-blocks so that its scope extends to int x; x = 3; x = 200;6 statement. This’ll work: error line 4: 'x' is an undeclared identifier4Code in between {}’s forms a block. So the #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }22 is followed by a block (the then block) and the else is followed by a block (the else block). You’ve already seen one example of a block: The block following #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }46. Anything you can write inside of the #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }75 block, you can write inside of any block. This means that our then blocks and else blocks can declare variables, read input, make assignments to variables… anything. So, suppose I wanted to write a program that would compute areas of circles and triangles for the user, first asking the user which kind of object she was interested in. My program might look something like: error line 4: 'x' is an undeclared identifier5… where we’d have to fill in the then-block with code that gets the radius of the circle and computes and outputs its area, and we’d have to fill in the else-block with code that reads in the base and height from the user and computes and outputs the triangle’s area.Code for circle area error line 4: 'x' is an undeclared identifier6Code for triangle area error line 4: 'x' is an undeclared identifier7Each of these “miniprograms” can be placed in its appropriate block, and we get the whole program.

The “#include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }26” is an example of a comparison operator. Relational operators make comparisons of their left and right-hand arguments, and return 1 for true or 0 for false. These op values accordingly. They are: error line 4: 'x' is an undeclared identifier8As you can see from the operator precedence table, they have lower precedence than the arithmetic operators, so things like #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }49 do what we’d like them to do - they evaluate the arithmetic expressions on the left and right, then they apply the #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }50 operator to compare the two values. This means, for example, that instead of writing #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }51 we could write #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }52 and get the same result.So what happens when we compare objects of different type? For example, what happens with #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }53, where k is an int, and x is a double? The answer is that the same automatic type conversions are applied as in arithmetic expressions. So, writenum((523 - 248) * (523 - 248) * (523 - 248), stdout);93 is implicitly converted to a double, and this double value is compared to writenum(1/2, stdout); writenum(13 % 4, stdout);6. Thus, #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }56 evaluates to 0, since 5 is converted to 5.0 prior to the comparison, and we end up actually doing #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }57.Consider a code fragment that reads in a value from the user and returns the “arcsine” or inverse sine of the value. We’ll use the #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }58 function from the math.h library to compute our value. Now, the arcsine is only defined for values between negative 1 and 1, so if the user enters a value outside of this range we should print an error message. Doing this with what we know so far is ugly: error line 4: 'x' is an undeclared identifier9We want to be able to say in our test condition that x must be less than or equal to 1 AND greater than or equal to -1. In C the operator #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }31 is “and”. So our program fragment becomes:#include "ic210.h" int main() { int x; // DECLARE x of type int x = 523 - 248; // ASSIGN x to the difference writenum(x*x*x, stdout); // PRINT x cubed fputs("\n", stdout); // print a newline at the end return 0; // success! }0… which is substantially simpler. More to the point, this does a much better job of reflecting what we’re thinking.Now at first glance, #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }31 looks like something mysterious and new. It’s not. It’s an operator just like writenum(true && false, stdout); writenum(!(false || true), stdout);8, #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }00, and #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }50, all of which we’ve used a lot already. It takes two objects of type writenum(1/2, stdout); writenum(13 % 4, stdout);3 and evaluates to an object of type writenum(1/2, stdout); writenum(13 % 4, stdout);3. We have an intuitive idea of what “and” means, and it coincides with C’s technical, exact definition of what #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }31 means:#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }37#include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }20#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }32zerozero#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }11zerononzero#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }11nonzerozero#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }11nonzerononzero#include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }12So, something like #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }74 makes sense because #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }75 evaluates to an writenum(1/2, stdout); writenum(13 % 4, stdout);3 that is 1 or 0 depending on the comparison, and #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }77 also evaluates to 1 or 0 depending on the second comparison, and then the #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }31 operator combines those two comparison results.This definition of “or” for the #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }33 operator is not quite what we sometimes mean in English by saying “or”. The #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }33 operator is what’s known as an inclusive or, meaning that if both parts are true (nonzero), then the #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }33 also evaluates to true (1). In English, if you said “I’m eating pizza or a burrito”, no one would expect you to be eating both, but in C that’s very possible!There are three boolean operators, the now familiar #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }31 (and), the #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }33 operator (or), and the #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }35 (not) operator. The #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }33 operator is much like #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }31, it takes two writenum(1/2, stdout); writenum(13 % 4, stdout);3s and evaluates to #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }12 if either of those writenum(1/2, stdout); writenum(13 % 4, stdout);3s is nonzero, or to #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }11 if both of the writenum(1/2, stdout); writenum(13 % 4, stdout);3s are 0.The #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }35 operator is a unary operator. Instead of operating on left and right-had values, it operates on a single value - the value following it on the right. It evaluates to 0 if the number following it is nonzero, and it evaluates to 1 if the number following it is 0.Things get especially interesting when you combine boolean operators. For example: Suppose you want to write a program that reads a character from the user and prints “Letter” or “Not a Letter” depending on whether or not the user entered a character that’s a letter. Your program will, more or less, look like this:#include "ic210.h" int main() { int x; // DECLARE x of type int x = 523 - 248; // ASSIGN x to the difference writenum(x*x*x, stdout); // PRINT x cubed fputs("\n", stdout); // print a newline at the end return 0; // success! }1But, of course, the problem is the test condition #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }93 is a letter. Letters come in two flavors, uppercase and lowercase. So a refinement of our if statement wuold be:#include "ic210.h" int main() { int x; // DECLARE x of type int x = 523 - 248; // ASSIGN x to the difference writenum(x*x*x, stdout); // PRINT x cubed fputs("\n", stdout); // print a newline at the end return 0; // success! }2From any ASCII table we would see that uppercase letters range from #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }94 (65) to #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }95 (90). So #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }93 is an uppercase letter boils down to #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }97. Similarly, because lowercase letters range from #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }47 (97) up to #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }99 (122), we know that #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }93 is a lowercase letter boils down to error line 4: 'x' is an undeclared identifier01. Put it all together and we get:#include "ic210.h" int main() { int x; // DECLARE x of type int x = 523 - 248; // ASSIGN x to the difference writenum(x*x*x, stdout); // PRINT x cubed fputs("\n", stdout); // print a newline at the end return 0; // success! }3The binary logical operators #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }31 and #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }33 follow short circuit evaluation rules. This means that the left-hand operand expression is evaluated first, and if the truth or falsity of the expression can be determined based only on the left-hand side, the right-hand operand expression is never even evaluated. So, for example, in the expression:#include "ic210.h" int main() { int x; // DECLARE x of type int x = 523 - 248; // ASSIGN x to the difference writenum(x*x*x, stdout); // PRINT x cubed fputs("\n", stdout); // print a newline at the end return 0; // success! }4if writenum(1/2, stdout); writenum(13 % 4, stdout);6 is, say, error line 4: 'x' is an undeclared identifier05, then the first part of the #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }31, the expression error line 4: 'x' is an undeclared identifier07, evaluates to #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }11. Since error line 4: 'x' is an undeclared identifier09 will always evaluate to #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }11, the right-hand side error line 4: 'x' is an undeclared identifier11 is never actually evaluated.Right now this is more of a curiosity than anything. However, later in the semester, this behavior becomes very important.Note that I wrapped my uppercase and lowercase tests in parentheses, because I wanted to be sure that the #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }31’s were evaluated before the #include "ic210.h" int main() { /* Read name into a variable */ fputs("What is your name? ", stdout); cstring name; readstring(name, stdin); /* Read age into a variable */ fputs("How old are you now? ", stdout); int age = readnum(stdin); /* Make a crucial decision */ if (age >= 21) { fputs(name, stdout); fputs(" can... rent a car!\n", stdout); } else { fputs("Sorry, no fun for ", stdout); fputs(name, stdout); fputs(" (yet).\n", stdout); } return 0; }33. Is that necessary? (Think about how you would decide this!) Even if it isn’t, adding the ()’s makes the meaning clear to everyone.Also observe, we could have used the ASCII integer values like 65 for #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }94 or 90 for #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }95 in the code above, but that would make it much less clear, plus we have to make sure to copy from the ASCII table correctly! When you can, it’s always better to use the character literals like #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }94 and #include "ic210.h" int main() { x = 523 - 248; writenum(x*x*x, stdout); return 0; }95 rather than the integer values from the ASCII table.

This section is optional reading if you want to learn more about C programming. You won’t be required to understand switch statements or to use them in your code. But if you read a lot of C code, you will probably come across

  error line 4: 'x' is an undeclared identifier
26 sooner or later, so you might want to know about it. (You are also free to use
  error line 4: 'x' is an undeclared identifier
26 yourself if you think there’s a good reason to do so.)

A

  error line 4: 'x' is an undeclared identifier
26 statement is an alternative way to write a long
#include "ic210.h"

int main() {
  x = 523 - 248;
  writenum(x*x*x, stdout);
  return 0;
}
22 /
  error line 4: 'x' is an undeclared identifier
19 /
#include "ic210.h"

int main() {
  x = 523 - 248;
  writenum(x*x*x, stdout);
  return 0;
}
23 statement if all of your conditions have the same certain form. You use a
  error line 4: 'x' is an undeclared identifier
26 statement when you want to test a single variable or expression for several different cases. The hitch is that the variable pretty much needs to be an
writenum(1/2, stdout);
writenum(13 % 4, stdout);
3 or a
writenum(true && false, stdout);
writenum(!(false || true), stdout);
2, which limits when
  error line 4: 'x' is an undeclared identifier
26 can be used. Switch breaks things up into cases. You write

int x;
x = 3;
x = 200;
1

… where expr is an expression of type

writenum(1/2, stdout);
writenum(13 % 4, stdout);
3 or
writenum(true && false, stdout);
writenum(!(false || true), stdout);
2, and then list cases consisting of possible values of expr. These cases must be constants, and each case is followed by a
  error line 4: 'x' is an undeclared identifier
38, then a sequence of statements to be executed, and finally a
  error line 4: 'x' is an undeclared identifier
39. In other words, each case looks like this:

int x;
x = 3;
x = 200;
2

You can list as many of these cases as you want. You can also put

int x;
x = 3;
x = 200;
3

as one “case”. This is a catch-all that catches every situation in which expr didn’t match one of the other cases, similar to an

#include "ic210.h"

int main() {
  x = 523 - 248;
  writenum(x*x*x, stdout);
  return 0;
}
23 condition.

For example, the following two blocks of code are equivalent:

int x;
x = 3;
x = 200;
4

int x;
x = 3;
x = 200;
5

Here’s another example program using

  error line 4: 'x' is an undeclared identifier
26. It reads a date in “mm/dd/yyyy” format and returns the date in “dd monthname, yyyy” format.

Here is a list of problems and solutions. With even the very basic construction of input, output, variables, and expressions, we can write some useful programs.

What is X in C?

Master C and Embedded C Programming- Learn as you go The %p is used to print the pointer value, and %x is used to print hexadecimal values. Though pointers can also be displayed using %u, or %x. If we want to print some value using %p and %x then we will not feel any major differences.

What does x == Y mean in C?

x == y compares x and y . The result of x == y will be true if x and y are equal, false otherwise. In C, true is equivalent to any non-zero value (default is 1) and false is equivalent to zero. So, if x is equal to y , x == y is equal to 1.

What is variable in C?

Variables are containers for storing data values, like numbers and characters. In C, there are different types of variables (defined with different keywords), for example: int - stores integers (whole numbers), without decimals, such as 123 or -123.

What does <= mean in C?

Less than or equal to operator is a logical operator that is used to compare two numbers.