Do You Have to Know C Before Learning C++

This C Beginner's Handbook follows the 80/20 rule. You lot'll acquire 80% of the C programming language in 20% of the time.

This approach will give you a well-rounded overview of the linguistic communication.

This handbook does not try to cover everything under the dominicus related to C. Information technology focuses on the core of the linguistic communication, trying to simplify the more complex topics.

And note: You can become a PDF and ePub version of this C Beginner'southward Handbook hither.

Enjoy!

Tabular array of Contents

  1. Introduction to C
  2. Variables and types
  3. Constants
  4. Operators
  5. Conditionals
  6. Loops
  7. Arrays
  8. Strings
  9. Pointers
  10. Functions
  11. Input and output
  12. Variables scope
  13. Static variables
  14. Global variables
  15. Type definitions
  16. Enumerated Types
  17. Structures
  18. Command line parameters
  19. Header files
  20. The preprocessor
  21. Conclusion

Introduction to C

C is probably the most widely known programming language. It is used as the reference linguistic communication for computer science courses all over the earth, and it's probably the language that people learn the most in school along with Python and Coffee.

I remember it being my second programming language ever, after Pascal.

C is not merely what students use to learn programming. It's not an academic language. And I would say it's non the easiest linguistic communication, because C is a rather low level programming linguistic communication.

Today, C is widely used in embedded devices, and it powers nigh of the Net servers, which are built using Linux. The Linux kernel is built using C, and this also means that C powers the cadre of all Android devices. We tin say that C code runs a practiced 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 accept for granted that we can run a plan written on a Mac on Windows or Linux, possibly 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 Get, Java, Swift or Rust. Other popular programming language like Python, Cerise or JavaScript are interpreted. The departure 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 circuitous task and one that requires a lot of attending to foreclose bugs, but it is as well what makes C platonic to write programs for embedded devices like Arduino.

C does not hibernate the complexity and the capabilities of the machine underneath. You have a lot of power, once y'all know what you tin can do.

I want to introduce the first C programme at present, which we'll telephone call "Hi, World!"

hi.c

          #include <stdio.h>  int main(void) {     printf("Hi, Globe!"); }                  

Let's describe the program source lawmaking: we first import the stdio library (the name stands for standard input-output library).

This library gives us access to input/output functions.

C is a very small-scale linguistic communication at its core, and anything that'south non part of the core is provided by libraries. Some of those libraries are built by normal programmers, and fabricated available for others to use. Some other libraries are congenital into the compiler. Like stdio and others.

stdio is the library that provides the printf() role.

This function is wrapped into a master() function. The main() function is the entry point of any C plan.

But what is a function, anyway?

A office is a routine that takes i or more arguments, and returns a single value.

In the case of primary(), the office gets no arguments, and returns an integer. We identify that using the void keyword for the argument, and the int keyword for the render value.

The office has a torso, which is wrapped in curly braces. Inside the body we accept all the code that the function needs to perform its operations.

The printf() function is written differently, equally you can come across. Information technology has no render value defined, and we laissez passer a cord, wrapped in double quotes. We didn't specify the blazon of the argument.

That's because this is a role invocation. Somewhere, inside the stdio library, printf is divers as

          int printf(const char *format, ...);                  

You don't need to empathise what this means now, but in short, this is the definition. And when we call printf("Hullo, World!");, that's where the office is run.

The main() function nosotros defined above:

          #include <stdio.h>  int main(void) {     printf("Howdy, World!"); }                  

will be run by the operating system when the programme is executed.

How do we execute a C program?

As mentioned, C is a compiled language. To run the plan we must beginning compile it. Whatsoever Linux or macOS computer already comes with a C compiler congenital-in. For Windows, you tin use the Windows Subsystem for Linux (WSL).

In any example, when you lot open the terminal window you tin type gcc, and this command should render an mistake saying that you didn't specify whatever file:

Screen-Shot-2020-01-29-at-10.10.50

That'southward good. It means the C compiler is at that place, and nosotros tin start using it.

Now blazon the plan to a higher place into a hello.c file. You can use any editor, only for the sake of simplicity I'yard going to use the nano editor in the command line:

Screen-Shot-2020-01-29-at-10.11.39

Type the program:

Screen-Shot-2020-01-29-at-10.16.52

Now press ctrl-X to exit:

Screen-Shot-2020-01-29-at-10.18.11

Confirm by pressing the y cardinal, then press enter to confirm the file name:

Screen-Shot-2020-01-29-at-10.18.15

That'due south it, we should exist back to the terminal now:

Screen-Shot-2020-01-29-at-10.13.46

At present blazon

          gcc hello.c -o hi                  

The program should give you lot no errors:

Screen-Shot-2020-01-29-at-10.16.31

but it should take generated a hello executable. Now blazon

          ./hello                  

to run it:

Screen-Shot-2020-01-29-at-10.19.20

I prepend ./ to the program name to tell the terminal that the command is in the current folder

Awesome!

Now if you call ls -al hullo, you can meet that the program is just 12KB in size:

Screen-Shot-2020-01-29-at-10.19.55

This is ane 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 express amount of resources.

Variables and types

C is a statically typed language.

This ways that any variable has an associated type, and this type is known at compilation time.

This is very different than how y'all piece of work with variables in Python, JavaScript, PHP and other interpreted languages.

When yous create a variable in C, you accept to specify the blazon of a variable at the declaration.

