Below are the C related stuffs we covered in week 1. If you're a C expert, you can just simply skip to the part where you find interesting. If you are a C beginner, you could read the C book in addition to this quick guide.
Not all the code in this page were tested. Please email me (login: haryadi) if you find one or more bugs.
Part 1:
Part 2:
Part 3:
For each source code below, you simply copy paste the source code to a .c file (e.g. test.c), compile it, and run the executable. If some include files are missing, it's your responsibility to add them.
For more on compling, please read this tutorialprompt> gcc test.c prompt> ./a.out
int main ()
{
printf("Hello World!\n");
return 0;
}
If you compile the hello world program above, you will get an error warning: warning: incompatible implicit declaration of built-in function 'printf'. The reason is you must use printf appropriately, that is, before making a library call, you need to check the manual first:
prompt> man 3 printf
Note the number 3 between the man and printf. The number is needed in this case because there are many programs that use printf, e.g. shell, awk, C, etc. man printf brings you the first manual it can find for printf. In this case, it will give you man 1 printf which is the user command for printf.
Thus, the rule of the thumb is: if you couldn't find what you're looking for by just typing man [your-func], you should use the numberings, man 1 [your-func], man 2 [your-func], and so on until you find the one you're looking for.
The manual tells you that if you want to use printf properly and correctly, you should add #include <stdio.h>. So, here is your final code:
#include <stdio.h>
int main ()
{
printf("Hello World!\n");
return 0;
}
Thus, the lesson is always check the manual. Specifically, you should look
for:
#include<stdio.h>
int main()
{
int x = 78;
double y = 12.34;
char aWord [20] = "I like C";
printf("a: |%d|\n", x);
printf("b: |%1d|\n", x);
printf("c: |%2d|\n", x);
printf("d: |%3d|\n", x);
printf("d: |%4d|\n", x);
printf("e: |%-3d|\n", x);
printf("f: |%-4d|\n", x);
printf("g: |%02d|\n", x);
printf("h: |%03d|\n", x);
printf("i: |%f|\n", y);
printf("j: |%5.2f|\n", y);
printf("k: |%8.2f|\n", y);
printf("l: |%08.2f|\n", y);
printf("m: |%-8.2f|\n", y);
printf("n: |%5.4f|\n", y);
printf("o: |%s|\n", aWord);
printf("p: |%30s|\n", aWord);
printf("q: |%-30s|\n", aWord);
}
Declaring a variable is straighforward. First you define the type (e.g. int, double), and the name of your variable. Optionally you can initialize them.
Note that C compilers require you to declare all your variables in the beginning of the function. If you want to declare variables in the middle of the function, such as:int x; double y; int z = 7;
You need to compile your program with c99 standard: gcc -std=c99....for (int i = 0; i < 10; i++)...
In C, there is no built-in string type, and that's why you love C ... or not. A string is basically an array of characters. Thus, to declare a string, you need to build an array of characters (the same way you build an array of integers).
char aString [10];
If you want to initialize it with empty string, you can do it in different ways: during declaration, or use strycpy (again, don't forget to check man strcpy), or set the first character to NULL.
1) char aString [10] = ""; 2) strcpy(aString, ""); 3) aString[0] = '\0';
If you don't initialize the string during the declaration, you cannot simply assign the string using the equal "=" operator. You use strcpy.
Finally, if you have two strings (two arrays of characters), and you want to copy one from another, you cannot use the equal "=" operator. You must use strcpy.aString = "What? I can't do this?!!#@*%";strcpy(aString, "this way is correct");
char dst [30] = "empty"; char src [30] = "copy me please";dst = src;// you can't do this, sorry strcpy(dst, src); // this is right
struct container {
int x;
int y;
}; // remember to put a semicolon here
int main ()
{
struct container c;
c.x = 0;
c.y = 2;
printf("%d \n", c.x);
printf("%d \n", c.y);
return 0;
}
// Form 1: while
i = 0;
while (i < 100) {
printf("%d");
i++;
}
// Form 2: do while, executes the while-body at least once
// before performing the check
i = 0;
do {
printf("%d");
i++;
} while (i < 100);
// Form 3: for
for (i = 0; i < 100; i++) {
printf("%d");
i++;
}
// Form 4: goto, people rarely do this,
// but you see this a lot in the Linux kernel
i = 0;
repeat:
printf("%d");
i++;
if (i < 100) {
goto repeat;
}
There are two forms of branch: if and switch.
if can accept complex logic, switch can only
accept equality. For more please see the C book.
if (i < 10) {
// do something
}
else {
// do something else
}
switch(i) {
case 1:
printf(" i is 1 \n");
break; // without break you fall through to the second case
// even though i is 1 .. try it
case 2:
printf(" i is 2 \n");
break;
default:
printf(" i is neither 1 nor 2 \n");
}
#define LINE_MAX 80
int main() {
int i = 0;
while (i < LINE_MAX) {
fgets(...);
}
}
char a;
while (1) {
a = getchar();
if (a == EOF)
break;
printf("%c", a);
}
Or you could be a little bit fancy by doing this:
while ((a = getchar()) != EOF) {
printf("%c", a);
}
(a = getchar()) != EOF basically performs two things: first it stores
the return value of getchar to a, and then compares a
with EOF.
To try the program above, compile and run this way:
> gcc test.c > ./a.out ---> this will simply wait for your character inputs > ./a.out < aFile --> this will take and print each character in the aFile
char input [10];
gets(input);
printf("%s", input);
Compile and run that. Moreover, when you type a line, use more than 10 characters. You suppose to get Segmentation fault because the OS only allocates 10 characters for input, but you overflow it; your program attempts to write to invalid memory addresses.
A better way is to use fgets, which requires you to specify how many characters you want to read from a file or from the prompt. If you wrongly specify the length, it's your fault.
char input [10];
fgets(input, 10, stream);
printf("%s", input);
Run it, and type as many characters as you want, and see what happens. Supposedly, it only accepts 9 characters (not 10? how do I know? read the manual :), the 10th character is for the null-terminating character.
If you feed in 15 characters, and it only accepts 9 characters, where would the other 6 characters go? Does the C library discard or buffer the rest of the characters? The answer is buffer. Try calling fgets twice and see what will happen.
fgets(input, 10, stream);
printf("%s", input);
fgets(input, 10, stream);
printf("%s", input);
#include<stdio.h>
int main()
{
f();
}
void f()
{
printf(" Hello world !\n");
}
You should get a warning:
The warning is produced by the C compiler because the compiler works from the top to the bottom of the file. In short, when the compiler sees that the main function calls a function f, it hasn't seen the declaration of f. You can get this around by putting the whole function f(){..} before main(){..}, but this is not the best solution. What you need to do is to tell in advance the functions that you want to call. This is also called as function prototype. In this case we need to copy the function header and put it before main.test.c:7: warning: conflicting types for 'f' test.c:4: warning: previous implicit declaration of 'f' was here
#include<stdio.h>
void f(); // --> this is called a function prototype;
int main()
{
f();
}
void f()
{
printf(" Hello world !\n");
}
Let's see how call by reference works. The problem this works only in C++, not C:
void makeDouble (int & x)
{
x = x * 2;
}
int main ()
{
int y = 7;
makeDouble (y);
printf("%d \n", y);
return 0;
}
Copy paste the above program into test.cpp (Notice the
.cpp extension!). Compile the program using g++, the
C++ compiler:
The result is 14. Why? Notice the & (ampersand) sign in makeDouble(int & x). The ampersand sign informs the C++ compiler that when makeDouble is called, it should pass the address of> g++ test.cpp > ./a.out
Now, suppose in C, we want to do the same thing. Unfortunately, C cannot accept the int & x syntax. So, let's remove the &:
void makeDouble (int x)
{
x = x * 2;
}
int main ()
{
int y = 7;
makeDouble (y);
printf("%d \n", y);
return 0;
}
Copy paste the program above into test.c (Notice the
.c extension!). Compile the program using gcc, the C
compiler:
If you know how C works, the above code will print 7, not 14! The technical explanation is when makeDouble is called , only the value of y is passed to x. Hence, the makeDouble function doubles x in a different memory location. Specifically, y lives in the main stack and x lives in the makeDouble stack. Don't trust me? Let's debug their addresses.> gcc test.c > ./a.out
void makeDouble (int x)
{
printf("Time 2: Address of x = %08x, Value of x = %d \n", &x, x);
x = x * 2;
printf("Time 3: Address of x = %08x, Value of x = %d \n", &x, x);
}
int main ()
{
int y = 7;
printf("Time 1: Address of y = %08x, Value of y = %d \n", &y, y);
makeDouble (y);
printf("Time 4: Address of y = %08x, Value of y = %d \n", &y, y);
return 0;
}
If I compile and run the program above in my machine, I get this
output:
You can see that the addresses of x and y are different! That's the core reason why updating x does not affect y. Surely this looks simple (No?). But when we get to pointer and structure initializations, printing the addresses will help you understand what's going on at the low level.Time 1: Address of y = bf94b7e0, Value of y = 7 Time 2: Address of x = bf94b7c0, Value of y = 7 Time 3: Address of x = bf94b7c0, Value of y = 14 Time 4: Address of y = bf94b7e0, Value of y = 7
As a side note, the addresses above are virtual address, not physical memory address. The memory management coverts virtual address to physical address. This will be much clearer when we have discussed memory management in the class.
int main()
{
int I = 7;
int *pI = & I; // make pI points to I
int **ppI = & pI; // make pI points to ppI
printf(" I is %d \n", I);
printf(" *pI is %d \n", *pI);
printf("**ppI is %d \n", **ppI);
}
The logical view looks like this: ppI --> pI --> I (7). Now, let's print
the addresses to prove this:
int main()
{
int I = 7;
int *pI = & I; // make pI points to I
int **ppI = & pI; // make ppI points to pI
printf(" I's address is %08x , I's value is %d \n", &I , I );
printf(" pI's address is %08x , pI's value is %08x \n", &pI , pI );
printf("ppI's address is %08x , ppI's value is %08x \n", &ppI , ppI);
}
The output in my machine is:
Let's discuss the addreses first. These addresses point to the area within the stack that keeps the I, pI, and ppI variables. As you can see, their addresses differ by 4 (i.e. bfbec278 + 4 = bfbec27c , bfbec27c + 4 = bfbec280). This is because an integer and a pointer are only 4 bytes long. (Note in 64-bit system, a pointer is 8 bytes long).I's address is bfbec280 , I's value is 7 pI's address is bfbec27c , pI's value is bfbec280 ppI's address is bfbec278 , ppI's value is bfbec27c
At the memory-level, a pointer basically contains the address of what it is pointing to. For example, since pI points to I, pI value is the address of I (i.e. bfbec280). Since ppI points to pI, ppI value is the address of pI (i.e. bfbec27c). In summary, this what the stack looks like:
Physical View | Logical View
---------------------------------------
| Address | Value |
| | |
| .. | .. |
| | |
| bfbec278 | bfbec27c | ppI ---------
| | | |
| bfbec27c | bfbec280 | pI ---- <---
| | | |
main: | bfbec280 | 7 | I <----
As a side note, in C++ you don't have to deal with pointers because C++ developers let you go around with that by using call by reference. In Java, the developers are much nicer -- everything is a pointer, but they hide it for you.
const int x = 100;
printf("x is %d , can you change me? \n", x);
The answer is yes, and here's the trick below. The idea,
const is only bound to variable x, but not the
pointer messer.
const int x = 100;
int * messer = & x;
*messer = 1000000;
printf("x is now %d , so amazing ..\n", x);
struct something {
int x;
int y;
};
void init(struct something s1)
{
s1.x = 100;
s1.y = 200;
}
int main()
{
struct something s0;
init(s0);
printf(" %d %d \n", s0.x, s0.y);
}
Exactly! The program will print garbage because in C everything is
passed by value. When init is called, the OS allocates a
memory of 8 bytes (ask yourself why 8?) in the stack for s1.
The contents of s0 is copied to s1. Thus,
s1 and s0 are at different addresses. When we
initialize x and y to 100 and 200, the changes are reflected only to
s1. After the initialization is done, the memory space from
the invocation of init will be wiped out. Nothing affects
s0.
int g = 30;
void f()
{
int y = 20;
printf(" y's address is %08x , y's value is %d \n", & y, y );
printf(" g's address is %08x , g's value is %d \n", & g, g );
}
int main()
{
int x = 10;
f();
printf(" x's address is %08x , x's value is %d \n", & x, x );
printf(" g's address is %08x , g's value is %d \n", & g, g );
}
The output on my machine:
As you can see x and y live in the stack (i.e. addresses bfd1...), while g lives in the heap (address 0804...). Stack grows from lower address to upper address, and heap is the other way around.y's address is bfd1e374 , y's value is 20 g's address is 08049684 , g's value is 30 x's address is bfd1e3a0 , x's value is 10 g's address is 08049684 , g's value is 30
Remember that the memory space used in the heap will be wiped out when the program exits, while the memory space used in the stack will be wiped out when the corresponding function exits.
struct something
{
int x;
int y;
};
int main()
{
int *a;
struct something *s;
a = malloc(sizeof(int));
s = malloc(sizeof(struct something));
*a = 100;
(*s).x = 200;
s->y = 300;
printf(" %d %d %d \n", *a, (*s).x, s->y);
printf(" Address of a = %08x \n", a);
printf(" Address of s = %08x \n", s);
free(a);
free(s);
}
There is a couple of notes here.
First, malloc expects you to give the size of the requested memory. Why? isn't it obvious that an integer is 4 bytes and struct something is 8 bytes? In this example, yes. But malloc is a generic function; it can be used for allocating a dynamic-length array (e.g. int *array = malloc( 10 * sizeof(int) );). We'll see an example of dynamic-length array later.
Second is about dereferencing a pointer. For example, since a is a pointer to an integer, to get the number, we need to dereference the pointer once (i.e. *a). The same thing for structure; since s is a pointer to a structure, dereferencing it (*s) will give us the structure. Thus, to access the fields inside the structure we use this notation (*s).x. Yuch! This is a very ugly notation. Luckily, C helps us a little by allowing us to use a more compact notation s->x.
Third, malloc will allocate memory space dynamically, which means that the allocated memory resides in the heap (check the address again if you don't believe me). Again, the allocated memory will not be wiped out until the program exits. A good practice is to always free the allocated memory once you are done with it. Otherwise, you have memory leak problem.
Using malloc is an example where we can run out of memory. Run this program for a while, and see what will happen:
struct something
{
int x;
char y [1024*32];
};
int main()
{
struct something *s;
while (1) {
s = malloc(sizeof(struct something));
printf(" Address of s = %08x \n", s);
s->x = 1;
}
}
You'll get a segmentation fault. What's happening is you allocate
memory all the time without freeing it. Then, when you run out of
memory, you forget to check the returned error code from
malloc. Reading man malloc tells you that
malloc could return NULL if there is no memory left. So, this
is the correct code:
while (1) {
s = malloc(sizeof(struct something));
// error handling
if (s == NULL) {
printf(" I hate malloc ... \n");
printf(" I hate memory ... \n");
printf(" I hate NULL ... \n");
printf(" I hate C ... \n");
printf(" I hate 537 ... \n");
printf(" I hate OS ... \n");
printf(" I love myself though ... \n");
exit(1);
}
printf(" Address of s = %08x \n", s);
s->x = 1;
}
struct something
{
int x;
int y;
};
void init_structure(struct something *s1)
{
s1 = malloc (sizeof(struct something));
if (s1 == NULL) {
// your error handling (or complaints) goes here
exit(1);
}
}
int main()
{
struct something *s0;
init_structure(s0);
s0->x = 10;
s0->y = 20;
}
You'll get a segmentation fault! Why? If you're adventurous (or you
only take 1 class), think about this for a while, and try to think of
the solution. If you take five 500-level courses, I feel you, so you
can proceed.
Let's debug the program by showing the addresses and the values again. Remember that the value of a pointer is the address of what it is pointing to. Another way to think about this is, in memory, an integer holds an integer number, while a pointer holds an address.
void init_structure(struct something *s1)
{
printf("Time 2: s1's address is %08x, s1's value is %08x \n", & s1, s1);
s1 = malloc (sizeof(struct something));
printf("Time 3: s1's address is %08x, s1's value is %08x \n", & s1, s1);
}
int main()
{
struct something *s0;
printf("Time 1: s0's address is %08x, s0's value is %08x \n", & s0, s0);
init_structure(s0);
printf("Time 4: s0's address is %08x, s0's value is %08x \n", & s0, s0);
s0->x = 10;
s0->y = 20;
}
My output is:
First, note the difference between the addresses of s0 and s1. They are different because s0 lives in the main stack, while s1 lives in the init_structure stack. This implies that any modification to s1 in init_structure only happens to s1 but not to s0!Time 1: s0's address is bf9c19e0, s0's value is 002f85d0 Time 2: s1's address is bf9c19c0, s1's value is 002f85d0 Time 3: s1's address is bf9c19c0, s1's value is 09a56008 Time 4: s0's address is bf9c19e0, s0's value is 002f85d0
At Time 1, s0 points to a garbage (002f85d0), thus at Time 2, s1 initially gets a garbage too. Remember again, in C everything is passed by value. In this case, the value of s0 (which is a garbage) is copied to s1.
At time 3, s1 gets a memory at the heap from the malloc call. This heap area is only pointed by s1 (not s0). After the init_structure exits, s1 is destroyed.
At time 3 this is what the memory looks like:
Physical View | Logical View
---------------------------------------
| Address | Value |
| | |
HEAP: | 09a56008 | something| (heap) <--
| | | |
| | | |
| .. | .. | |
| | | |
| | | |
| | | |
inits:| bf9c19c0 | 09a56008 | s1 -------
| | |
main: | bf9c19e0 | 002f85d0 | s0 ---[points to]---> garbage
And at time 4, the invocation of init_structure is wiped out, s1 is
gone. The result is: first, s0 still points to a garbage, and
we have a
memory leak. The dynamically-created memory is still allocated
but not pointed by anyone, hence, cannot be referenced.
Physical View | Logical View
---------------------------------------
| Address | Value |
| | |
HEAP: | 09a56008 | something| (heap) <---- X (memory leak!)
| | |
| | |
| .. | .. |
| | |
| | |
| | |
inits:| bf9c19c0 | 09a56008 | s1
| | |
main: | bf9c19e0 | 002f85d0 | s0 ---[points to]---> garbage
void init_structure(struct something **s1)
{
*s1 = malloc (sizeof(struct something));
}
int main()
{
struct something *s0;
init_structure(& s0);
s0->x = 10;
s0->y = 20;
printf(" %d %d \n", s0->x, s0->y);
}
Let's print the addresses and values again:
void init_structure(struct something **s1)
{
printf("Time 2: s1's address is %08x, s1's value is %08x \n", & s1, s1);
printf(" *s1's address is %08x, *s1's value is %08x \n", s1, *s1);
*s1 = malloc (sizeof(struct something));
printf("Time 3: s1's address is %08x, s1's value is %08x \n", & s1, s1);
printf(" *s1's address is %08x, *s1's value is %08x \n", s1, *s1);
}
int main()
{
struct something *s0;
printf("Time 1: s0's address is %08x, s0's value is %08x \n", & s0, s0);
init_structure(& s0);
printf("Time 4: s0's address is %08x, s0's value is %08x \n", & s0, s0);
s0->x = 10;
s0->y = 20;
printf(" %d %d \n", s0->x, s0->y);
}
My output is:
Time 1: s0's address is bfb14410, s0's value is 002f85d0
Time 2: s1's address is bfb143f0, s1's value is bfb14410
*s1's address is bfb14410, *s1's value is 002f85d0
Time 3: s1's address is bfb143f0, s1's value is bfb14410
*s1's address is bfb14410, *s1's value is 09192008
Time 4: s0's address is bfb14410, s0's value is 09192008
The virtual memory at time 3 looks like this:
Physical View | Logical View
---------------------------------------
| Address | Value |
| | |
HEAP: | 09192008 | something| (heap) <----
| | | |
| | | |
| .. | .. | |
| | | |
| | | |
| | | |
inits:| bfb143f0 | bfb14410 | s1 ---- |
| | | | | (note: *s1 is basically s0)
main: | bfb14410 | 09192008 | s0 <--- |
---------
The virtual memory at time 4 looks like this:
Physical View | Logical View
---------------------------------------
| Address | Value |
| | |
HEAP: | 09192008 | something| (heap) <----
| | | |
| | | |
| .. | .. | |
| | | |
| | | |
| | | |
inits:| bfb143f0 | bfb14410 | s1 ---- |
| | | | (note: *s1 is basically s0)
main: | bfb14410 | 09192008 | s0 ---------
Thus, at time 4, your struct pointer has been initialized correctly.
What about time 1 and 2? Make yourself the memory snapshots for time
1, 2, and 4.
Second, how about if you need to make an arbitrary-size array? You use malloc. An array is technically a pointer to some elements stored consecutively in memory. For example, this array initialization is the same as above, except you need to free the memory after you finish using it.int anArray [10];
Third, you normally access the elements in the array using indices, such as anArray[i]. For example:int *anArray; anArray = malloc ( 10 * sizeof(int) ); ... free(anArray);
int main()
{
int anArray[10];
int i;
for (i = 0; i < 10; i++)
anArray[i] = i;
for (i = 0; i < 10; i++)
printf(" %d \n", anArray[i]);
}
You might like more challenging stuffs, so you ask yourself, can I
iterate the array without using indices? Sure you
can. anArray is simply a pointer to a consecutive integers in
the memory. Thus, we could create another pointer to integer that we
could fully control to access the elements of the array:
int main()
{
int anArray[10];
int *fancy;
int i;
for (i = 0; i < 10; i++)
anArray[i] = i;
fancy = anArray;
for (i = 0; i < 10; i++) {
printf(" fancy: %d \n", *fancy);
fancy++;
}
}
The code above uses an extra integer-pointer, fancy, that is
incremented by one in every iteration. The C compiler knows that fancy
is an integer (4 bytes long), therefore when we increment fancy by
one, the C compiler increments the address that fancy is pointing to
by 4. To understand this more, try these two examples below:
int main() { int anArray[10]; int *fancy; int i;
for (i = 0; i < 10; i++)
anArray[i] = i;
fancy = anArray;
for (i = 0; i < 10; i++) {
printf(" i=%d --> %d \n", i, *fancy);
fancy = fancy + 2;
}
}
The code above should print 0, 2, 4, 6, 8, and then some garbage. You
should know the reason by now: the last five accesses are
out-of-bound. What?? C lets me do this? Yes, C expects you to be a
responsible programmer. Unlike Java, which will be warn you if there's
an out-of-bound array access, C treats you like an adult (which could
be a good or a bad thing).
Here's the last example on array. Compile and run this:
int main()
{
long long anArray[10];
int *fancy;
int i;
for (i = 0; i < 10; i++)
anArray[i] = i;
fancy = anArray;
for (i = 0; i < 10; i++) {
printf(" i=%d --> %d \n", i, *fancy);
fancy++;
}
}
The output should be 0, 0, 1, 0, 2, 0, 3, 0, 4, 0. How come? Here's the hint: long long creates 64 bits (8 bytes) number, while int only represents 32 bits (4 bytes) number. You should be able to figure out the rest.
int main()
{
char *a;
char b [10];
sprintf(b, "hello");
strcpy (a, b);
}
You're gonna say the program will crash because a has not
been given memory. You're right, but don't forget to check man
strcpy. The manual says that the library will not allocate
memory for a, thus the program will crash.
So far, we simply create a program that does exactly one thing. But sometimes, we want to have the program do different things without recompiling the program. We can do that by feeding the program with more command-line arguments. Try the code below and play around with it.
int main(int argc, char **argv)
{
int i = 0;
char * anArg;
int option;
if (argc != 4) {
printf(" ./a.out [1 or 2] [a word] [a word] \n");
exit(1);
}
// this prints all the args
for(i = 0; i< argc; i++) {
anArg = argv[i];
printf(" arg %d = %s \n", i, anArg);
}
printf("\n");
// do something, depends on the arg
printf(" I want to print : ");
option = atoi(argv[1]); // change a string to an int, see 'man atoi'
if (option == 1) {
printf(" %s \n", argv[2]);
}
else if (option == 2) {
printf(" %s \n", argv[3]);
}
else {
printf(" I only accecpt 1 or 2 \n");
}
}
Compile and run it:
> ./a.out 1 abc def > ./a.out 2 abc def
First, almost all operating systems are written in C because C lets you do low-level tricks, sometimes to make things go fast.
Second, you might wondering why I give these crazy examples as if we have lots of spare time. Well, the reason is, you'll be a system programmer. OS developers tend to use one of the tricks above to do their work. For example, they love to use extra pointers to access some relevant parts of a given array. A more specific example: A network packet is comprised of lots of headers (IP, TCP/UDP, MAC Address, etc.). When the OS receives a network packet, it only sees an array of bytes. The OS programmers need to manage extra pointers to access those specific headers.
So, hopefully this tutorial will bring benefits to your future.