[From A to Z] C Programming Language Tutorial

R4V3N

Adanmış Üye
3 Tem 2016
6,258
36
25
Kocaeli
C Programming Language

Hi Friends, this article will tell you the details, and subtleties of the C programming language. It will be a long-term article first let me mention it. I will try to enter as much as I can and explain the pointer logic by simplifying it as much as I can.



Why Should We Learn C?

Programming languages is a tool used to solve the problem. The X problem can be solved with each programming language. But what language is suitable for solving the X problem becomes open to discussion. Certain programming languages have come into existence to solve certain problems. You will see in the article that is the reason for the emergence of the C language is that Unix wants to be developed. In other words, each language has a specific purpose. The C programming language is the closest language to the symbolic machine language. It is the fastest language available on the market. As you can see from this sentence, we should use this language when a speed is critical. Embedded systems, system programs, operating systems, autonomous vehicles, smart home systems. C/C++ is necessary in the world of these application areas.

What Kind of Advantage Will C Give?

First, knowing C provides a much better understanding of programming logic than other languages. C the learner has to develop the algorithms he / she thinks of himself / herself because there are not many functions. Learning C in a nutshell adds enough to algorithm development. In this C language, where we are directly related to Ram, Ram allows us to understand much better topics such as computer operating architecture. In C, a concept called Dynamic Memory Management has been created because everything is left to the developer. With this concept, we can get to know and comprehend heap-stack space more closely. Most languages on the market was inspired by the C language. C never gets old, there will always be a need for C/C++ languages.

To summarize;

* Problem solving skills
* Operating architecture of computer and compiler
* Learning other languages faster
* Working on embedded systems
* Knowing operating systems well


History Of The C Language

0Qy6IO.jpg


The C programming language was conceived as a byproduct during the development of the UNIX operating system at the AT&T Bell Laboratory in 1970-1971. AT & T was working on an operating system project called Multics at the time. AT & T withdrew from this project and deviated from the path of writing its operating systems. This operating system was given the name UNIX by wordplay over Multics. At the time, operating systems were written in symbolic machine language. Ken Thompson developed a programming language called B to make things easier. In the following years Dennis Ritchie developed it, making it C. The UNIX operating system was rewritten in C again in 1973. At that time, for the first time, an operating system was written using an advanced programming language; in short, this event was a revolution in programming history. In 1980, IBM launched its first personal computers. The book ‘The C Programming Language’ was written by Dennis Ritchie and Brian Kernigan in 1978. The C programming language was the most common language used in personal computers.

CBzdH1.jpg


Classification Of Programming Languages According To Their Level

zH3WIM.jpg


The measure of level in programming languages represents the proximity of the programming language to human perception. High-level languages are the languages closest to human perception and are easy to learn. Low-level languages. on the other hand, are the most distant languages to human perception and are very difficult to learn. The lowest level language is machine language. This system is also referred to a as binary system. We're just talking about codes with 1s and 0s, and you can more or less guess how difficult, and troublesome it is to write. This language is based on the Assembly language. Although it is easier than Assembly machine language, it is still a difficult language for humans to detect and encode. On top of this is the C language. The C language is closer to the English language, but is much more comprehensible (compared to the assembly language), along with simple mathematical operation opetors and simple keywords.

COMPILE

1COQST.jpg


C is a language that needs to be compiled. The operating system cannot understand the code that is composed of English words that we write, it has to compile the code and convert it into code snippets that it understands itself. If we compile a C code, it is first converted to assembly code with the help of assembler, then it is converted to machine code, which we call binary code, now the operating system understands what the code we write.

The most commonly used compiler today is the compiler called GCC. It consists of the initials of the GNU C compiler words. There are also several compilers on the Microsoft side.

IDE

Normally, compilers are programs that run from the command line. Code is written in the editor environment, this code is compiled on the terminal. In fact, it is in this way. But today, a concept called IDE has emerged. It consists of the initials of the words Integrated Development Environment. The reason for IDEs is to write the program on the editor, and then compiled it on the terminal screen. If we install any IDE on our computer, a compiler is installed with it. IDE is not actually a compiler. It is a program that makes it easy for us to write, and compile code. Buttons such as Compile & Run are available. If it's not the compiler, what can you say about the compile button? If we Press that button, we get rid of the trouble of compiling manually in the terminal, the program in the background does this for us.

Preprocess

Our C program is put through a process called preprocess before it is compiled. This process interprets lines beginning with the # (sharp) sign at the top of the program. After these lines are interpreted, and the necessary operations are done, compile starts.

Compile processing

The Compile process starts with tokenizing. Let's talk about what this process is. Before the compiler can make sense of the code, the contents of the code are broken into Token fragments. When this is done, the compiler does not look at nouns and sentences, only separates them into tokens. He cannot understand the meaning of the code, what it does, and the logic errors in the code at that stage. We can think of Token as the smallest unit. What are tokens?

Keywords/Reserved Words

Keywords are words that are predetermined by the language's design, have a special meaning from the beginning, and are forbidden to be used in any other meaning. There are 32 keywords in the C language.

4eH93O.jpg


Identifiers

2LbxTT.png


They are the original names given to entities in the C language. As an example we can give:
*Names given to variables
*Names given to functions
*Names given to constants
*Names given to labels


Operators