In this instance we initialize a variable age with blazon int:

          int age;                  

A variable proper noun can comprise whatsoever uppercase or lowercase letter, can contain digits and the underscore graphic symbol, but it tin can't outset with a  digit. Age and Age10 are valid variable names, 1age is not.

You can also initialize a variable at declaration, specifying the initial value:

          int age = 37;                  

Once you declare a variable, you are and so able to utilize information technology in your plan code. You can change its value at any fourth dimension, using the = operator for instance, like in age = 100; (provided the new value is of the same type).

In this case:

          #include <stdio.h>  int main(void) {     int age = 0;     age = 37.2;     printf("%u", historic period); }                  

the compiler volition raise a warning at compile time, and will convert the decimal number to an integer value.

The C born data types are int, char, short, long, float, double, long double. Let's find out more near those.

Integer numbers

C provides us the following types to define integer values:

  • char
  • int
  • brusque
  • long

Virtually of the time, yous'll likely use an int to store an integer. Just in some cases, you might want to choose one of the other 3 options.

The char blazon is unremarkably used to store letters of the ASCII chart, simply information technology tin can be used to agree small integers from -128 to 127. It takes at to the lowest degree 1 byte.

int takes at least 2 bytes. short takes at least 2 bytes. long takes at least 4 bytes.

As you tin can see, we are not guaranteed the same values for different environments. Nosotros only have an indication. The problem is that the verbal numbers that tin can exist stored in each data blazon depends on the implementation and the architecture.

We're guaranteed that brusk is not longer than int. And nosotros're guaranteed long is not shorter than int.

The ANSI C spec standard determines the minimum values of each blazon, and thanks to information technology we can at to the lowest degree know what's the minimum value nosotros can look to have at our disposal.

If y'all are programming C on an Arduino, different board volition take different limits.

On an Arduino Uno lath, int stores a 2 byte value, ranging from -32,768 to 32,767. On a Arduino MKR 1010, int stores a four bytes value, ranging from -2,147,483,648 to two,147,483,647. Quite a large difference.

On all Arduino boards, short stores a 2 bytes value, ranging from -32,768 to 32,767. long store 4 bytes, ranging from -2,147,483,648 to 2,147,483,647.

Unsigned integers

For all the above data types, we tin prepend unsigned to showtime the range at 0, instead of a negative number. This might make sense in many cases.

  • unsigned char volition range from 0 to at least 255
  • unsigned int volition range from 0 to at least 65,535
  • unsigned short will range from 0 to at least 65,535
  • unsigned long volition range from 0 to at least 4,294,967,295

The problem with overflow

Given all those limits, a question might come: how can we make certain our numbers do not exceed the limit? And what happens if we do exceed the limit?

If you lot accept an unsigned int number at 255, and you lot increment it, you lot'll get 256 in return. Equally expected. If you lot take an unsigned char number at 255, and you increment it, yous'll become 0 in return. Information technology resets starting from the initial possible value.

If you have a unsigned char number at 255 and you add ten to it, you lot'll get the number nine:

          #include <stdio.h>  int principal(void) {   unsigned char j = 255;   j = j + 10;   printf("%u", j); /* 9 */ }                  

If yous don't accept a signed value, the beliefs is undefined. Information technology volition basically give you a huge number which can vary, like in this case:

          #include <stdio.h>  int main(void) {   char j = 127;   j = j + 10;   printf("%u", j); /* 4294967177 */ }                  

In other words, C does non protect you from going over the limits of a type. Y'all need to take intendance of this yourself.

Warnings when declaring the wrong type

When you declare the variable and initialize it with the wrong value, the gcc compiler (the i y'all're probably using) should warn you:

          #include <stdio.h>  int main(void) {   char j = grand; }                  
          hello.c:iv:11: warning: implicit conversion    from 'int' to       'char' changes value from 1000 to -24       [-Wconstant-conversion]         char j = 1000;              ~   ^~~~ one alarm generated.                  

And it as well warns you in direct assignments:

          #include <stdio.h>  int main(void) {   char j;   j = yard; }                  

Simply not if yous increase the number using, for example, +=:

          #include <stdio.h>  int main(void) {   char j = 0;   j += 1000; }                  

Floating point numbers

Floating point types can represent a much larger set of values than integers tin, and can also represent fractions, something that integers tin't practice.

Using floating point numbers, we stand for numbers every bit decimal numbers times powers of ten.

You might encounter floating betoken numbers written every bit

  • 1.29e-3
  • -2.3e+five

and in other seemingly weird means.

The following types:

  • float
  • double
  • long double

are used to represent numbers with decimal points (floating point types). All can correspond both positive and negative numbers.

The minimum requirements for any C implementation is that bladder can stand for a range between 10^-37 and ten^+37, and is typically implemented using 32 bits. double can correspond a bigger set of numbers. long double can concur fifty-fifty more numbers.

The exact figures, as with integer values, depend on the implementation.

On a modern Mac, a float is represented in 32 bits, and has a precision of 24 significant $.25. 8 bits are used to encode the exponent.

A double number is represented in 64 $.25, with a precision of 53 pregnant bits. 11 bits are used to encode the exponent.

The type long double is represented in 80 $.25, has a precision of 64 significant bits. 15 bits are used to encode the exponent.

