Which of the following is the directive you must use to access files from a C++ program
This C Beginner's Handbook follows the 80/20 rule. You'll learn 80% of the C programming language in 20% of the time. Show
This approach will give you a well-rounded overview of the language. This handbook does not try to cover everything under the sun related to C. It focuses on the core of the language, trying to simplify the more complex topics. And note: You can get a PDF and ePub version of this C Beginner's Handbook here. Enjoy! Table of Contents
Introduction to CC is probably the most widely known programming language. It is used as the reference language for computer science courses all over the world, and it's probably the language that people learn the most in school along with Python and Java. I remember it being my second programming language ever, after Pascal. C is not just what students use to learn programming. It's not an academic language. And I would say it's not the easiest language, because C is a rather low level programming language. Today, C is widely used in embedded devices, and it powers most of the Internet servers, which are built using Linux. The Linux kernel is built using C, and this also means that C powers the core of all Android devices. We can say that C code runs a good portion of the entire world. Right now. Pretty remarkable. When it was created, C was considered a high level language, because it was portable across machines. Today we kind of take for granted that we can run a program written on a Mac on Windows or Linux, perhaps using Node.js or Python. Once upon a time, this was not the case at all. What C brought to the table was a language that was simple to implement and that had a compiler that could be easily ported to different machines. I said compiler: C is a compiled programming language, like Go, Java, Swift or Rust. Other popular programming language like Python, Ruby or JavaScript are interpreted. The difference is consistent: a compiled language generates a binary file that can be directly executed and distributed. C is not garbage collected. This means we have to manage memory ourselves. It's a complex task and one that requires a lot of attention to prevent bugs, but it is also what makes C ideal to write programs for embedded devices like Arduino. C does not hide the complexity and the capabilities of the machine underneath. You have a lot of power, once you know what you can do. I want to introduce the first C program now, which we'll call "Hello, World!" hello.c
Let's
describe the program source code: we first import the This library gives us access to input/output functions. C is a very small language at its core, and anything that's not part of the core is provided by libraries. Some of those libraries are built by normal programmers, and made available for others to use. Some other libraries are built into the compiler. Like
This function is wrapped into a But what is a function, anyway? A function is a routine that takes one or more arguments, and returns a single value. In the case of The function has a body, which is wrapped in curly braces. Inside the body we have all the code that the function needs to perform its operations. The That's because this is a function invocation. Somewhere, inside the
You don't need to understand what this means
now, but in short, this is the definition. And when we call The
will be run by the operating system when the program is executed. How do we execute a C program? As mentioned, C is a compiled language. To run the program we must first compile it. Any Linux or macOS computer already comes with a C compiler built-in. For Windows, you can use the Windows Subsystem for Linux (WSL). In
any case, when you open the terminal window you can type That's good. It means the C compiler is there, and we can start using it. Now type the program above into a Type the program: Now press Confirm by pressing the That's it, we should be back to the terminal now: Now type
The program should give you no errors: but it should have generated a
to run it: I prepend Awesome! Now if you call This is one of the pros of C: it's highly optimized, and this is also one of the reasons it's this good for embedded devices that have a very limited amount of resources. Variables and typesC is a statically typed language. This means that any variable has an associated type, and this type is known at compilation time. This is very different than how you work with variables in Python, JavaScript, PHP and other interpreted languages. When you create a variable in C, you have to specify the type of a variable at the declaration. In this example we initialize a variable
A variable name can contain any uppercase or lowercase letter, can contain digits and the underscore character, but it can't
start with a digit. You can also initialize a variable at declaration, specifying the initial value:
Once you declare a variable, you are then able to use it in your program code. You can change its value at any time, using the In this case:
the compiler will raise a warning at compile time, and will convert the decimal number to an integer value. The C built-in data types are Integer numbersC provides us the following types to define integer values:
Most of the time, you'll likely use an The
As you can see, we are not guaranteed the same values for different environments. We only have an indication. The problem is that the exact numbers that can be stored in each data type depends on the implementation and the architecture. We're guaranteed that The ANSI C spec standard determines the minimum values of each type, and thanks to it we can at least know what's the minimum value we can expect to have at our disposal. If you are programming C on an Arduino, different board will have different limits. On an Arduino Uno board, On all Arduino boards, Unsigned integersFor all the above data types, we can prepend
The problem with overflowGiven all those limits, a question might come up: how can we make sure our numbers do not exceed the limit? And what happens if we do exceed the limit? If you have an If you have a
If you don't have a signed value, the behavior is undefined. It will basically give you a huge number which can vary, like in this case:
In other words, C does not protect you from going over the limits of a type. You need to take care of this yourself. Warnings when declaring the wrong typeWhen you declare the variable and initialize it with the wrong value, the
And it also warns you in direct assignments:
But not if you increase the number using, for example,
Floating point numbersFloating point types can represent a much larger set of values than integers can, and can also represent fractions, something that integers can't do. Using floating point numbers, we represent numbers as decimal numbers times powers of 10. You might see floating point numbers written as
and in other seemingly weird ways. The following types:
are used to represent numbers with decimal points (floating point types). All can represent both positive and negative numbers. The minimum requirements for any C implementation is that The exact figures, as with integer values, depend on the implementation. On a modern Mac, a A The type On your specific computer, how can you determine the specific size of the types? You can write a program to do that:
In my system, a modern Mac, it prints:
ConstantsLet's now talk about constants. A constant is declared similarly to variables, except it is prepended with the Like this:
This is perfectly valid C, although it is common to declare constants uppercase, like this:
It's just a convention, but one that can greatly help you while reading or writing a C program as it improves readability. Uppercase name means constant, lowercase name means variable. A constant name follows the same rules for variable names: can contain any uppercase or lowercase letter, can contain digits and the underscore character, but it can't start with a digit. Another way to define constants is by using this syntax:
In this case, you don't need to add a
type, and you don't also need the The C compiler will infer the type from the value specified, at compile time. OperatorsC offers us a wide variety of operators that we can use to operate on data. In particular, we can identify various groups of operators:
In this section I'm going to detail all of them, using 2 imaginary variables I am keeping bitwise operators, structure operators and pointer operators out of this list, to keep things simpler Arithmetic operatorsIn this macro group I am going to separate binary operators and unary operators. Binary operators work using two operands:
Unary operators only take one operand:
The difference between For example:
The same applies to the decrement operator. Comparison operators
Logical operators
Those operators are great when working with boolean values. Compound assignment operatorsThose operators are useful to perform an assignment and at the same time perform an arithmetic operation:
The ternary operatorThe ternary operator is the only operator in C that works with 3 operands, and it’s a short way to express conditionals. This is how it looks:
Example:
If The ternary operator is functionality-wise same as an if/else conditional, except it is shorter to express and it can be inlined into an expression. sizeofThe Example usage:
Operator precedenceWith all those operators (and more, which I haven't covered in this post, including bitwise, structure operators, and pointer operators), we must pay attention when using them together in a single expression. Suppose we have this operation:
What's the value of There is a set of rules that help us solve this puzzle. In order from less precedence to more precedence, we have:
Operators also have an associativity rule, which is always left to right except for the unary operators and the assignment. In:
We first execute Then we can perform the sum and the subtraction: 4 + 1 - 2. The value of In all cases, however, I want to make sure you realize you can use parentheses to make any similar expression easier to read and comprehend. Parentheses have higher priority over anything else. The above example expression can be rewritten as:
and we don't have to think about it that much. ConditionalsAny programming language provides the programmers the ability to perform choices. We want to do X in some cases, and Y in other cases. We want to check data, and make choices based on the state of that data. C provides us 2 ways to do so. The
first is the ifIn an
You can append an
Beware of one common source of bugs - always use the comparison operator
Why does this happen? Because the conditional check will look for a boolean result (the result of a comparison), and the You can have multiple
switchIf you need to do too many if / else / if blocks to perform a check, perhaps because you need to check the exact value of a variable, then You can provide a variable as condition, and a series of
We need a You can add a "catch-all" case at the end, labeled
LoopsC offers us three ways to perform a loop: for loops, while loops and do while loops. They all allow you to iterate over arrays, but with a few differences. Let's see them in detail. For loopsThe first and probably most common way to perform a loop is for loops. Using the Like this:
The
We first define a loop variable, in this case named The variable is initialized at the 0 value, and the first iteration is done. Then it is incremented as the increment part says ( Inside the loop main block we can access the variable
Loops can also start from a high number, and go a lower number, like this:
You can also increment the loop variable by 2 or another value:
While loopsWhile loops is simpler to write than a Instead of defining all the loop data up front when you start the loop, like you do in the
This assumes that And this loop will be an infinite loop unless you increment the This is what you need for a "correct" while loop:
There's one exception to this, and we'll see it in one minute. Before, let me introduce Do while loopsWhile loops are great, but there might be times when you need to do one particular thing: you want to always execute a block, and then maybe repeat it. This is done using the
The block that contains the Then, until Breaking out of a loop using breakIn all the C loops we have a way to break out of a loop at any point in time, immediately, regardless of the conditions set for the loop. This is done using the This is useful in many cases. You might want to check for the value of a variable, for example:
Having this option to break out of a loop is particularly interesting for
It's rather common to have this kind of loop in C. ArraysAn array is a variable that stores multiple values. Every value in the array, in C, must have the same type. This means you will have arrays of You can define an array of
You must always specify the size of the array. C does not provide dynamic arrays out of the box (you have to use a data structure like a linked list for that). You can use a constant to define the size:
You can initialize an array at definition time, like this:
But you can also assign a value after the definition, in this way:
Or, more practical, using a loop:
And you can reference an item in the array by using square brackets after the array variable name, adding an integer to determine the index value. Like this:
Array indexes start from 0, so an array with 5 items, like the The interesting thing about C arrays is that all elements of an array are stored sequentially, one right after another. Not something that normally happens with higher-level programming languages. Another interesting thing is this: the variable name of the array, More on pointers soon. StringsIn C, strings are one special kind of array: a string is an array of
I introduced the A string can be initialized like you initialize a normal array:
Or more conveniently with a string literal (also called string constant), a sequence of characters enclosed in double quotes:
You can print a string via
Do you notice how "Flavio" is 6 chars long, but I defined an array of length 7? Why? This is because the last character in a string must be a This is important to keep in mind especially when manipulating strings. Speaking of
manipulating strings, there's one important standard library that is provided by C: This library is essential because it abstracts many of the low level details of working with strings, and provides us with a set of useful functions. You can load the library in your program by adding on top:
And once you do that, you have access to:
and many, many more. PointersPointers are one of the most confusing/challenging parts of C, in my opinion. Especially if you are new to programming, but also if you come from a higher level programming language like Python or JavaScript. In this section I want to introduce them in the simplest yet not-dumbed-down way possible. A pointer is the address of a block of memory that contains a variable. When you declare an integer number like this:
We can use the
I used the We can assign the address to a variable:
Using We can use the pointer operator
This time we are using the pointer operator again, but since it's not a declaration this time it means "the value of the variable this pointer points to". In this example we declare an
When working with C, you'll find that a lot of things are built on top of this simple concept. So make sure you familiarize with it a bit by running the above examples on your own. Pointers are a great opportunity because they force us to think about memory addresses and how data is organized. Arrays are one example. When you declare an array:
The
The cool thing
is that we can get the second item by adding 1 to the
And so on for all the other values. We can also do many nice string manipulation operations, since strings are arrays under the hood. We also have many more applications, including passing the reference of an object or a function around to avoid consuming more resources to copy it. FunctionsFunctions are the way we can structure our code into subroutines that we can:
Starting from your very first program, a "Hello, World!", you immediately make use of C functions:
The Here's another function:
Functions have 4 important aspects:
The function body is the set of instructions that are executed any time we invoke a function. If the function has no return value, you can use the keyword You cannot return more than one value from a function. A function can have arguments. They are
optional. If it does not have them, inside the parentheses we insert
In this case, when we invoke the function we'll call it with nothing in the parentheses:
If we have one parameter, we specify the type and the name of the parameter, like this:
When we invoke the function, we'll pass that parameter in the parentheses, like this:
We can have multiple parameters, and if so we separate them using a comma, both in the declaration and in the invocation:
Parameters are passed by copy. This means that if you modify If you pass a pointer as a parameter, you can modify that variable value because you can now access it directly using its memory address. You can't define a default value for a parameter. C++ can do that (and so Arduino Language programs can), but C can't. Make sure you define the function before calling it, or the compiler will raise a warning and an error:
The warning you get regards the ordering, which I already mentioned. The error is about another thing, related. Since C does not "see" the function declaration before the invocation, it must make assumptions. And it assumes the function to return If you change the function definition to:
you'd just get the warning, and not the error:
In any case, make sure you declare the function before using it. Either move the function up, or add the function prototype in a header file. Inside a function, you can declare variables.
A variable is created at the point of invocation of the function and is destroyed when the function ends. It's not visible from the outside. Inside a function, you can call the function itself. This is called recursion and it's something that offers peculiar opportunities. Input and outputC is a small language, and the "core" of C does not include any Input/Output (I/O) functionality. This is not something unique to C, of course. It's common for the language core to be agnostic of I/O. In the case of C, Input/Output is provided to us by the C Standard Library via a set of functions defined in the
You can import this library using:
on top of your C file. This library provides us with, among many other functions:
Before describing what those functions do, I want to take a minute to talk about I/O streams. We have 3 kinds of I/O streams in C:
With I/O functions we always work with streams. A stream is a high level interface that can represent a device or a file. From the C standpoint, we don't have any difference in reading from a file or reading from the command line: it's an I/O stream in any case. That's one thing to keep in mind. Some functions are designed to work with a specific stream, like Since I started talking about
In its simplest usage form, you pass it a string literal:
and the program will print the content of the string to the screen. You can print the value of a variable. But it's a bit tricky because you need to add a special character, a placeholder,
which changes depending on the type of the variable. For example we use
We can print more than one variable by using commas:
There are other format specifiers like
and many more. We can use escape characters in
|