Operators are tokens that perform a certain operation. Although it varies from programming language to programming language, its overall structure is the same. Mathematical operations, logic operations, such as operations can be done through operators.

BeQIWK.jpg


Constant/Literal

Expressions that specify a numeric magnitude or sequence of characters directly within the code. There are 3 separate systems for writing numerical constants.

*Decimal
*Hexadecimal
*Octal


Decimal numbers are written as when writing.
When writing Hexadecimal numbers, they are written by taking the values ‘0x’ or ‘0X’ on their heads. Octal numbers are written on their heads by taking the value '0'.
0x35 (10), 035 (16), 35 (8)
The 3 values we see above represent different numbers.


String Literal

Are constants written in double quotation marks. They are qualified according to ASCII codes.

eHSN5O.jpg


In the above code, the value of the variables A, b, and c is the constant value. If we say something like c = a, the inside of C would be variable rather than constant.

Delimeters/Punctuators

All atoms used to separate expressions, except for the groups mentioned above, are called separators. For example,'; ' and '{ }' are separators.

Compiler Rules

KJKOyP.png


There should be no syntax error during Tokenizing. There is no rule between 2 tokens, such as skipping a line, leaving spaces, leaving no spaces. Even if we write a very legible code, these codes are combined in tokenizing. It is important for the programmer to write legible code regarding readability, even if this is not a rule.

Global nameSpace/Local namespace

The C code we wrote consists of 2 different parts. Global namespace and local namespace. What remains in our functions is our local namespaces. The part outside the functions is our global namespace. We'll get to the specifics of these areas in a moment.

8PB8NI.jpg


Declaration/Statement

Each sentence we use in the C language must contain one of the 2 structures in the title. Declaration means notification. No action is taken. Only notification is made. It can be used in both the global name space and the local name space. It means the sentence we use when defining a variable or function. If we do not give notice, the compiler will not recognize what that variable or function is.

The statement means statement. When the Compiler sees statements, it knows that it needs to perform an operation. While writing loops, putting decision structure, doing math process, etc. expressions are used. Statements cannot be written on the global name space. The Local name space must be written in the function.

02ffLG.jpg


If you compile the code in the example above, it will give an error. We defined both variables in the global domain, and our rule was that we could only declare in the global domain. There is no trouble defining the first variable, but the second variable contains a statement. An expression means the collection of a constant and a variable. We could say 5 + 3, because 2 also contains Constant, but we can't use it.

#include Directive

This command is a Preprocessor command. This command indicates that the command will be copied to the place where it was placed during compilation, deleting this line and replacing it with stdio.it has the same effect as placing the contents of the file named h there. The word #include means to include. To use the most basic functions in C, we need to include basic libraries, unlike in other languages.

Basic Libraries In C Language.

<stdio.h>: it is the most basic c library, it is necessary for us to achieve standard input and output functions. Uses stdin, stdout, stderr files.

<stdlib.h>: it is one of the basics c libraries, we need to include these libraries to get to the basic functions. Let's sort the functions that come with this library;

Kod:
 abort();
abs();
atexit();
atof();
atoi();
atol();
bsearch();
calloc();
div();
exit();
free();
getenv();
labs();
ldiv();
malloc();
mblen();
mbstowcs();
mbtowc();
qsort();
rand();
realloc();
srand();
strtod();
strtol();
strtoul();
system();
wcstombs();
wctomb();

<math.h>: as its name suggests, it is a library that contains functions for us to do mathematical operations. Let's sort the functions that come with this library;

Kod:
 acts();
asin();
atan();
atan2();
ceil();
cos();
cosh();
exp();
fabs();
floor();
fmod();
frexp();
ldexp();
log();
log10();
modef();
pow();
sin();
sinh();
sqrt();
tan();
tanh();

<string.h>: are functions that allow us to perform certain operations in character sequences. There are many high-level functions in this library. Let's examine these functions.

Kod:
memccpy();
memchr();
memcmp();
memcpy();
memcpy_s();
memmove();
memmove_S();
memset();
memset_s();
strcat();
strcat_s();
strchr();
strcmp();
strcoll();
strcpy();
strcpy_s();
strcspn();
strdup();
strerror();
strerror_s();
strerrorlen_s();
strlen();
strlen_s();
strncat();
strncat_s();
strncmp();
strncpy_s();
strndup();
strpbrk();
strrchr();
strspn();
strstr();
strtok();
strtok_s();
strxfrm();

#define Directive

Define is a preprocessor command, used for data that we do not want to change in the program. It is considered Constant/literal, not variable, in the program because it is processed by the preprocessor. In general use, name assignment to define values is capitalized, as soon as the value is equal to the name, only spaces are left.

Example usage;
Kod:
#define A 15
#define PI 3.14

Not: Capitalization is customary when defining a constant with Define, programmers should pay attention.

Variables In C Language

Variables are the data stored on the computer's memory (ram), which we can change at any time on the name.

Why do we need data storage?

-At certain points of the program we may want to get data from the user, to change the flow of the program from user to user.

-In certain cases, we may want to make certain operations and use these operations in other parts of the program. For this we need a temporary storage unit.

The data stored on Ram (variable) has to be a specific data type. We have to specify what this data type is in the row in which we define the variable. To define a variable, we use:

Kod:
date_type modife_name (Identifier) = modife_name;

We determine the data type. We give the variable a name, and that name should mean what the variable is about, so as not to forget when calling it in another part of the program. When naming a variable, we give it a name under certain rules. We'll come to those rules later. And then we use =(assignment operator). Don't confuse it with the equal sign in mathematics. The mark's purpose here is to retrieve the value on the right and synchronize to the variable on the left. After the assignment operator, we give data according to the type of variable we specify.

What if we want to get the data from the user?

Kod:
int x;
scanf("%d",&x);

If we want to get the data from the user, we only need to specify the data type and name. We make room for a variable on the memory. It does not yet have a value in memory, but it has an address. In short, we tell the program to save a space for the x variable and I'll fill it later. the scanf function, which allows us to receive input from the user, we receive data from the user and we say save that data to X's address.

Variable Name Rules

- The name we give variables can't start with a number. But in or in the end the number may pass.

- Variables can't contain special characters in the name we give them. For this rule, the _ sign that we have one exploit can be used.

- The name we give variables can't be longer than 32 characters.

- The name we give to variables cannot use specific words that the program uses itself. (such as int, short, for, if,..)

- In C, variables are case-sensitive, i.e. uppercase - lowercase canonical languages.

Kod:
int merhaba;
int mErHaBa;

The 2 variables described above are independent of each other, and if we define a variable with exactly the same name as a variable, we get an error.

Basic Data Types In C Language

What is the data type first, let me tell you about him. The concept we call data type qualifies the type of variable we create. In fact, the data type is basically a concept created for the computer to understand how many bytes to hold on ram and how to interpret that variable. Each variable we want to store in programming languages is stored in a specific address on ram. The main reason for allocating data types is not to waste unnecessary space on ram. If we use small numbers, we specify the data type according to it, and we do not waste unnecessary bytes, and if we use unsigned integers, we determine according to it, and we do not cause complexity. In short, the data type tells us what the data is. All variables in memory (even characters) after compiling our code, convert them to 0's and 1's.

Char Data Type

The char data type is only for a single 1 character. It holds a byte in memory and is written between the ‘ ‘ signs when it is defined. Since the portion of memory allocated for char is a byte, we cannot hold more than 255 data with char. I can hear you say that with this data type. How do we compare the number 255 with the character? Let's read the sentence I wrote above again:

All variables in memory (even characters) after compiling our code, convert them to 0's and 1's.

If we keep the letter a in the character variable, how do we convert the letter a to a number? In time, programmers asked themselves this question and created a standard that required them to come up with a common solution. Standards that will be accepted by the world. And they call it the American Standard Code for Information Interchange(ASCII).

00JRVx.jpg


As we have seen above, there is a numeric value for each input value on the keyboard.

Let's define a character variable and see its equivalent according to ASCII code.

Kod:
char a = 'a';
printf("%d",a); // d integer value using placeholder
printf("%c",a); // c string value using placeholder

As you can see above, we printed both the char value and the integer value of the A Variable.

Integer Data Type

The Integer data type is our data type that stores integers. Although the space it occupies on memory varies from computer to computer, it is generally 4 bytes. If the value is 4 bytes, 32 bits can take the maximum value of 2^32-1. You can use the sizeof() operator to find out how much space the integer data type takes up in memory on your computer.

Point is, let's define a variable using the integer data type.

Kod:
int x = 5;
printf("%i",x);
printf("%d",x);

We can use 2 different placeholders for Integer variables. %d and %i. In general, the use of % d is more common.

Float ve Double Data Types

Float and double floating decimal numbers are used for commas if we are going to Turkish a little more. However, in the programming language, we separate decimal and integer values by a period, not by a comma, and if we try to separate them by a comma, the compiler does not understand it and treats it as a syntax error. If they both represent decimals. The answer to the question why we use 2 different data types is simple. The space they're storing. The Float data type allocates up to 4 bytes of space, while the double data type allocates up to 8 bytes of space. 4 bytes equals 32 bits and the integer can actually store up to of data. Double is exactly double. Calculating floating-point numbers on the computer does not give a clear result, the higher the byte we do the operation, the closer the result is to accuracy. But we can't say for sure that it is true, so programmers are advised to use the double data type.

Kod:
float x = 5.4;
float y = 5.0;
double z = 4.9;
double t = 4;

All of the above uses are true. In the last use, the T variable is assigned a value of 4 directly. If the integer value is overwritten, the program saves it as float memory. 4.0. We use the %f placeholder when printing for Float and Double data types. When reading a value (scanf), we use %lf for float, %F for double.

Input/Output Functions in C Programming Language

Function doesn’t read data directly from keyboard or display something to screen when we use or write input or output function. I’ve told you that C programming language firstly came out with UNIX. If you’ve researched about UNIX, you must heard this:

Everything (include hardware) is an file in UNIX systems.

So, we basically write to file and read from file in C. When you need to take some data, use stdin. When you need to give something, use stdout. And if it’s and error, use stderr.

Output Functions

I’m gonna explain top 2 output functions: printf() and putchar() functions.

Printf function takes 2 arguments in it. In the first one, we write data that we gonna input between 2 quotes or placeholder that we wanna use. We use comma to sparing this arguments. In the second one, we write an expression. Such as a + b, c + 3, 3 + 2, etc.

And putchar function is used to display just one character. We can just give an variable or anything you want inside single quotes.

Input Functions

scanf, getch, getche, getchar, gets.....

There are lots of them, and little differences between each others.

Scanf is the most used input function. It takes 2 arguments; the left one can be assigned a placeholder specifically between quotes, the right one can be address of variable that we want. This function reads it till we left blank, doesn't take afterwards.

Gets function is removed from C standards later, but still available to use. This function reads it till enter ('\n'). That means we can finish our sentence whenever we want.

You must pay a big attention while using getchar function. You say why? This function reads each character and waits for enter. When you press 'K' and enter, it writes both 'K' character and '\n' into stdin file. It means that if you wanna read it with putchar twice, the first one will be 'K' and the second one will be '\n'. The function we need to use as a solution to that, is fflush() function. It allows to clear output buffer. We gonna clear output buffer but which one?

Isn't it obvious? Stdin is a file and it writes characters that took from getchar into this file. We need to clear that output buffer sometimes. To do that: "fflush(stdin);"

Getch function doesn't come with standard library, we have to import it with <conio.h> library. This function does its process in the second when you type something, doesn't wait for enter. This is why it's a good bet about choosing input function.

Loops and Conditional Statements

Now let's talk about musts of programming languages; loops and conditional statements. There are 3 types of loop structure. Each one can converted to another one, there are absolutely no difference. Lemme explain with more detail.

For Loop

There are 3 parts inside of parenthesis of for loop. The first part is about declaring variable. Back in old C standards, we had to that declaring process over the for loop. But not anymore. The second part is about condition. Our loop runs during this condition returns true. We have 2 semicolons that seperate our loop into 3 parts. The third part is about updating. We have to update our loop or it's gonna run forever.

Kod:
for (declaring ; condition ; updating );

While Loop

There is only 1 part inside of parenthesis of while loop. It may looks different than for loop but runs the same thing actually. Every for loop can be converted to while loop and likewise. I told you that there is 1 part. That part is about condition. It runs if it's true, it doesn't run if it's false.

Kod:
int j = 0; // declaring
while(j< 10) // condition
{
j++; // updating
}

Do-While Loop

It's pretty much same with while loop. The only difference between them is the procecss runs first, then controls. Even if it's 0, it's gonna run at least once.

Kod:
do{

j++;

}while(j<10);

If-Else Condition

We can do specific processes in specific situations in if-else. There can be more than one conditions inside of if-else. The difference between loops is it runs once.

Kod:
int x =5;
if(x == 5)
{
printf("if condition ran");
}

Compiler waits for else-if or else after if, and doesn't care if there isn't any. It doesn't check else-if or else if "if" condition is true.

Wrong:
Kod:
int x = 5;
if(x <10)
{
printf("if ran);
}
if(x >10)
{
printf("Second if ran");
}

I just showed you a wrong way to use "if". You gonna ask why, here is why. It can't be possible x is less than 10 and x is greater than 10 at the same time. It's either less or greater than 10. Processing it twice with 2 if, only makes our program slower. The proper way to use it with if - else or if - else if. Because it skips other blocks if "if" condition is true.

True:
Kod:
int x = 5;
if(x <10)
{
printf("if ran);
}
else if(x >10)
{
printf("else if ran");
}

Switch-Case Condition

This condition must be used if there's a lot possibilities. Every if condition can be converted to switch and likewise. But if there're lots of possibilities, it'ld be doing the donkey job if you use if-else.

Kod:
switch(variable)
{
case 1:
xxxxx;
break;
case 2:
yyyyy;
break;
case 3:
zzzzzz;
break;
default:
.............;
}

Switch can take 1 variable. Let's say it's x. And x has value of 5. It scans case conditions. If one of them is true about x = 5, it runs. If none of them is true, then default runs.

What is Pointer?

Pointer stores address of variable, shows where is that variable over ram. When we create a variable in any programming language, this variable is stored in random memory unit over ram as hexadecimal addressing.

Kod:
int x =5; // we're creating a variable called x and assign inside it value of 5.

We know that this x variable is stored random somewhere in ram. And i just told you that this is an hexadecimal address. We have to define pointer to see that address. We use * to do that.

Kod:
int *p = &x; // pointer variable that holds address of x variable

As you can see, i used &. This symbol is called ampersand. If you use this symbol twice, it means "and". If you use this symbol once, it means "an address of something". It shows where that variable is.

If we wanna print a pointer variable, we have to use use placeholder. Placeholder for pointers is %p.

Kod:
int x = 5;

int *p = &x;

printf("%p",p);

This code outputs address of x variable. If we run that code over and over, we got different output at each time. As i say at the top, it's stored over ram randomly.

Is it possible to see inside value of address variable by using pointer? The answer is yes. P pointer that we used shows ******** of x variable. X variable that we used is an integer. So what will i get if i type %d (placeholder for integer) inside of printf? It's gonne be 5, right?

Kod:
int x = 5;

int *p = &x;

printf("%d",p);

But this code will return an error. Don't know why? We wanted to print an integer value with printf function. That's why we used %d. The part after comma must be an integer, too. But we typed p. P isn't an integer. Think it like Integer, float, double, char, long, pointer. It has address value inside it, not integer. This is where * steps in. * means that show value of address that pointer pointed out. The one we say address that pointer pointed out is address of x variable acturally. I mean inside of address of x variable, x, 5..

True:
Kod:
int x = 5;

int *p = &x;

printf("%d", *p);

Let's write another examples to make it clear.

Kod:
int a = 10;

int *ptr = &a;

*ptr = 15;

Kod:
int b = 20;

int c = 30;

int *ptr2 = &b;

ptr2 = &c;

Could you understand the different between this codes?

In the first one we created a variable called "a". Ptr pointer holds address of a variable. And we change inside of address that pointer holds to value of 15.

In the second one we created two variable called "b" and "c". Ptr2 pointer holds address of b variable. And we change ptr2 pointer (not inside, i didn't use *). Ptr2 pointer holds address of c variable instead of b. You just have to know ampersand and star to understand pointer, that's all.

I've told that every variable is being hold in somewhere in every programming languages at the top of this title. Aren't pointers that we declared, a variable, too? I mean, pointers hold something too. Here it is:

Kod:
int x = 5;
int *p = &x;
int *p2 = &p;

This isn't a common usage. Nobody wants to know where is theirs pointer being hold (except extreme situations). I just wanna express the logic of it. In that code, p2 pointer is being hold in somewhere else too. So it goes forever.

It's also possible to see address of a variable without declaring pointer. It's actually like printing integer without declaring integer.

Kod:
printf("%d",15); // It prints 15 without declaring integer variable.

int x = 5;
printf("%p", &x); // It prints address of x without declaring pointer.

As you can see, we can see address of a variable without declaring pointer. But what if we use:

Kod:
int a = 50;
printf("%d", *&a);

Ampersand means address of variable and star means inside of variable.

I meant printing inside of address of a variable by that code. Again, i just wanna express the logic of it. It's not a common usage. Printing "*&a" and just "a" actually same thing. When we did it with "a", it prints a variable. But when we did it with "*&a", it also prints a variable but in a unnecessary roundabout way.

You figure this out this time. Compile it and compare it :)

Kod:
int a = 10;
int b = 20;
int c = 30;

int *p = &a;
*p = 15;
p = &c;
*p = b;

printf("%d", a);
printf("%d", b);
printf("%d", c);

Strings (Char List) in C

Strings in C programming language holds one more than its length over memory. The reason is that every string has an end character. There is always \0 at the end of every string. That's how computer can tell when string ends. We have to define how length is variable gonna be. Enough places is set according to that defining and can't be changed anywhere else in program.

Kod:
char name[10] = "Emir";

Let's say we declared a variable just like above. We can't change its length and also it's impossible to cross that limit. Even if we cross that limit, we get errors during compiling.

String isn't one of basic data types in C. Strings are actually lists consist of char data type. We can use strings by importing string library if we want but all we do is masking char.

Declaring String by Using Pointer

We know that pointer holds address of certain variables. And we also know that strings are char lists. Every list has a starting address over ram and it goes 1 byte because it's char list. We can declare a string without defining a limit by using pointer. Here is an example usage:

Kod:
char *name = "Emir";

We declared a pointer called name and it holds a random place over ram (let's say 0x123). 0x123 has 'e', 0x124 has 'm', 0x125 has 'i', and 0x126 has 'r'. Don't forget last character. 0x127 has '\0'. Lemme explain it:

Kod:
char *name = "Emir";
if (*(name+4)=='\0')
{
printf("!!!!");
}

We just held a place by using pointer. As you know that char data type has 1 byte, we skip 4 bytes after name when we say name+4. Now we're in right after 'r' (from Emir) where \0 is. We're not quite sure about if it's exist or not, so we did a condition. If there is really \0, it return that if and print !!!!.

Declaring Integer List with Pointer

We talked about that strings are list, that means we can declare list by the help of pointer. Here is example usage:

Kod:
int *list = {1,2,3};
int list2[3];
list2[0] = 1;

I just showed 2 different usage at the above code. Let's try to mess with char pointer and integer list's datas by creating integer list (array).

Kod:
int list[4];
list[4] = 10;
char *p = list;
*(p+12) = 150;

We just declared a list above there. We can change fifth data of list with the help of pointer. But you may ask why. As you know integer data type has 4 bytes, and char variable type has 1 byte. When we create an integer list, 6 pieces which has 4 part inside of them are created. That means 24 bytes is being hold over ram. To access to last data, we have to skip it four by four because char has 1 byte. We're trying to point out an integer value with char pointer here. So, you should think it as 24 pieces, not 6. When we're in fifth piece, it means we're at the beginning of last piece (list[5]). And change it with pointer. Try it yourself if you don't believe me.

9BW1U2.jpg


The noteworthy point about declaring char pointer is char pointers can store data to 1 byte. 1 byte equals to 8 bits. There are 2^8 possibilities actually. One byte can take 255 max as a value (totally 256 values including 0). When we want to even up list[5] to any value than 255, it's gonna return to 256. Let's see:

Kod:
int list[4];
list[3] = 10;
printf("%d\n", list[3]);
char *p = list;
*(p + 12) = 256;
printf("%i\n", list[3]);
short *p2 = list;
*(p2+6) = 25;
printf("%i", list[3]);

When we want to print list[3], we get 0 as output. Because 256 mod 256 equals to 0. Btw i used short, too. We use 6 instead of 12 because short has 2 bytes.

What is Struct?

I've told you guys that there are some basic data types such as int, float, double, and char. But they're not gonna be enough for us. If we wanna input a date from user, we need something more advanced data struct. We can say that it's something like classes in other languages.

Kod:
struct cyber{
int a;
char b;
float c;
}

I just declared a struct called cyber. This struct has 3 different variables. Let's make a variable from this struct.

Kod:
struct cyber a;
a.a = 5;
a.b = 'a';
a.c = 5.12;

I created a variable by assigning theirs value.

Lemme be more specific.

Kod:
struct date{
int month;
int day;
int year;
}

I declared my date struct. Let's assign some values.

Kod:
struct date birthday;
birthday.month = 05;
birthday.day = 12;
birthday.year = 1998;

As you can see, we can take date infos just like this.

We can also perform same process with typedef which is more common than struct. Because it has easier syntax.

Kod:
typedef unsigned long long ULL;

ULL a;

Kod:
typedef struct a{
char a;
}

Kod:
a degisken_adi;
 
Moderatör tarafında düzenlendi:

R4V3N

Adanmış Üye
3 Tem 2016
6,258
36
25
Kocaeli
Functions In C Language

Functions are concepts that developed because writing same algorithm over and over is gonna be difficult in case of we need to perform a process more than one over that program. Function structure can take value or values into itself. Functions can return a value by performing process according to specific algorithm bearing in mind that this values. Firstly you need to write which type of value that you want to return while you're defining a function. If it's not going to return value, we define a function in type of vòid.

Kod:
vòid myFunc()
{
printf("I am a function");
}

We definitied a function. If function definition is make on function call, we need define function prototype.

Why we doing this ?

Because, code compilers reads codes from top to bottom. And It will say "I dont know you" when come to "myFunc()" line. Because it didnt see that definition before. So, we'll define prototype. Generally, prototypes definites bottom of preprocessor directives.

Kod:
#include <stdio.h>
vòid myFunc();

Derleyici bu prototipi görünce satır atlayacak ve fonksiyonu tanımladığımız satıra dönecektir. Tanımı yapıp tekrar olduğu yere dönecektir.

Giving parameters to funcitions

Functions can want some numbers for specific algorithm proccessings from us. We are writing addition function, For example; It will be add a + b but which values a and b ? They must be spesific numbers for creating dynamic structure. We want to add 5 + 3 (example). 5 value converting to "a" and 3 value converting to "b".

Kod:
int topla(int a, int b)
{
return a+b;
}

Now we are adding two diffrent numbers with this code. We are seeing "Return" word.

Where and Why We Using This Word

We are creating variables on RAM when we call this function. A and b variables that we declared as int a and int b, are created when the function ran. And variables will delete when function finish. Program doesn't know that variable. If we try to write a with printf, the compiler will say "I dont know a". And we'll see compile time error. We use return word for this. Return means; return something to back.

So, you will delete variables which i created. Now I have 5+3. Briefly, you need to delete variables that i've created before.
What i got is sum of 5 and 3.
If you want to know how to use that value, here it is. Return value basically returns that value to wherever that function is called.

Kod:
int main()
{
int c;
c = add(a, b);

}

int add(int a, int b)
{
return a+b;
}

Value in that c variable, will be value which returns from function. So we use return word.

Call By Value

Variable is declared, function is done and variable is deleted in call by value functions. I determined x = 4 and y = 7. If i want to change they with each other, If i use Call By Value method, It will be wrong.
Neden hatalı olur ?

Because parameters which we sended to function, create their own variables inside. They make changes inside and they delete this variables on memory.

For example (function)

Kod:
int main()
{
int x = 4, y=7;
swap(x,y);

}
int swap(int x, int y)
{
int tmp;
tmp = x;
x = y;
y = tmp;
}

This codes wont change values. Because (int x, int y) text is conspicuous. Even we'll write same variable names, it will create diffrent variable and delete from memory this variables. So, we need to use Call By Referance for this problems.

Call By Reference (Referans ile Çağırma)

Maybe referance calling doesn't mean something. But, If we say Call By Pointer, you can understand better. We are giving address as parametre to function. Function cant create It's own address. So It will go that address. It makes processes on that address. That address Is our x and y variables. So, Swap process succesfully worked.

Kod:
int main()
{
int x = 4, y=7;
swap(&x, &y);

}
int swap(int *x, int *y)
{
int tmp;
tmp = *x;
*x = *y;
*y = tmp;
}

We are doing processing with address. So dont forget use "&". We are using Call By Referance on processing with string. Because strings are pointers so they specify address. We define string[10]. If we try to print string with printf, this returns us address of first index of that list. All processes that can be done with pointers, can also be done in strings too.

Recursive Function

These functions calls themselves. Using these function is so risky. If we cant out on function loop, stack space is will be full and we can get stackoverflow(segmentation fault:11) error.

Kod:
#include <stdio.h>
int asalMi(int sayi, int i);
int main(int argc, char const *argv[])
{
	int n, control;
	printf("input number\n");
	scanf("%d", &n);
	for (int i = 2; i < n; ++i)
	{
		control= asalMi(i, i/2);
		if (control== 1)
		{
			printf("%d\n", i);
		}
	}
	return 0;
}

int asalMi(int number, int i)
{
	if (i == 1)
	{
		return 1;
	}
	else if (number% i == 0)
	{
		return 0;
	}
	else
	{
		return asalMi(number, i-1);
	}
}

You can see an example about recursive function that helps to us on find prime numbers in above code. As you can see, my function recall processing is bottom of a condition block. This is, obstructs calling function itself until forever.

I want to share this example beacuse this is very confusing.

Kod:
#include <stdio.h>
#include <stdlib.h>
int fibonacci(int n);
int main(int argc, char const *argv[])
{
  system("clear");
  int x;
  printf("input any diget plays you want : ");
  scanf("%d", &x);
  printf("\nFibonacci string :\n\n");
  for (int i = 0; i < x; ++i)
  {
    printf("%4d", fibonacci(i));
  }
  printf("\n\n\n");


  return 0;
}

int fibonacci(int n)
{
  if (n==0)
  {
    return 0;
  }
  else if(n==1)
  {
    return 1;
  }
  else
  {
    return (fibonacci(n-2) + fibonacci(n-1));
  }
}

This code also outputs Fibonacci sequence in the amount of whatever user inputted. If you notice, our function calling point is bottom of a condition








Dynamic Memory A͟l͟l͟o͟c͟a͟t͟i͟o͟n͟

There are no classes in C language. All processes doing by users. For example, let's say we have a list having 5 element. What are we gonna do if we realize 5 element isn't gonna be enough for us and wanna increase it to 10 in the middle of program? We can do something like that based on knowledge up to now, We can delete the previous one, create a new one with 10 element, and declare old values into new list with for loop. But it's kinda memory occupation. This isn't a wise solution. We need something more dynamical. I wanna explain what is stack and heap first.

What is Stack?

Stack is workplace of program in memory. When we run the program, a part of memory is assigned to our program's workplace in memory by operating system. We can use that space statically. We use variables that have no possible to change ever again. Think that stack as a list. It works like first in last out. Our variables are declared as a list. Let me give an example:

Kod:
#include <stdio.h>

int main()
{
	int x = 4;
	int dizi[5] = {1,2,3,4,5};
}

Two variables in above code are stored in stack. How much spaces they gonna take is calculated during compiling. Compiler checks that code out and says we have a list having 5 elements in it. And that's all. It means that you just declared that list as 5 elements, nothing more.


What is Heap?

Heap space is out of program's workspace. There is always a possible that you may come across with operating system's or another program's used memory space. If that happens, NULL address is returned.

What is that Null Address?

I wanted 5 byte memory over Heap from operating system. If that space is been using by that operating system, that can be done. It say i'm using it man. It can be done if that space is available. That's why programmers assigned to 0. byte as NULL value (forbidden zone). If we come across with space that OS is using it rn, we're forwarded to that NULL address.

When we used heap space, return that space to OS. If we don't, it causes to memory occupation. And that leads to memory leak. When we use a program or play a game so long and it starts to slowing, that means programmer who took care of dynamic memory al******** had coded some parts wrong. He didn't return spaces which is no longer needed to OS. Memory becomes huge over time and causes to slowing in program or game. There is no Garbage Collector in C unlike others.

What is Garbage Collector?

It's an mechanism that automatically returns heap space after we used it and no longer needed to OS. But it's not available in C. Programmer has to do it manually.


Stack Features

- Faster than Heap space
- Created variables are returned to OS automatically
- Not dynamic
- Created in compile time

Heap Features

- Slower than Stack space
- Programmer has to return it to OS because there's no Garbage Collector in C
- Dynamic
- Created in run time

Primitive data types are stored in Stack but reference data types are stored in Heap. Referance that refers referance data type is also stored in Stack.

RxfBOL.png


As you can see in the above image, referance (address) value is stored over the sayi (means number in Turkish) variable. And that address is stored in Heap space.


malloc() Function

We are using this function for get memory space on heap space. It gets one parameter. For example;

Kod:
int *p = malloc(5*4);

This using method is not recommend. Now we got 5 integer list space, but we should have done like that because integer's size can be different from various systems.

Kod:
int *p = malloc(5*sizeof(int));

In some sources, malloc function converting to integer pointer before using. We dont need to do that. We typed "*p". So, It will chance automatically. For example;

Kod:
int *p = (int*)malloc(5*(sizeof(int));
Kod:
int *p = malloc(5*sizeof(int));

Yukarıdaki iki kod aynıdır. Malloc fonksiyonu bize 20 byte kadar heap alanı üzerinde bellek tahsil eder. Kelime anlamı ise memory allocate'den gelmektedir. Türkçe anlamı ise hafıza ayırma demektir.



calloc() Function

Calloc funtion is like malloc function. There is a diffrent thing. the malloc cleans memory. So, calloc slower than calloc. What is cleaning ? It will put "0" value in all values. But when we want to reserve space with malloc, there will be trash values in there

Kod:
int *p = calloc(5,sizeof(int));

Second diversity is this function gets two parameters. We are typing "5*sizeof(int)" in malloc. But we need to type "5, sizeof(int)" in this function.

realloc() Function

Realloc function is using when we need reserving space. It gets two diffrent parameters. First parameter wants address and second parameter wants new size.

Kod:
int *p = malloc(5*sizeof(int));

We reserved space with malloc. Isn't is enough ?

Kod:
int *p2 = realloc(p, 10*sizeof(int));

Now that space enlarged to 40 Byte.

free() Function.

I've mentioned about memory leak at the beginning of this article. The reason of this concept is occured is because of wrong or lack of this function usage. There is a Garbage Collector mechanism in C language. So, we need to give back that memory space to operating system when our process is finised. We can give back that memory with using free() function.

Kod:
free(p);

Our process is finished. And we gave back that memory to operating system.

Expression concept

Expression is a concept that lies at the heart of programming language. It splits into 2. Lvalue expression and Rvalue expression


L-Value Expression[/SIZE

We know, "equals" phrase is assignment operator in programming. That means; assign value on right place to left place. Left value must be L-value expression always. L-value is a variable name. It wont be constant or operator.(as "a+5")

For Example;

a+c is not a lvalue expression. But alone a or c is a can be lvalue expression.


R-Value Expression

Everything can happen in here. Because we said "assign value on right place to left place". Constant values is R-value expression.

For example;

15, a+b, a, 15/5.....


Union Structure

It is using for comminication on sockets. It can smash the incoming packages. It likes struct. But But its size is calculated as size of the biggest data type inside of itself. Variables inside of it use that space.

Kod:
union{
int a;
char a,b,c,d;
}myUnion;

Above in this code, most space filling data type is integer so our myUnion data's structure is created by 4 bytes.

S21GKL.png


You can see work logic in this photo;


Pointer Struct Definition


We can create struct and we can define pointer from data which we created. There is a diffrent thing. We are not using ".". We are using "->" this. For example;

LKIIW8.png


Program output;

WS523R.png


Work logic;

Our created struct x build's size is 4 byte. There are four char variables. So, we are using this struct as pointer. We are showing again four byte integer value with this pointer. The integer's value is 1028. We are typing hexadecimal now;

0x00000404 (Address values are addressed as 8 byte (64 bit) in CPU. That's why we put that zeros like that.)

Char is showing 1 byte. So we will type 1 byte space for a value and it will be 0 and 4. Because this number is hexadecimal base. You can look to number bases on mathematics if dont you understand.

Briefly;

a = 04
b = 04
c = 00
d = 00

Random Value Generating

Actually, computer dont generate random numbers. There is a specific algorithm. So, there are many problems. This algorithm generates same number after a specific number. This algorithm has a seek value. We need change that. After compile, program will generate same values after our second calling. We always need change seek value with srand() seekrandom function. It's good but if i put time value into this srand() function. that means, program generates random values when it runs. Because the time is changing always. I think you learned srand function's logic. You can give srand(time(0)) or srand(Clock()) as parameters. Time 0 looks seconds. And clock uses split second as a base.

We changed seek value. Now we can speak about rand() function. Rand function generates so big values. We must make manuel mod. This is rule on math

for generating number in close space of min-max

rand() % (max-min+1) + min

We typed this. We need to to include our time.h file in code for use Clock or Time functions.

Kod:
int main()
{
srand(clock());
int dizi[10];
for(int i = 0;i<10;++i)
    {
        dizi[i] = rand() % (10-0+1) +0;
    }
}

Above code generates 10 numbers between 0-10 (includes 10) and sends these numbers to list.

C Programming Tricks

I will speak about some tricks.

1) If we use assignment operator instead logic operator, in loop and decision structure, assignment operators's R-Value value is will back.

For example;

6BSAfa.png



2) The last thing to do operator is assignment operator. This is so importnant.

You can encounter misleading questions. For example;



e7yJW9.png


3) You shouldn't mistake byte 'and' for normal 'and' else. Even byte and first wrong, it will look second part.

P0J0RI.png


Using "++" and "--" equal "x += 1". So, it wont make on numbers.

MLNdef.png


5) "^" mark is EXOR conjunction. It makes processes on byte. If it same it will convert to 0, If it will diffrent it will converto to 1

277LPd.png


6) Printf function return one more whatever it takes in it
277LPd.png


7) We can access to strings with pointer operator, and pointers with string.

xMBKNK.png


8) Using If on a string (?) Operator

KbxMML.png


9) It's impossible to process over define variables that we've given to preprocessor. It acts as Copy Paste.

V6MeA8.png


 
Moderatör tarafında düzenlendi:
Üst

Turkhackteam.org internet sitesi 5651 sayılı kanun’un 2. maddesinin 1. fıkrasının m) bendi ile aynı kanunun 5. maddesi kapsamında "Yer Sağlayıcı" konumundadır. İçerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır. Turkhackteam.org; Yer sağlayıcı olarak, kullanıcılar tarafından oluşturulan içeriği ya da hukuka aykırı paylaşımı kontrol etmekle ya da araştırmakla yükümlü değildir. Türkhackteam saldırı timleri Türk sitelerine hiçbir zararlı faaliyette bulunmaz. Türkhackteam üyelerinin yaptığı bireysel hack faaliyetlerinden Türkhackteam sorumlu değildir. Sitelerinize Türkhackteam ismi kullanılarak hack faaliyetinde bulunulursa, site-sunucu erişim loglarından bu faaliyeti gerçekleştiren ip adresini tespit edip diğer kanıtlarla birlikte savcılığa suç duyurusunda bulununuz.