On your specific estimator, how can you determine the specific size of the types? Yous tin can write a program to do that:

          #include <stdio.h>  int chief(void) {   printf("char size: %lu bytes\n", sizeof(char));   printf("int size: %lu bytes\n", sizeof(int));   printf("short size: %lu bytes\n", sizeof(short));   printf("long size: %lu bytes\n", sizeof(long));   printf("float size: %lu bytes\northward", sizeof(float));   printf("double size: %lu bytes\northward",      sizeof(double));   printf("long double size: %lu bytes\n",      sizeof(long double)); }                  

In my system, a modernistic Mac, it prints:

          char size: one bytes int size: four bytes brusque size: two bytes long size: 8 bytes float size: iv bytes double size: 8 bytes long double size: xvi bytes                  

Constants

Let's now talk about constants.

A abiding is declared similarly to variables, except it is prepended with the const keyword, and you lot always need to specify a value.

Like this:

          const int age = 37;                  

This is perfectly valid C, although it is common to declare constants uppercase, like this:

          const int Age = 37;                  

It's only a convention, only one that can profoundly help you lot while reading or writing a C program as it improves readability. Uppercase name means abiding, lowercase name means variable.

A constant name follows the same rules for variable names: tin can comprise any uppercase or lowercase letter, can contain digits and the underscore character, but information technology tin can't commencement with a digit. Historic period and Age10 are valid variable names, 1AGE is not.

Some other way to ascertain constants is by using this syntax:

          #define AGE 37                  

In this case, you don't need to add a type, and yous don't also need the = equal sign, and you omit the semicolon at the end.

The C compiler volition infer the type from the value specified, at compile time.

Operators

C offers united states a wide diversity of operators that we can use to operate on data.

In particular, nosotros can identify various groups of operators:

  • arithmetic operators
  • comparison operators
  • logical operators
  • compound assignment operators
  • bitwise operators
  • pointer operators
  • construction operators
  • miscellaneous operators

In this section I'm going to detail all of them, using ii imaginary variables a and b equally examples.

I am keeping bitwise operators, structure operators and pointer operators out of this list, to keep things simpler

Arithmetics operators

In this macro group I am going to separate binary operators and unary operators.

Binary operators work using ii operands:

Operator Name Example
= Consignment a = b
+ Addition a + b
- Subtraction a - b
* Multiplication a * b
/ Partition a / b
% Modulo a % b

Unary operators only take one operand:

Operator Name Example
+ Unary plus +a
- Unary minus -a
++ Increase a++ or ++a
-- Decrement a-- or --a

The difference between a++ and ++a is that a++ increments the a variable after using it. ++a increments the a variable before using it.

For example:

          int a = 2; int b; b = a++ /* b is 2, a is 3 */ b = ++a /* b is 4, a is iv */                  

The same applies to the decrement operator.

Comparison operators

Operator Name Instance
== Equal operator a == b
!= Not equal operator a != b
> Bigger than a > b
< Less than a < b
>= Bigger than or equal to a >= b
<= Less than or equal to a <= b

Logical operators

  • ! NOT (case: !a)
  • && AND (example: a && b)
  • || OR (example: a || b)

Those operators are great when working with boolean values.

Compound assignment operators

Those operators are useful to perform an assignment and at the same time perform an arithmetic operation:

Operator Name Example
+= Addition assignment a += b
-= Subtraction assignment a -= b
*= Multiplication assignment a *= b
/= Division assignment a /= b
%= Modulo assignment a %= b

The ternary operator

The ternary operator is the simply operator in C that works with iii operands, and information technology's a short manner to express conditionals.

This is how information technology looks:

          <condition> ? <expression> : <expression>                  

Example:

          a ? b : c                  

If a is evaluated to true, then the b statement is executed, otherwise c is.

The ternary operator is functionality-wise same equally an if/else conditional, except it is shorter to express and it can exist inlined into an expression.

sizeof

The sizeof operator returns the size of the operand y'all pass. Yous tin can pass a variable, or even a blazon.

Instance usage:

          #include <stdio.h>  int main(void) {   int historic period = 37;   printf("%ld\n", sizeof(age));   printf("%ld", sizeof(int)); }                  

Operator precedence

With all those operators (and more than, which I haven't covered in this post, including bitwise, construction operators, and arrow operators), we must pay attending when using them together in a single expression.

Suppose we have this operation:

          int a = 2; int b = 4; int c = b + a * a / b - a;                  

What'due south the value of c? Practise nosotros go the improver being executed before the multiplication and the division?

There is a set up of rules that help us solve this puzzle.

In guild from less precedence to more precedence, nosotros have:

  • the = assignment operator
  • the + and - binary operators
  • the * and / operators
  • the + and - unary operators

Operators also have an associativity rule, which is always left to correct except for the unary operators and the consignment.

In:

          int c = b + a * a / b - a;                  

We first execute a * a / b, which, due to being left-to-correct, we can split up into a * a and the result / b: 2 * 2 = four, 4 / iv = i.

Then nosotros tin can perform the sum and the subtraction: iv + one - 2. The value of c is 3.

In all cases, still, I desire to make sure you lot realize you tin utilise parentheses to make whatever similar expression easier to read and comprehend.

Parentheses have higher priority over anything else.

The above example expression can be rewritten as:

          int c = b + ((a * a) / b) - a;                  

and nosotros don't take to call back about it that much.

Conditionals

Any programming language provides the programmers the ability to perform choices.

We want to practise X in some cases, and Y in other cases.

We want to check data, and make choices based on the land of that data.

C provides united states of america 2 ways to do so.

The first is the if statement, with its else helper, and the second is the switch statement.

if

In an if argument, you can check for a condition to be truthful, and so execute the block provided in the curly brackets:

          int a = 1;  if (a == 1) {   /* exercise something */ }                  

Y'all can append an else block to execute a dissimilar block if the original status turns out to be false:

          int a = ane;  if (a == two) {   /* exercise something */ } else {   /* do something else */ }                  

Beware of i mutual source of bugs - always utilise the comparison operator == in comparisons, and not the assignment operator =. If you don't, the if conditional bank check will always be true, unless the statement is 0, for example if you exercise:

          int a = 0;  if (a = 0) {   /* never invoked */ }                  

Why does this happen? Because the conditional check will look for a boolean result (the result of a comparison), and the 0 number always equates to a fake value. Everything else is true, including negative numbers.

You tin have multiple else blocks by stacking together multiple if statements:

          int a = ane;  if (a == 2) {   /* practice something */ } else if (a == one) {   /* do something else */ } else {   /* do something else again */ }                  

switch

If you need to practice too many if / else / if blocks to perform a bank check, perchance because you demand to cheque the verbal value of a variable, then switch can exist very useful to you.

You can provide a variable as status, and a series of case entry points for each value you lot wait:

          int a = i;  switch (a) {   case 0:     /* exercise something */     break;   case one:     /* exercise something else */     pause;   case two:     /* exercise something else */     interruption; }                  

We need a interruption keyword at the stop of each case to avoid the side by side case beingness executed when the one before ends. This "cascade" effect can be useful in some creative means.

You tin add a "catch-all" example at the end, labeled default:

          int a = one;  switch (a) {   case 0:     /* do something */     break;   case i:     /* practice something else */     break;   case two:     /* exercise something else */     break;   default:     /* handle all the other cases */     break; }                  

Loops

C offers us iii ways to perform a loop: for loops, while loops and do while loops. They all allow you to iterate over arrays, merely with a few differences. Permit's see them in detail.

For loops

The first and probably most common way to perform a loop is for loops.

Using the for keyword we tin define the rules of the loop upwardly front, and and so provide the cake that is going to be executed repeatedly.

Like this:

          for (int i = 0; i <= x; i++) {   /* instructions to be repeated */ }                  

The (int i = 0; i <= 10; i++) block contains 3 parts of the looping details:

  • the initial status (int i = 0)
  • the test (i <= 10)
  • the increment (i++)

We first define a loop variable, in this case named i. i is a common variable name to be used for loops, along with j for nested loops (a loop inside another loop). It's but a convention.

The variable is initialized at the 0 value, and the first iteration is washed. Then it is incremented equally the increase role says (i++ in this case, incrementing by one), and all the cycle repeats until you get to the number 10.

Inside the loop primary block we can admission the variable i to know at which iteration we are. This program should print 0 1 two iii 4 5 five 6 seven 8 9 ten:

          for (int i = 0; i <= 10; i++) {   /* instructions to be repeated */   printf("%u ", i); }                  

Loops can too showtime from a high number, and go a lower number, similar this:

          for (int i = ten; i > 0; i--) {   /* instructions to be repeated */ }                  

You tin also increment the loop variable by 2 or some other value:

          for (int i = 0; i < 1000; i = i + thirty) {   /* instructions to be repeated */ }                  

While loops

While loops is simpler to write than a for loop, considering it requires a bit more than work on your part.

Instead of defining all the loop data upwardly front end when you lot start the loop, like you practise in the for loop, using while you only check for a status:

          while (i < 10) {  }                  

This assumes that i is already defined and initialized with a value.

And this loop will be an infinite loop unless you increment the i variable at some point within the loop. An space loop is bad because it will block the plan, allowing nothing else to happen.

This is what y'all need for a "correct" while loop:

          int i = 0;  while (i < 10) {   /* practice something */    i++; }                  

There'south ane exception to this, and we'll see it in ane minute. Before, permit me introduce practice while.

Do while loops

While loops are groovy, just there might be times when you need to practice 1 particular thing: y'all want to e'er execute a block, and then maybe repeat it.

This is done using the practise while keyword. In a style it's very similar to a while loop, but slightly dissimilar:

          int i = 0;  do {   /* do something */    i++; } while (i < 10);                  

The block that contains the /* do something */ comment is e'er executed at least once, regardless of the condition check at the bottom.

And so, until i is less than 10, nosotros'll repeat the cake.

Breaking out of a loop using interruption

In all the C loops we have a way to suspension out of a loop at any bespeak  in fourth dimension, immediately, regardless of the conditions set for the loop.

This is done using the suspension keyword.

This is useful in many cases. You might desire to check for the value of a variable, for example:

          for (int i = 0; i <= 10; i++) {   if (i == 4 && someVariable == 10) {     break;   } }                  

Having this pick to break out of a loop is specially interesting for while loops (and practise while likewise), because we can create seemingly infinite loops that end when a  condition occurs. Y'all define this inside the loop block:

          int i = 0; while (1) {   /* do something */    i++;   if (i == ten) break; }                  

It's rather mutual to have this kind of loop in C.

Arrays

An array is a variable that stores multiple values.

Every value in the array, in C, must take the same type. This means you will have arrays of int values, arrays of double values, and more.

You lot can define an array of int values like this:

          int prices[v];                  

You lot must always specify the size of the array. C does non provide dynamic arrays out of the box (you lot have to use a data construction like a linked listing for that).

You tin use a abiding to ascertain the size:

          const int SIZE = 5; int prices[SIZE];                  

Y'all tin can initialize an array at definition time, like this:

          int prices[5] = { ane, 2, 3, iv, 5 };                  

But you can also assign a value afterward the definition, in this fashion:

          int prices[5];  prices[0] = one; prices[ane] = 2; prices[ii] = 3; prices[three] = iv; prices[four] = 5;                  

Or, more practical, using a loop:

          int prices[5];  for (int i = 0; i < 5; i++) {   prices[i] = i + ane; }                  

And you can reference an item in the array past using foursquare brackets after the array variable name, adding an integer to determine the index value. Like this:

          prices[0]; /* array item value: 1 */ prices[1]; /* array item value: two */                  

Assortment indexes outset from 0, so an assortment with 5 items, like the prices array higher up, will have items ranging from prices[0] to prices[4].

The interesting matter virtually C arrays is that all elements of an array are stored sequentially, one right after some other. Not something that usually happens with higher-level programming languages.

Another interesting affair is this: the variable name of the assortment, prices in the higher up case, is a arrow to the kickoff element of the array. As such it can be used like a normal pointer.

More on pointers soon.

Strings

In C, strings are one special kind of array: a string is an array of char values:

          char name[7];                  

I introduced the char type when I introduced types, but in curt it is unremarkably used to store letters of the ASCII chart.

A string can be initialized like you initialize a normal array:

          char proper noun[7] = { "F", "50", "a", "5", "i", "o" };                  

Or more conveniently with a string literal (also called string abiding), a sequence of characters enclosed in double quotes:

          char name[7] = "Flavio";                  

You can print a cord via printf() using %s:

          printf("%southward", name);                  

Do y'all notice how "Flavio" is 6 chars long, just I defined an assortment of length 7? Why? This is because the last character in a string must exist a0 value, the string terminator, and we must make infinite for it.

This is important to keep in mind peculiarly when manipulating strings.

Speaking of manipulating strings, there'due south one important standard library that is provided by C: string.h.

This library is essential because it abstracts many of the low level details of working with strings, and provides usa with a fix of useful functions.

Y'all tin can load the library in your program by calculation on top:

          #include <string.h>                  

And once y'all do that, you have admission to:

  • strcpy() to copy a cord over some other string
  • strcat() to append a cord to another string
  • strcmp() to compare ii strings for equality
  • strncmp() to compare the first n characters of 2 strings
  • strlen() to summate the length of a string

and many, many more.

Pointers

Pointers are one of the virtually confusing/challenging parts of C, in my opinion. Especially if you are new to programming, but also if y'all come from a higher level programming language similar 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 retention that contains a variable.

When you declare an integer number like this:

          int age = 37;                  

We can utilise the & operator to become the value of the address in retention of a variable:

          printf("%p", &historic period); /* 0x7ffeef7dcb9c */                  

I used the %p format specified in printf() to print the address value.

We can assign the address to a variable:

          int *address = &age;                  

Using int *address in the declaration, we are not declaring an integer variable, but rather a arrow to an integer.

We can utilize the arrow operator * to get the value of the variable an address is pointing to:

          int age = 37; int *address = &historic period; printf("%u", *address); /* 37 */                  

This time we are using the pointer operator again, but since it's non a proclamation this time it means "the value of the variable this arrow points to".

In this example we declare an historic period variable, and we employ a pointer to initialize the value:

          int age; int *address = &age; *address = 37; printf("%u", *address);                  

When working with C, you'll observe that a lot of things are built on pinnacle of this simple concept. And so make sure y'all familiarize with it a scrap by running the higher up examples on your own.

Pointers are a corking opportunity because they force us to think about retentivity addresses and how data is organized.

Arrays are i example. When you declare an array:

          int prices[3] = { 5, 4, three };                  

The prices variable is actually a pointer to the get-go item of the assortment. You tin can get the value of the beginning item using this printf() function in this example:

          printf("%u", *prices); /* five */                  

The cool affair is that we can become the second item by adding 1 to the prices pointer:

          printf("%u", *(prices + 1)); /* 4 */                  

And and then on for all the other values.

We can as well do many nice string manipulation operations, since strings are arrays under the hood.

We besides have many more applications, including passing the reference of an object or a role around to avert consuming more than resources to re-create information technology.

Functions

Functions are the mode we can structure our code into subroutines that nosotros tin can:

  1. requite a name to
  2. telephone call when we need them

Starting from your very beginning program, a "Hello, World!", yous immediately make apply of C functions:

          #include <stdio.h>  int main(void) {     printf("Hullo, World!"); }                  

The chief() function is a very of import function, as it'south the entry point for a C program.

Here's another function:

          void doSomething(int value) {     printf("%u", value); }                  

Functions have 4 important aspects:

  1. they accept a name, so nosotros can invoke ("phone call") them later
  2. they specify a return value
  3. they can take arguments
  4. they have a body, wrapped in curly braces

The function body is the set of instructions that are executed any time we invoke a function.

If the function has no render value, you tin can use the keyword void before the function name. Otherwise you specify the part return value type (int for an integer, float for a floating indicate value, const char * for a string, etc).

You cannot return more one value from a office.

A function tin have arguments. They are optional. If information technology does non accept them, within the parentheses nosotros insert void, similar this:

          void doSomething(void) {    /* ... */ }                  

In this case, when we invoke the office we'll call it with nothing in the parentheses:

          doSomething();                  

If nosotros have one parameter, we specify the type and the name of the parameter, similar this:

          void doSomething(int value) {    /* ... */ }                  

When we invoke the office, we'll pass that parameter in the parentheses, like this:

          doSomething(3);                  

We tin can take multiple parameters, and if so we split up them using a comma, both in the declaration and in the invocation:

          void doSomething(int value1, int value2) {    /* ... */ }  doSomething(3, 4);                  

Parameters are passed past copy. This ways that if you modify value1, its value is modified locally. The value outside of the office, where it was passed in the invocation, does non change.

If you pass a pointer equally a parameter, you tin can modify that variable value because y'all can now access it directly using its memory address.

You tin can't ascertain a default value for a parameter. C++ tin can exercise that (and and then Arduino Language programs can), but C can't.

Make sure you define the function before calling it, or the compiler volition enhance a warning and an mistake:

          ➜  ~ gcc hello.c -o hello; ./hello hello.c:thirteen:3: warning: implicit declaration of       office 'doSomething' is invalid in C99       [-Wimplicit-function-declaration]   doSomething(3, iv);   ^ hullo.c:17:vi: error: conflicting types for       'doSomething' void doSomething(int value1, char value2) {      ^ hello.c:thirteen:3: note: previous implicit annunciation       is here   doSomething(3, 4);   ^ 1 warning and ane error generated.                  

The alert y'all get regards the ordering, which I already mentioned.

The error is about another thing, related. Since C does not "come across" the function declaration earlier the invocation, it must make assumptions. And it assumes the function to return int. The function however returns void, hence the error.

If you change the function definition to:

          int doSomething(int value1, int value2) {   printf("%d %d\n", value1, value2);   return 1; }                  

you'd merely become the alarm, and not the fault:

          ➜  ~ gcc hello.c -o how-do-you-do; ./howdy hello.c:14:three: warning: implicit proclamation of       function 'doSomething' is invalid in C99       [-Wimplicit-office-declaration]   doSomething(3, 4);   ^ ane alert generated.                  

In any case, make certain y'all declare the function before using it. Either move the function upwards, or add together the part prototype in a header file.

Within a function, you can declare variables.

          void doSomething(int value) {   int doubleValue = value * ii; }                  

A variable is created at the betoken of invocation of the part and is destroyed when the office 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 output

C is a minor language, and the "core" of C does not include any Input/Output (I/O) functionality.

This is non something unique to C, of course. It's common for the language core to exist agnostic of I/O.

In the instance of C, Input/Output is provided to us past the C Standard Library via a prepare of functions defined in the stdio.h header file.

You tin can import this library using:

          #include <stdio.h>                  

on top of your C file.

This library provides us with, among many other functions:

  • printf()
  • scanf()
  • sscanf()
  • fgets()
  • fprintf()

Before describing what those functions practise, I want to take a infinitesimal to talk about I/O streams.

We have three kinds of I/O streams in C:

  • stdin (standard input)
  • stdout (standard output)
  • stderr (standard error)

With I/O functions we ever work with streams. A stream is a high level interface that tin can correspond a device or a file. From the C standpoint, nosotros don't have whatsoever difference in reading from a file or reading from the command line: it'southward an I/O stream in whatsoever example.

That's one thing to go on in mind.

Some functions are designed to piece of work with a specific stream, like printf(), which we utilise to print characters to stdout. Using its more general counterpart fprintf(), nosotros tin can specify which stream to write to.

Since I started talking about printf(), let's innovate it now.

printf() is i of the outset functions you'll use when learning C programming.

In its simplest usage course, you laissez passer information technology a cord literal:

          printf("hey!");                  

and the program will print the content of the cord to the screen.

You can print the value of a variable. Just information technology's a fleck catchy because you demand to add a special grapheme, a placeholder, which changes depending on the type of the variable. For case we use %d for a signed decimal integer digit:

          int age = 37;  printf("My age is %d", age);                  

We can print more than 1 variable by using commas:

          int age_yesterday = 37; int age_today = 36;  printf("Yesterday my age was %d and today is %d", age_yesterday, age_today);                  

In that location are other format specifiers like %d:

  • %c for a char
  • %southward for a char
  • %f for floating signal numbers
  • %p for pointers

and many more.

We can use escape characters in printf(), like \n which nosotros tin use to make the output create a new line.

scanf()

printf() is used equally an output function. I desire to introduce an input function now, so we can say nosotros can practice all the I/O thing: scanf().

This part is used to get a value from the user running the program, from the command line.

Nosotros must commencement define a variable that will hold the value we get from the input:

          int age;                  

And then we call scanf() with ii arguments: the format (type) of the variable, and the address of the variable:

          scanf("%d", &age);                  

If we want to get a string as input, remember that a string name is a arrow to the kickoff character, and so you don't need the & character before information technology:

          char name[20]; scanf("%s", name);                  

Here's a little program that uses both printf() and scanf():

          #include <stdio.h>  int main(void) {   char name[20];   printf("Enter your proper name: ");   scanf("%due south", proper name);   printf("you entered %s", name); }                  

Variable scope

When you ascertain a variable in a C program, depending on where you declare it, it volition take a different scope.

This means that it will be available in some places, but not in others.

The position determines 2 types of variables:

  • global variables
  • local variables

This is the deviation: a variable declared inside a function is a local variable, similar this:

          int main(void) {   int historic period = 37; }                  

Local variables are only accessible from within the function, and when the role ends they terminate their existence. They are cleared from the memory (with some exceptions).

A variable defined outside a office is a global variable, like in this case:

          int age = 37;  int main(void) {   /* ... */ }                  

Global variables are attainable from whatsoever role of the plan, and they are available for the whole execution of the program, until information technology ends.

I mentioned that local variables are not bachelor any more than afterwards the part ends.

The reason is that local variables are declared on the stack, by default, unless you explicitly classify them on the heap using pointers. Merely and so you take to manage the memory yourself.

Static variables

Within a function, you lot tin initialize a static variable using the static keyword.

I said "inside a function" because global variables are static by default, so there's no need to add the keyword.

What'southward a static variable? A static variable is initialized to 0 if no initial value is specified, and it retains the value across part calls.

Consider this function:

          int incrementAge() {   int historic period = 0;   historic period++;   return age; }                  

If we phone call incrementAge() once, nosotros'll get 1 as the return value. If nosotros telephone call it more than than once, we'll always get ane back, because age is a local variable and it's re-initialized to 0 on every single part call.

If we change the function to:

          int incrementAge() {   static int age = 0;   age++;   return age; }                  

Now every time we phone call this function, we'll get an incremented value:

          printf("%d\north", incrementAge()); printf("%d\northward", incrementAge()); printf("%d\n", incrementAge());                  

will give us

          1 2 three                  

We tin too omit initializing age to 0 in static int age = 0;, and just write static int age; considering static variables are automatically ready to 0 when created.

We tin can as well take static arrays. In this case, each single particular in the array is initialized to 0:

          int incrementAge() {   static int ages[3];   ages[0]++;   render ages[0]; }                  

Global variables

In this section I want to talk more than about the difference between global and local variables.

A local variable is defined inside a function, and it'due south only available within that part.

Like this:

          #include <stdio.h>  int main(void) {   char j = 0;   j += 10;   printf("%u", j); //10 }                  

j is non available anywhere exterior the main function.

A global variable is defined outside of any office, similar this:

          #include <stdio.h>  char i = 0;  int primary(void) {   i += 10;   printf("%u", i); //10 }                  

A global variable can be accessed by any office in the programme.  Access is non limited to reading the value: the variable can be updated by any office.

Due to this, global variables are one way we have of sharing the aforementioned data between functions.

The main difference with local variables is that the retention allocated for variables is freed once the office ends.

Global variables are but freed when the program ends.

Blazon definitions

The typedef keyword in C allows yous to defined new types.

Starting from the built-in C types, we can create our own types, using this syntax:

          typedef existingtype NEWTYPE                  

The new blazon nosotros create is usually, by convention, upper-case letter.

This it to distinguish it more easily, and immediately recognize it equally type.

For case we can ascertain a new NUMBER type that is an int:

          typedef int NUMBER                  

and once y'all exercise so, you tin define new NUMBER variables:

          NUMBER i = 1;                  

At present y'all might inquire: why? Why not just use the built-in type int instead?

Well, typedef gets really useful when paired with two things: enumerated types and structures.

Enumerated types

Using the typedef and enum keywords nosotros tin define a type that can have either ane value or another.

It'southward one of the nearly of import uses of the typedef keyword.

This is the syntax of an enumerated type:

          typedef enum {   //...values } TYPENAME;                  

The enumerated type we create is commonly, past convention, uppercase.

Here is a uncomplicated example:

          typedef enum {   true,   imitation } BOOLEAN;                  

C comes with a bool type, and so this example is not really practical, but y'all become the thought.

Some other case is to ascertain weekdays:

          typedef enum {   monday,     tuesday,   wednesday,   thursday,   friday,   sat,   sunday } WEEKDAY;                  

Here's a simple program that uses this enumerated blazon:

          #include <stdio.h>  typedef enum {   monday,     tuesday,   wed,   th,   fri,   saturday,   dominicus } WEEKDAY;  int main(void) {   WEEKDAY day = monday;    if (24-hour interval == monday) {     printf("It'southward monday!");    } else {     printf("It'south not monday");    } }                  

Every item in the enum definition is paired to an integer, internally. So in this example mon is 0, tuesday is i and so on.

This means the conditional could have been if (day == 0) instead of if (day == mon), but it's mode simpler for us humans to reason with names rather than numbers, so it'due south a very convenient syntax.

Structures

Using the struct keyword we can create complex data structures using basic C types.

A structure is a drove of values of different types. Arrays in C are limited to a type, so structures tin prove to exist very interesting in a lot of use cases.

This is the syntax of a structure:

          struct <structname> {   //...variables };                  

Example:

          struct person {   int age;   char *name; };                  

You lot tin declare variables that have as type that structure by calculation them after the endmost curly bracket, before the semicolon, like this:

          struct person {   int age;   char *proper noun; } flavio;                  

Or multiple ones, like this:

          struct person {   int historic period;   char *name; } flavio, people[20];                  

In this case I declare a single person variable named flavio, and an assortment of twenty person named people.

We tin also declare variables after on, using this syntax:

          struct person {   int age;   char *proper name; };  struct person flavio;                  

We can initialize a structure at declaration fourth dimension:

          struct person {   int age;   char *name; };  struct person flavio = { 37, "Flavio" };                  

and once nosotros take a construction divers, we can access the values in it using a dot:

          struct person {   int historic period;   char *name; };  struct person flavio = { 37, "Flavio" }; printf("%due south, age %u", flavio.name, flavio.historic period);                  

We can also change the values using the dot syntax:

          struct person {   int age;   char *name; };  struct person flavio = { 37, "Flavio" };  flavio.age = 38;                  

Structures are very useful because nosotros can laissez passer them around as part parameters, or render values, embedding various variables within them. Each variable has a label.

It's important to annotation that structures are passed by copy, unless of course you pass a arrow to a struct, in which case information technology'south passed by reference.

Using typedef nosotros tin simplify the code when working with structures.

Let'southward look at an example:

          typedef struct {   int age;   char *proper noun; } PERSON;                  

The structure nosotros create using typedef is usually, past convention, upper-case letter.

Now nosotros can declare new PERSON variables like this:

          PERSON flavio;                  

and we tin initialize them at proclamation in this manner:

          PERSON flavio = { 37, "Flavio" };                  

Control line parameters

In your C programs, you might demand to have parameters from the control line when the command launches.

For simple needs, all you lot need to do to exercise so is change the chief() function signature from

          int main(void)                  

to

          int chief (int argc, char *argv[])                  

argc is an integer number that contains the number of parameters that were provided in the control line.

argv is an assortment of strings.

When the program starts, we are provided the arguments in those 2 parameters.

Note that there's always at to the lowest degree 1 particular in the argv array: the name of the plan

Let's take the example of the C compiler we use to run our programs, like this:

          gcc how-do-you-do.c -o hello                  

If this was our program, we'd accept argc beingness iv and argv being an array containing

  • gcc
  • hullo.c
  • -o
  • hello

Permit's write a program that prints the arguments it receives:

          #include <stdio.h>  int main (int argc, char *argv[]) {   for (int i = 0; i < argc; i++) {     printf("%due south\n", argv[i]);   } }                  

If the proper name of our program is howdy and we run it similar this: ./hi, we'd get this as output:

          ./hello                  

If we pass some random parameters, like this: ./how-do-you-do a b c we'd become this output to the terminal:

          ./how-do-you-do a b c                  

This system works bully for simple needs. For more than complex needs, in that location are usually used packages similar getopt.

Uncomplicated programs tin be put in a unmarried file. Merely when your program grows larger it'southward incommunicable to keep it all in just one file.

You tin move parts of a plan to a split file. Then you create a header file.

A header file looks like a normal C file, except information technology ends with .h instead of .c. Instead of the implementations of your functions and the other parts of a program, it holds the declarations.

You already used header files when you beginning used the printf() function, or other I/O part, and you had to type:

          #include <stdio.h>                  

to use information technology.

#include is a preprocessor directive.

The preprocessor goes and looks upwardly the stdio.h file in the standard library because you used brackets around it. To include your ain header files, you'll use quotes, like this:

          #include "myfile.h"                  

The above will look up myfile.h in the electric current binder.

You tin can also use a folder structure for libraries:

          #include "myfolder/myfile.h"                  

Let'southward expect at an example. This programme calculates the years since a given twelvemonth:

          #include <stdio.h>  int calculateAge(int year) {   const int CURRENT_YEAR = 2020;   return CURRENT_YEAR - year; }  int main(void) {   printf("%u", calculateAge(1983)); }                  

Suppose I want to motion the calculateAge function to a separate file.

I create a calculate_age.c file:

          int calculateAge(int year) {   const int CURRENT_YEAR = 2020;   return CURRENT_YEAR - year; }                  

And a calculate_age.h file where I put the office prototype, which is the same equally the office in the .c file, except the trunk:

          int calculateAge(int twelvemonth);                  

At present in the main .c file we can become and remove the calculateAge() function definition, and we can import calculate_age.h, which will make the calculateAge() office bachelor:

          #include <stdio.h> #include "calculate_age.h"  int chief(void) {   printf("%u", calculateAge(1983)); }                  

Don't forget that to compile a program equanimous past multiple files, yous need to list them all in the control line, like this:

          gcc -o main primary.c calculate_age.c                  

And with more circuitous setups, a Makefile is necessary to tell the compiler how to compile the programme.

The preprocessor

The preprocessor is a tool that helps us a lot when programming with C. It is role of the C Standard, just like the linguistic communication, the compiler, and the standard library.

It parses our program and makes sure that the compiler gets all the things it needs earlier going on with the process.

What does it exercise, in practise?

For example, information technology looks up all the header files you include with the #include directive.

It also looks at every constant you lot defined using #ascertain and substitutes it with its actual value.

That's simply the start. I mentioned those ii operations considering they are the most common ones. The preprocessor tin do a lot more.

Did you notice #include and #ascertain have a # at the beginning? That's common to all the preprocessor directives. If a line starts with #, that's taken care of by the preprocessor.

Conditionals

Ane of the things nosotros can do is to use conditionals to change how our plan volition be compiled, depending on the value of an expression.

For example we tin can cheque if the DEBUG constant is 0:

          #include <stdio.h>  const int DEBUG = 0;  int main(void) { #if DEBUG == 0   printf("I am NOT debugging\n"); #else   printf("I am debugging\n"); 

0 Response to "Do You Have to Know C Before Learning C++"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel