Learning C# 8 and net Core 30 Review

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

This approach volition give you a well-rounded overview of the language.

This handbook does not try to cover everything under the lord's day related to C. It focuses on the core of the language, trying to simplify the more complex topics.

And notation: You tin can get a PDF and ePub version of this C Beginner's Handbook here.

Enjoy!

Table 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. Blazon 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 about widely known programming language. It is used as the reference language for informatics courses all over the globe, and information technology's probably the language that people learn the most in school along with Python and Coffee.

I remember it being my second programming language always, afterwards Pascal.

C is not but what students use to larn programming. It's not an academic language. And I would say information technology's not the easiest language, because C is a rather low level programming language.

Today, C is widely used in embedded devices, and information technology powers virtually of the Cyberspace servers, which are congenital using Linux. The Linux kernel is congenital using C, and this too means that C powers the cadre of all Android devices. We tin can say that C code runs a good portion of the unabridged globe. Right now. Pretty remarkable.

When it was created, C was considered a high level language, because information technology was portable across machines. Today nosotros kind of have for granted that we tin run a program written on a Mac on Windows or Linux, perhaps using Node.js or Python.

Once upon a fourth dimension, 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 Become, 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 non garbage collected. This means we have to manage retentiveness 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 non hibernate the complexity and the capabilities of the machine underneath. You have a lot of power, once you know what you tin can practice.

I desire to introduce the get-go C program at present, which we'll telephone call "Hello, World!"

hullo.c

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

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

This library gives u.s. access to input/output functions.

C is a very small language at its cadre, and annihilation that's not part of the cadre is provided by libraries. Some of those libraries are congenital by normal programmers, and made available for others to apply. Some other libraries are built into the compiler. Like stdio and others.

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

This function is wrapped into a main() role. The primary() function is the entry point of any C programme.

But what is a role, anyway?

A function is a routine that takes one or more arguments, and returns a unmarried value.

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

The office has a body, which is wrapped in curly braces. Within the body nosotros have all the code that the function needs to perform its operations.

The printf() function is written differently, as yous can see. Information technology has no render value divers, and we laissez passer a string, wrapped in double quotes. We didn't specify the blazon of the statement.

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

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

Yous don't need to empathise what this ways now, but in short, this is the definition. And when we call printf("Hi, Globe!");, that'southward where the office is run.

The main() function we defined in a higher place:

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

volition exist run by the operating organisation when the program is executed.

How practise nosotros execute a C program?

As mentioned, C is a compiled language. To run the program we must get-go compile information technology. Any Linux or macOS computer already comes with a C compiler congenital-in. For Windows, yous tin apply the Windows Subsystem for Linux (WSL).

In any case, when you open up the concluding window you can type gcc, and this control should render an error saying that you didn't specify whatever file:

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

That's good. It ways the C compiler is there, and nosotros tin start using it.

Now type the plan above into a hullo.c file. You can employ any editor, simply for the sake of simplicity I'g 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

At present press ctrl-X to leave:

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

Ostend past pressing the y key, then printing enter to ostend the file name:

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

That'south it, we should be back to the final at present:

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

Now type

          gcc hello.c -o hello                  

The program should give y'all no errors:

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

but it should have generated a hello executable. Now type

          ./how-do-you-do                  

to run information technology:

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 electric current folder

Awesome!

At present if you lot call ls -al hello, you can see that the programme is but 12KB in size:

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

This is 1 of the pros of C: it'southward highly optimized, and this is besides ane of the reasons it's this good for embedded devices that accept a very express corporeality of resources.

Variables and types

C is a statically typed linguistic communication.

This ways 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 y'all create a variable in C, yous have to specify the type of a variable at the declaration.

In this example nosotros initialize a variable age with type int:

          int age;                  

A variable proper noun can contain any uppercase or lowercase letter, tin can contain digits and the underscore character, but information technology can't start with a  digit. Historic period and Age10 are valid variable names, 1age is not.

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

          int age = 37;                  

One time you declare a variable, you are so able to use it in your program lawmaking. You can change its value at whatever fourth dimension, using the = operator for example, similar in age = 100; (provided the new value is of the aforementioned type).

In this case:

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

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

The C congenital-in data types are int, char, short, long, bladder, double, long double. Let's notice out more nearly those.

Integer numbers

C provides united states of america the following types to define integer values:

  • char
  • int
  • brusk
  • long

Nearly of the time, you lot'll likely use an int to store an integer. But in some cases, you might want to cull i of the other 3 options.

The char type is commonly used to shop messages of the ASCII nautical chart, simply it can be used to concord small integers from -128 to 127. Information technology takes at least 1 byte.

int takes at least 2 bytes. short takes at to the lowest degree 2 bytes. long takes at least four bytes.

Equally yous can run into, we are non guaranteed the aforementioned values for different environments. We but take an indication. The trouble is that the exact numbers that can be stored in each data type depends on the implementation and the architecture.

We're guaranteed that short is not longer than int. And we'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 least know what'southward the minimum value nosotros can expect to have at our disposal.

If you are programming C on an Arduino, dissimilar board will have dissimilar limits.

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

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

Unsigned integers

For all the to a higher place data types, we can prepend unsigned to start the range at 0, instead of a negative number. This might make sense in many cases.

  • unsigned char will range from 0 to at to the lowest degree 255
  • unsigned int volition range from 0 to at least 65,535
  • unsigned brusque will range from 0 to at least 65,535
  • unsigned long will range from 0 to at least four,294,967,295

The problem with overflow

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

If you accept an unsigned int number at 255, and you increment it, yous'll go 256 in render. As expected. If you lot have an unsigned char number at 255, and you increment information technology, yous'll get 0 in render. It resets starting from the initial possible value.

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

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

If you don't have a signed value, the behavior is undefined. Information technology will basically requite you a huge number which can vary, like in this case:

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

In other words, C does not protect you from going over the limits of a type. You need to accept intendance of this yourself.

Warnings when declaring the wrong type

When you declare the variable and initialize information technology with the wrong value, the gcc compiler (the one you're probably using) should warn you:

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

And it also warns y'all in direct assignments:

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

Simply non if you increment the number using, for instance, +=:

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

Floating point numbers

Floating indicate types can represent a much larger gear up of values than integers can, and tin also represent fractions, something that integers can't practise.

Using floating bespeak numbers, we represent numbers as decimal numbers times powers of 10.

You might see floating point numbers written as

  • ane.29e-3
  • -ii.3e+five

and in other seemingly weird ways.

The post-obit types:

  • float
  • double
  • long double

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

The minimum requirements for whatever C implementation is that float tin represent a range betwixt 10^-37 and 10^+37, and is typically implemented using 32 $.25. double can stand for a bigger set up of numbers. long double tin can agree even more numbers.

The exact figures, every bit 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 bits. 8 bits are used to encode the exponent.

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

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

On your specific computer, how can you determine the specific size of the types? You lot tin can write a program to exercise that:

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

In my system, a modernistic Mac, it prints:

          char size: 1 bytes int size: 4 bytes brusque size: 2 bytes long size: 8 bytes bladder size: four bytes double size: 8 bytes long double size: 16 bytes                  

Constants

Permit's at present talk well-nigh constants.

A constant is alleged similarly to variables, except it is prepended with the const keyword, and you lot e'er need to specify a value.

Like this:

          const int age = 37;                  

This is perfectly valid C, although information technology is common to declare constants uppercase, similar this:

          const int AGE = 37;                  

It'south just a convention, but ane that can greatly help you while reading or writing a C program every bit it improves readability. Majuscule name ways constant, lowercase proper name means variable.

A constant proper name follows the aforementioned rules for variable names: can contain whatever majuscule or lowercase letter, tin incorporate digits and the underscore grapheme, but it tin't offset with a digit. Historic period and Age10 are valid variable names, 1AGE is not.

Another fashion to ascertain constants is by using this syntax:

          #define AGE 37                  

In this case, you lot don't need to add a type, and you don't as well demand the = equal sign, and you omit the semicolon at the end.

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

Operators

C offers us a wide diverseness of operators that we can utilise to operate on data.

In particular, we can identify diverse groups of operators:

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

In this department I'm going to detail all of them, using 2 imaginary variables a and b as examples.

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

Arithmetic operators

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

Binary operators work using two operands:

Operator Name Instance
= Assignment a = b
+ Add-on a + b
- Subtraction a - b
* Multiplication a * b
/ Sectionalization a / b
% Modulo a % b

Unary operators only take ane operand:

Operator Name Case
+ Unary plus +a
- Unary minus -a
++ Increment a++ or ++a
-- Decrement a-- or --a

The difference betwixt a++ and ++a is that a++ increments the a variable after using information technology. ++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 4 */                  

The same applies to the decrement operator.

Comparison operators

Operator Proper noun 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 (example: !a)
  • && AND (case: a && b)
  • || OR (example: a || b)

Those operators are neat when working with boolean values.

Compound assignment operators

Those operators are useful to perform an consignment and at the aforementioned time perform an arithmetic performance:

Operator Proper name Instance
+= Improver 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 only operator in C that works with 3 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 truthful, then the b statement is executed, otherwise c is.

The ternary operator is functionality-wise same every bit an if/else conditional, except information technology is shorter to express and information technology can be inlined into an expression.

sizeof

The sizeof operator returns the size of the operand y'all pass. You tin pass a variable, or even a type.

Case usage:

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

Operator precedence

With all those operators (and more, which I haven't covered in this mail service, including bitwise, construction operators, and pointer operators), we must pay attention 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's the value of c? Practise we get the add-on being executed before the multiplication and the sectionalization?

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

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

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

Operators too have an associativity dominion, which is always left to right except for the unary operators and the assignment.

In:

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

We showtime execute a * a / b, which, due to existence left-to-right, nosotros can separate into a * a and the issue / b: 2 * 2 = 4, iv / 4 = 1.

Then nosotros can perform the sum and the subtraction: 4 + 1 - 2. The value of c is iii.

In all cases, however, I desire to brand sure yous realize you tin utilize parentheses to make any similar expression easier to read and comprehend.

Parentheses have college priority over anything else.

The above instance expression tin be rewritten every bit:

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

and nosotros don't take to call up most information technology that much.

Conditionals

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

We want to practice 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 2nd is the switch statement.

if

In an if argument, y'all can cheque for a condition to be true, then execute the cake provided in the curly brackets:

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

You tin suspend an else cake to execute a unlike cake if the original condition turns out to be imitation:

          int a = i;  if (a == 2) {   /* do something */ } else {   /* exercise something else */ }                  

Beware of one common source of bugs - always use the comparison operator == in comparisons, and not the assignment operator =. If you lot don't, the if conditional bank check will always be true, unless the argument is 0, for example if you practice:

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

Why does this happen? Because the provisional check will await for a boolean result (the outcome of a comparison), and the 0 number e'er equates to a false value. Everything else is true, including negative numbers.

Y'all tin take multiple else blocks past stacking together multiple if statements:

          int a = 1;  if (a == two) {   /* do something */ } else if (a == one) {   /* do something else */ } else {   /* do something else over again */ }                  

switch

If you demand to practice also many if / else / if blocks to perform a check, perhaps because y'all need to check the exact value of a variable, then switch can be very useful to yous.

You lot tin provide a variable as condition, and a series of case entry points for each value you expect:

          int a = 1;  switch (a) {   example 0:     /* do something */     interruption;   example 1:     /* practice something else */     break;   case 2:     /* practice something else */     break; }                  

We need a break keyword at the finish of each instance to avert the adjacent case existence executed when the i before ends. This "cascade" effect tin can exist useful in some artistic ways.

You can add together a "take hold of-all" instance at the end, labeled default:

          int a = 1;  switch (a) {   case 0:     /* do something */     pause;   case 1:     /* do something else */     break;   case 2:     /* exercise something else */     break;   default:     /* handle all the other cases */     intermission; }                  

Loops

C offers u.s.a. 3 means to perform a loop: for loops, while loops and practice while loops. They all allow you to iterate over arrays, but with a few differences. Let'southward meet them in item.

For loops

The start and probably most common style to perform a loop is for loops.

Using the for keyword we can define the rules of the loop up front, and and so provide the block that is going to exist executed repeatedly.

Like this:

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

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

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

We offset define a loop variable, in this case named i. i is a common variable proper name to exist used for loops, along with j for nested loops (a loop inside another loop). It'southward only a convention.

The variable is initialized at the 0 value, and the kickoff iteration is done. And then it is incremented as the increment role says (i++ in this instance, incrementing by 1), and all the cycle repeats until you get to the number 10.

Inside the loop main block we can access the variable i to know at which iteration we are. This program should impress 0 1 2 3 four 5 5 half dozen 7 eight ix 10:

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

Loops tin likewise showtime from a high number, and go a lower number, similar this:

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

You can also increment the loop variable by 2 or another value:

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

While loops

While loops is simpler to write than a for loop, because it requires a flake more piece of work on your function.

Instead of defining all the loop data upwardly front when you starting time the loop, similar you do in the for loop, using while you lot just check for a condition:

          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 lot increment the i variable at some point inside the loop. An infinite loop is bad because it will block the plan, allowing nothing else to happen.

This is what you need for a "correct" while loop:

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

There'southward 1 exception to this, and we'll see it in i minute. Earlier, let me introduce do while.

Do while loops

While loops are bang-up, but there might be times when you demand to do ane particular matter: you want to always execute a cake, and and then mayhap repeat it.

This is done using the do while keyword. In a fashion it'due south very similar to a while loop, but slightly different:

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

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

Then, until i is less than 10, we'll repeat the block.

Breaking out of a loop using break

In all the C loops we have a way to pause out of a loop at whatever point  in time, immediately, regardless of the conditions set for the loop.

This is done using the break keyword.

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

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

Having this option to break out of a loop is especially interesting for while loops (and exercise while as well), because we tin can create seemingly infinite loops that end when a  condition occurs. You define this inside the loop block:

          int i = 0; while (i) {   /* practice something */    i++;   if (i == x) break; }                  

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

Arrays

An assortment is a variable that stores multiple values.

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

You tin ascertain an array of int values similar this:

          int prices[5];                  

You must ever specify the size of the array. C does non provide dynamic arrays out of the box (you have to use a information structure like a linked list for that).

You can apply a constant to define the size:

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

You can initialize an array at definition time, like this:

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

Simply you can also assign a value after the definition, in this way:

          int prices[5];  prices[0] = 1; prices[1] = 2; prices[two] = 3; prices[3] = 4; prices[4] = 5;                  

Or, more practical, using a loop:

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

And you can reference an detail in the array by using square brackets subsequently the assortment variable proper noun, adding an integer to decide the index value. Similar this:

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

Array indexes kickoff from 0, and then an array with v items, like the prices assortment above, will take items ranging from prices[0] to prices[four].

The interesting thing about C arrays is that all elements of an array are stored sequentially, one correct after another. Non something that usually happens with higher-level programming languages.

Another interesting matter is this: the variable name of the array, prices in the higher up example, is a arrow to the beginning chemical element of the assortment. Equally such it tin can be used similar a normal arrow.

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 blazon when I introduced types, just in brusk it is commonly used to store messages of the ASCII chart.

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

          char proper name[7] = { "F", "l", "a", "v", "i", "o" };                  

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

          char name[7] = "Flavio";                  

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

          printf("%south", name);                  

Practise you notice how "Flavio" is 6 chars long, merely I defined an assortment of length 7? Why? This is considering the terminal graphic symbol in a string must exist a0 value, the cord terminator, and we must brand space for it.

This is of import to continue in mind specially when manipulating strings.

Speaking of manipulating strings, in that location's one important standard library that is provided past C: string.h.

This library is essential considering information technology abstracts many of the depression level details of working with strings, and provides us with a set of useful functions.

Yous can load the library in your plan by adding on top:

          #include <string.h>                  

And once you do that, you have access to:

  • strcpy() to re-create a string over another string
  • strcat() to append a string to another cord
  • strcmp() to compare two strings for equality
  • strncmp() to compare the starting time due north characters of two strings
  • strlen() to summate the length of a string

and many, many more.

Pointers

Pointers are one of the well-nigh confusing/challenging parts of C, in my stance. Particularly if you are new to programming, but also if you come from a higher level programming linguistic communication like Python or JavaScript.

In this section I want to innovate them in the simplest even so not-dumbed-down manner possible.

A pointer is the accost of a block of memory that contains a variable.

When yous declare an integer number like this:

          int age = 37;                  

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

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

I used the %p format specified in printf() to impress the accost value.

We can assign the address to a variable:

          int *address = &age;                  

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

We can use the pointer operator * to go the value of the variable an address is pointing to:

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

This time we are using the pointer operator again, but since it's not a declaration this time it ways "the value of the variable this pointer points to".

In this example we declare an age variable, and we use a pointer to initialize the value:

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

When working with C, you'll discover that a lot of things are built on top of this simple concept. So make sure you lot familiarize with information technology a bit by running the above examples on your ain.

Pointers are a great opportunity considering they strength us to remember about memory addresses and how data is organized.

Arrays are i example. When y'all declare an array:

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

The prices variable is really a pointer to the starting time item of the assortment. Yous can get the value of the first item using this printf() function in this case:

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

The cool affair is that we tin get the second item by calculation 1 to the prices pointer:

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

And and then on for all the other values.

We can also practise many nice string manipulation operations, since strings are arrays under the hood.

We as well take many more applications, including passing the reference of an object or a function effectually to avoid consuming more resource to copy it.

Functions

Functions are the way we can structure our lawmaking into subroutines that we can:

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

Starting from your very first programme, a "Hello, Globe!", you immediately make utilize of C functions:

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

The main() function is a very important function, as information technology's the entry point for a C programme.

Here's another function:

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

Functions have 4 of import aspects:

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

The function body is the set of instructions that are executed whatsoever time nosotros invoke a function.

If the function has no return value, yous tin utilize the keyword void before the part name. Otherwise yous specify the function return value type (int for an integer, bladder for a floating point value, const char * for a cord, etc).

You cannot return more than than one value from a function.

A role can have arguments. They are optional. If information technology does not have them, within the parentheses we insert void, similar this:

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

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

          doSomething();                  

If we have i parameter, we specify the type and the name of the parameter, like this:

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

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

          doSomething(3);                  

We can accept multiple parameters, and if so we separate them using a comma, both in the declaration and in the invocation:

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

Parameters are passed past re-create. This means that if you change value1, its value is modified locally. The value outside of the function, where it was passed in the invocation, does non change.

If you laissez passer a pointer as a parameter, you tin can change that variable value because y'all can now access it directly using its memory address.

You lot can't define a default value for a parameter. C++ can do that (and so Arduino Language programs can), only C can't.

Make sure you ascertain the part before calling it, or the compiler will enhance a alarm and an mistake:

          ➜  ~ gcc hi.c -o hullo; ./hullo how-do-you-do.c:13:3: alert: implicit declaration of       function 'doSomething' is invalid in C99       [-Wimplicit-function-declaration]   doSomething(three, 4);   ^ how-do-you-do.c:17:6: error: alien types for       'doSomething' void doSomething(int value1, char value2) {      ^ how-do-you-do.c:13:3: note: previous implicit annunciation       is here   doSomething(3, iv);   ^ i warning and ane error generated.                  

The warning y'all go regards the ordering, which I already mentioned.

The error is nearly some other affair, related. Since C does not "come across" the function proclamation before the invocation, information technology must make assumptions. And it assumes the function to return int. The function however returns void, hence the mistake.

If you change the role definition to:

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

you'd just become the alarm, and not the error:

          ➜  ~ gcc hello.c -o hello; ./hello hello.c:xiv:iii: warning: implicit announcement of       function 'doSomething' is invalid in C99       [-Wimplicit-office-declaration]   doSomething(three, four);   ^ ane warning generated.                  

In whatsoever case, make sure you declare the function earlier using it. Either movement the function up, or add the function prototype in a header file.

Inside a function, y'all tin declare variables.

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

A variable is created at the signal of invocation of the function and is destroyed when the function ends. Information technology's not visible from the outside.

Inside a function, you can call the office itself. This is chosen recursion and information technology's something that offers peculiar opportunities.

Input and output

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

This is not something unique to C, of grade. It's mutual for the language core to be agnostic of I/O.

In the case of C, Input/Output is provided to united states of america by the C Standard Library via a set of functions defined in the stdio.h header file.

You lot can import this library using:

          #include <stdio.h>                  

on top of your C file.

This library provides u.s. with, among many other functions:

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

Earlier describing what those functions exercise, I want to have a minute to talk about I/O streams.

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

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

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'southward i thing to continue in heed.

Some functions are designed to work with a specific stream, like printf(), which nosotros use to print characters to stdout. Using its more general analogue fprintf(), nosotros can specify which stream to write to.

Since I started talking about printf(), let's introduce information technology now.

printf() is ane of the first functions you'll apply when learning C programming.

In its simplest usage form, you pass it a string literal:

          printf("hey!");                  

and the plan will print the content of the string to the screen.

You lot can print the value of a variable. Merely it'southward a fleck tricky because you demand to add a special character, a placeholder, which changes depending on the type of the variable. For example we apply %d for a signed decimal integer digit:

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

We can impress more than one 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);                  

There are other format specifiers similar %d:

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

and many more than.

We tin can employ escape characters in printf(), like \due north which we tin can utilize to make the output create a new line.

scanf()

printf() is used as an output function. I want to innovate an input function now, so we tin can say we can do all the I/O thing: scanf().

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

Nosotros must beginning ascertain a variable that volition agree the value we get from the input:

          int age;                  

Then nosotros call scanf() with 2 arguments: the format (type) of the variable, and the accost of the variable:

          scanf("%d", &historic period);                  

If we want to become a string as input, remember that a string proper name is a pointer to the starting time graphic symbol, so you lot don't need the & character before it:

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

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

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

Variable scope

When you lot define a variable in a C programme, depending on where you declare information technology, information technology will have a dissimilar scope.

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

The position determines two types of variables:

  • global variables
  • local variables

This is the difference: a variable declared within a function is a local variable, like this:

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

Local variables are only attainable from within the function, and when the office ends they stop their existence. They are cleared from the retention (with some exceptions).

A variable defined outside a role is a global variable, like in this example:

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

Global variables are accessible from whatsoever function of the plan, and they are bachelor for the whole execution of the programme, until it ends.

I mentioned that local variables are not available any more after the function ends.

The reason is that local variables are alleged on the stack, by default, unless you lot explicitly allocate them on the heap using pointers. Just then you have to manage the memory yourself.

Static variables

Inside a function, you tin can initialize a static variable using the static keyword.

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

What's a static variable? A static variable is initialized to 0 if no initial value is specified, and information technology retains the value across function calls.

Consider this role:

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

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

If nosotros modify the function to:

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

At present every time we telephone call this function, we'll get an incremented value:

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

volition give us

          ane 2 iii                  

We tin can also omit initializing age to 0 in static int age = 0;, and just write static int historic period; because static variables are automatically set to 0 when created.

We can also have static arrays. In this instance, each single item 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 about the difference between global and local variables.

A local variable is defined inside a function, and it's only available inside that function.

Similar this:

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

j is not available anywhere outside the chief function.

A global variable is defined outside of any function, like this:

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

A global variable tin be accessed past any office in the program.  Admission is non limited to reading the value: the variable can be updated by any function.

Due to this, global variables are 1 mode we have of sharing the same information between functions.

The chief difference with local variables is that the retentivity allocated for variables is freed once the function ends.

Global variables are only freed when the program ends.

Type definitions

The typedef keyword in C allows you lot 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 type nosotros create is usually, past convention, capital.

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

For example we can define a new NUMBER blazon that is an int:

          typedef int NUMBER                  

and one time y'all do then, you can define new NUMBER variables:

          NUMBER one = 1;                  

Now yous might ask: why? Why not just utilise the built-in type int instead?

Well, typedef gets actually useful when paired with ii things: enumerated types and structures.

Enumerated types

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

It's one of the near important uses of the typedef keyword.

This is the syntax of an enumerated type:

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

The enumerated type we create is usually, by convention, uppercase.

Here is a simple instance:

          typedef enum {   true,   false } BOOLEAN;                  

C comes with a bool type, so this example is not really practical, but you get the thought.

Another example is to define weekdays:

          typedef enum {   monday,     tuesday,   wednesday,   thursday,   friday,   saturday,   sun } WEEKDAY;                  

Hither's a simple program that uses this enumerated type:

          #include <stdio.h>  typedef enum {   monday,     tuesday,   midweek,   th,   friday,   saturday,   sunday } WEEKDAY;  int main(void) {   WEEKDAY solar day = monday;    if (mean solar day == monday) {     printf("Information technology's monday!");    } else {     printf("It'south non monday");    } }                  

Every item in the enum definition is paired to an integer, internally. And so in this example monday is 0, tuesday is i then on.

This ways the provisional could take been if (twenty-four hours == 0) instead of if (24-hour interval == monday), but it'southward way simpler for us humans to reason with names rather than numbers, then information technology's a very user-friendly 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 express to a type, so structures tin prove to exist very interesting in a lot of use cases.

This is the syntax of a construction:

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

Example:

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

You can declare variables that take as type that construction past adding them after the closing curly bracket, before the semicolon, like this:

          struct person {   int historic period;   char *proper name; } flavio;                  

Or multiple ones, like this:

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

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

We can also declare variables afterwards on, using this syntax:

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

We can initialize a structure at declaration time:

          struct person {   int historic period;   char *proper name; };  struct person flavio = { 37, "Flavio" };                  

and once we have a construction divers, we can admission the values in it using a dot:

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

We can also change the values using the dot syntax:

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

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

It's important to note that structures are passed by copy, unless of course you pass a pointer to a struct, in which case it's passed by reference.

Using typedef we can simplify the lawmaking when working with structures.

Permit's expect at an example:

          typedef struct {   int age;   char *name; } PERSON;                  

The structure nosotros create using typedef is usually, by convention, capital.

Now we can declare new PERSON variables like this:

          PERSON flavio;                  

and nosotros tin initialize them at annunciation in this way:

          PERSON flavio = { 37, "Flavio" };                  

Control line parameters

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

For simple needs, all you demand to practise to practise so is modify the main() office signature from

          int chief(void)                  

to

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

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

argv is an assortment of strings.

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

Note that there'southward ever at least one particular in the argv array: the name of the program

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

          gcc howdy.c -o hullo                  

If this was our programme, we'd take argc existence 4 and argv being an array containing

  • gcc
  • hello.c
  • -o
  • hello

Let's write a programme that prints the arguments it receives:

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

If the name of our program is hello and we run information technology like this: ./hello, nosotros'd get this as output:

          ./hi                  

If we pass some random parameters, similar this: ./hello a b c we'd become this output to the terminal:

          ./hello a b c                  

This organization works great for elementary needs. For more complex needs, there are commonly used packages like getopt.

Simple programs tin can be put in a single file. But when your programme grows larger it'south impossible to keep it all in just one file.

You tin move parts of a plan to a separate file. So you create a header file.

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

You lot already used header files when you first used the printf() function, or other I/O role, and y'all had to type:

          #include <stdio.h>                  

to employ it.

#include is a preprocessor directive.

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

          #include "myfile.h"                  

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

You tin can also apply a folder structure for libraries:

          #include "myfolder/myfile.h"                  

Let's look at an instance. This program calculates the years since a given year:

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

Suppose I want to move 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 function image, which is the same as the office in the .c file, except the body:

          int calculateAge(int year);                  

At present in the main .c file nosotros can get and remove the calculateAge() function definition, and nosotros tin import calculate_age.h, which will make the calculateAge() function available:

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

Don't forget that to compile a program composed by multiple files, you demand to list them all in the command line, like this:

          gcc -o primary main.c calculate_age.c                  

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

The preprocessor

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

Information technology parses our program and makes sure that the compiler gets all the things information technology needs before going on with the process.

What does it do, in practice?

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

Information technology also looks at every constant you divers using #define and substitutes it with its actual value.

That's just the start. I mentioned those 2 operations because they are the most common ones. The preprocessor can practice a lot more.

Did you find #include and #define have a # at the beginning? That's mutual to all the preprocessor directives. If a line starts with #, that's taken intendance of by the preprocessor.

Conditionals

One of the things nosotros can do is to employ conditionals to change how our program volition exist compiled, depending on the value of an expression.

For example we can check if the DEBUG constant is 0:

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

0 Response to "Learning C# 8 and net Core 30 Review"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel