Jump to content
xisto Community
Sign in to follow this  
heaven_master_ash

Tutorial: Help About C & C++ Programming Langauge

Recommended Posts

Help About C & C++ Programming Langauge


Prologue

I remember the time I started learning C. It was not too long ago. I liked programming, I always did, but I didn't know a lot of languages. The only languages I knew were useless, such as Visual Basic, PHP, ASP, and the basics of Javascript and VBScript.
So I decided to learn a real language: C. So I downloaded some tutorials and started reading. The well known "Hello, world!" program didn't cause any difficulties, nor did the few programs after it.

But then some new word showed up in the tutorial: "pointer". What was this horrible thing? I kept reading, but I just could not understand it. Maybe it was because my first language wasn't English, and the explenation was too hard? I didn't know - I still don't actually. Maybe my English was too bad back then?

Fortunately I didn't give up and kept on reading. I understood everything except for the pointer, and it was a huge pain in the **bottom**. Pointers are used very often in C. And it took a long time before I really understood how pointers worked and yet it was actually very easy... Once you understand it. So I will try to explain it in this tutorial. Basic knowledge of C is required.

POINTERS

What is a pointer?

A pointer is nothing else than an address of some place in the memory. A pointer can be defined like:
char* test;
In this case, test is a number, not a char as you might think. It's a number - an address to be exact. This address is an address of a place in the memory.
Let's describe the memory as a bunch of lines. Every line (-) is one byte. The "^" points to a line, thus to a byte. Now have a look at the following drawing:

--------------------------------------------------------------------------
^

The "^" points to a byte. It just shows you one place in the memory. It's a pointer(!) to a place in the memory.


So the pointer is an address. The address may or may not already point to a valid address in the memory right after you declared it, that depends on the way you declare it:
char* test;
will NOT point to a valid address in the memory. You will have to make it point somewhere before you read/write from/to it, or else a "Segmentation Fault" will occur.

char test[10];

will point to a valid address in the memory. You can read/write from/to the memory, but be careful: you can not read/write more than 10 characters (note the [10]?). If you DO read/write more than 10 characters, a "Segmentation Fault" will occur. Of course this 10 can be changed, which will allow more characters to be read/written.
What's the use of pointers?

There are many uses of pointers. A lot of functions need pointers to be passed. One example is printf if you want to print a string: it will need a pointer to this string. Another use is the ability to use arrays. You may not know what it means now, but I will cover that later. I do assume you know what printf does and how it works. If you do not, please read the printf manual.

Point the pointer

In case you define it the first way ("char* test"), it will not yet point to a valid address in the memory. You can make it point somewhere with malloc. Malloc will reserve the specified amount of bytes and return the memory address of this.

So malloc will create a place in the memory where you can read/write from/to without any problems. It will "allocate" some space in the memory (malloc = Memory ALLOCate). The malloc function will take the ammount of space to allocate as a parameter and return the pointer to the memory. It will return a "void *", but that doesn't matter since all pointers are actually handled exactly the same. Though, there are differences in how you can read/write from/to the memory, so always use the type you want to read or write.

An example:

char* test;
test = (char*)malloc(10);


This will allocate 10 bytes (10 bytes, not 10 characters! The size of a character is 1 byte most of the times, but it may differ.), and assign the location of the memory to test. Note that I use "(char*)" before malloc. This will not convert anything and this is not required. Though, if you don't do this your compiler will display a warning ("warning: assignment makes pointer from integer without a cast"), and it is best to have as little warnings in your program as possible.

[indent]Malloc or [#]
So there are two ways to create a pointer to the memory to write to:
char test[10];
or
char* test;test = (char*)malloc(10);

Of course the number 10 can be changed into any number above 0 (although there is a maximum, but you will probably never reach it).


There are two differences in these ways. The first difference is that from "char test[10];", the size can not be changed. It will keep a length of 10 characters but you can always re-allocate the space for a "char* test;". The second difference is that "char test[10];" will reserve 10 characters while malloc will reserve 10 bytes if you specify 10 as the parameter. On most machines a character will be 1 byte, but this is not on all machines. You can use "malloc(10 * sizeof(char));" to allocate 10 characters in stead of 10 bytes (sizeof(char) will return the size of one character, multiplied with the number of characters to allocate will be the memory in bytes to allocate). You should always do this so that your program will be portable to other computers.

Malloc may fail. This can for example happen when there wasn't enough memory to allocate the specified bytes. If this happens, malloc will return NULL. You should always check whether its NULL after you allocated some space. If you write to a NULL pointer, a "Segmentation Fault" will occur.

I will use "[#]" the rest of this tutorial, because that's easier. Note that the other method may be required sometimes, but since that not the case now and "[#]" will only be one line of code, I will use that method.

Free

If you have a pointer created by malloc which you will not use anymore, you should ALWAYS use free(pointer); (where pointer is the pointer). You must do this before you use malloc on the same pointer again, too. If you do not do this, your program will leak memory. This is bad if it happens once or twice, but can kill your program if it happens very often!

But there is another way to kill your program, which you should watch out for, too. You may not EVER free a pointer which either has not yet been allocated, which failed to be allocated or which has been defined with "[#]". If you do this, a "Segmentation Fault" will occur.
So to make sure you are not freeing a pointer that failed to be created, you should always add a check before you free it:

if(test != NULL)free(test);

But if you declared test with "char* test;", test will not be NULL. So if it is not allocated and it tries to free it, the program will crash. This is why you should alway declare pointers you will malloc later with "char* test = NULL;". That way the default will be NULL, and the above check will also prevent it from freeing unallocated parts of the memory.

One more tricky part: free will not make the pointer NULL again. So if it is possible it would free it more than once, always use the following check:
if(test != NULL){free(test);test = NULL;}
test will be set to NULL when freed, and will not be freed anymore until it has been re-allocated.
Access the memory one by one

You can access the memory on several ways. One way is to access it one by one. I can't say byte by byte, since it differs on how you declared it. For example, if you used a pointer to an integer, this will work integer by integer. If it's to a character it will work character by character.
For example, let's define it as a char:

char test[10] = "0123456789";

This will allocate the space for 10 characters (10 x sizeof(char) bytes), and put "0123456789" in the memory on that place. Test will point to the first character to this string: "0". Now lets say you have defined a character: "char test2;" and you want to put the second character of test in it. What could you do?

What we actually got is nothing else than an array of characters: 10 characters after each other. You can simply access these characters in the memory with "test[#];". Replace the "#" with the number of the character you need, minus one. In this case, "test[0]" equals "0". This way of accessing it will select a char from the memory, not a byte. So in this case, you can pick any number from 0 to 9, and test[#] (where # is your chosen number) will have your number stored as character. Make sure you do not pick a number below 0 or higher than 9, or else it will cause the program to crash with a "Segmentation Fault" or just return a character from another part of the memory.

So test[1] will be in the memory with the address test + 1 * sizeof(char). Test[#] will not return a pointer, but a char, but "test + 1 * sizeof(char)" is possible and will return a pointer. Of course, test[2] will be in the memory with the address test + 2 * sizeof(char), etc.
You can also get a character of a specified memory address by adding a "*" in front of it. For example, "char test2 = *test;" will put the character test points to in test2. Again, you can also use "char test2 = *(test + 1 * sizeof(char));", which will select the second character in the array.

So this means that
"test[0]" equals "*test","test[1]" equals "*(test + 1 * strlen(char));","test[2]" equals "*(test + 2 * strlen(char));",
and so on.

Here, too, you must pay attention: you may not read in a memory location you did not allocate. Otherwise the result will be a character of something different in the memory from or, again, cause a "Segmentation Fault".
Of course you can write to the memory the same way:
test[0] = 'a';
will put the character "a" in the memory ('' is for characters, "" is for pointers to strings), and
*test = 10;
will put a return character (\n, ascii code 10) in the memory test points to.

Value to pointer

Let's say you have a character and you would like to know where in the memory it is. It's very simple to do this: just put a "&" in front of the variable you want the pointer of, and it will return a pointer. So:

char* test;char test2 = '!'; //This character is somewhere in the memory... but Where?test = &test2; //Ah, there it is!

Now test contains the address of the memory where test2 is stored. This can be used on, for example, the following way:

char test[11] = "0123456789\0";//\0 Makes sure it ends with a 0-character. If not, the printf//function will just keep on reading until it sees a 0-char.//So it will display characters which should not be shown.//Or may cause a "Segmentation Fault"printf("%s\n", &test[1]);

The first thing to explain is the term a "0-character". It's a character with the ascii code 0. In a string, it identifies the end of the string. If this is read, the functions know what the end of the string is.
test[1] will select the second character. The & will make a pointer of it. So the pointer to the second character of "0123456789" will be passed, thus the memory address of the character '1' will be passed to printf. Printf will read the memory, and show the characters there. So it will show "123456789". If test[10] would not be 0, it would keep on reading memory outside test's allocated memory, and possible show characters that should not be shown, maybe even complete passwords if you're unlucky or it may crash with a "Segmentation Fault".
Copy functions

You can use the method described above to assign values to the memory manually. Of course, this is a lot of work for some tasks. For example, if you would want to put "test" in the memory, ending with a 0 character so that you can use it with printf(); later, you could use:

char test[5];test[0] = 't';test[1] = 'e';test[2] = 's';test[3] = 't';test[4] = 0;
Too much work. And you can't use
char test[10] = "0123456789";test = "9876543210";

either, because that would try to put the string "9876543210" somewhere in the memory, and try to put the pointer in test. Not the string itself into the memory where the pointer points to.
For this use some functions were developed. I won't cover all of them, but I will cover the ones you will probably use most:

- sprintf and snprintf
- strcpy and strncpy
- memcpy


Note that all those functions can cause so called "buffer overflows" these are exploits that can be used for causing the program to crash, or even become (both remote or local) root, or just get a remote shell. You should NEVER try to copy more characters to the destination than allocated for the destination! Check all the data you want to write before you actually write it!
sprintf and snprintf

I said earlier in this tutorial I assume you know how printf works. That's required to understand this function too: this is simply because the sprintf function is almost identical to the printf function. Everything works exactly the same, but it will require one more paramter: the first parameter has to be the pointer pointing to the place in the memory to write to. The output will unlike the printf function not be sent to the screen, but to the memory the pointer points to. An

example:

char test[11];sprintf(test, "%s", "0123456789");

will write "0123456789" to the memory where test points to. This string will be terminated with a 0-character so that you can pass it to functions like printf. Note you will have to spare one character for this 0-character too! But this is still unsafe.
For this matter, snprintf has been developed. This is almost identical to the sprintf function with one difference: it has one more parameter, inserted between the first and second parameter, which will be the MAXIMUM number of characters to write to the memory. This is including the 0-character, thus:

char test[10];snprintf(test, 10, "%s", "0123456789");

Will only print "012345678" to the memory, ended with a 0-character. Note that it will not only stop when the maximum number of characters has been reached, but also when a 0-character is seen. This is because the 10th character is the last character allowed to be written and has to be changed to a 0-character in order be allowed to be passed to functions such as printf, and a lot others. If the string to write is less than the number specified, the number is just ignored. This function is to prevent data from being written to memory where it may not be written.
Both functions will return the number of characters successfuly written, the 0-character not counted. For both functions the strings written to the memory will end with a 0-character.
strcpy and strncpy

Strcpy is even easier than sprintf. Strcpy requires two parameters, both pointers. It will read all data from the memory the second parameter points to and write this to the memory the first parameter points to. It will not stop before it reaches a 0-character (it WILL copy the 0-character too), so you should be 100% sure it ends with one! An example of this function:

char test[11];strcpy(test, "0123456789");

will copy "0123456789" to the memory test points to, including the terminating 0-character (which is added automatically, if you use "").
Strncpy will work exactly the same way, except that it allows a third parameter: the MAXIMUM number of characters to copy. It will stop when the 0-character is reached or if the maximum number of characters has been reached. This means it is possible it does not end with a 0-character.

For example:
char test[5];strncpy(test, "0123456789", 5);

will write "01234" to the memory test points to, but it will not be terminated with a 0-character, so you may NOT pass it to functions such as printf before you checked or added the 0-character. This function is to prevent data from being written to memory where it may not be written.
memcpy

Memcpy is another function to write something to the memory. It works the same as strncpy, except that it will not terminate after a 0-character. This is useful for things other than strings. For example if you have two variables with the same structure, and you want to copy them. The first parameter is the destination, the second the source and the third the number of bytes to write (so it's the same as strncpy).

An example:

struct sockaddr test;struct sockaddr test2;memcpy(&test, &test2, sizeof(test2));

This will copy test2 to the memory where test is located. Test will be exactly the same as test2 after this. Sizeof(test2) characters were copied, which is the complete size. So everything.

Compare functions

Now you may need a way to compare two memory locations. For exmaple, are two strings the same, or are two memory locations the same. For this you will need to know three more functions:
- strcmp and strncmp
- memcmp


strcmp and strncmp

Strcmp is the easiest function to compare. It compares two strings (both the parameters), and it will return 0 if the strings are the same. Both strings must be terminated with a 0-character.

An example:

char test[11] = "0123456789";char test2[11] = "9876543210";if(strcmp(test, test2) == 0)printf("The strings are the same (1)\n");strcpy(test2, "0123456789");if(strcmp(test, test2) == 0)printf("The strings are the same (2)\n");

This will only display the string "The strings are the same (2)\n". Thus only the second time there was a match.
Strncmp is almost identical, but it will take a third parameter: the number of characters to test. It will ignore all the characters behind this.

An example:
char test[11] = "0123456789";if(strncmp(test, "01234", 5) == 0)printf("The first 5 characters are equal (1)!\n");if(strncmp(test, "01234!", 6) == 0)printf("The first 6 characters are equal (2)!\n");

This will only display the string "The first 5 characters are equal (1)!\n". Thus only the first time there was a match.

memcmp

memcmp is identical to strncmp, except that it will not be terminated by the 0-character. This is useful to compare two non-strings, for example structures. Let's take the example from memcpy a bit further:

struct sockaddr test;struct sockaddr test2;memcpy(&test, &test2, sizeof(test2));if(memcmp(&test, &test2, sizeof(test2)) == 0)printf("test equals test2\n");
This equals both test's. Since they were just copied, they are identical.
Comments
This version of this textfile is released in astalavista.net and has been written under the name of my group, the Raiders of the Lost Circuit (RLC). You can contact me (Spoofed Existence) using u2u if you got any questions, comments, etc. You can also contact me with u2u if you would like to join the Raiders of the Lost Circuit. We do not yet have a website, but we are working on it.
The Raiders of the Lost Circuit is not a hacking group. It's a group of all kind of people: we have (and still need) authors, programmers, researchers, exploits finders and lots more. If you think you are good enough for any job, even when this job isn't mentioned here, u2u me and we will talk about it.
And please, DO comment. What isn't clear (enough)? What should be improved?

Share this post


Link to post
Share on other sites

Thanks for posting this information about C and C++ programming.I was trying to learn these two languages but was finding some parts a little difficult. This topic has helped out a little bit by explaining the functions etc in more detail.Hopefully i'll be able to go back to programming finding it a little easier now I've read this <_<

Share this post


Link to post
Share on other sites

inverse of matrix

Tutorial: Help About C & C++ Programming Langauge

 

If we have a 40*40 matrix, then find out the time to calculate the inverse of the matrix I.E the time it will take to give the output of the given matrix.

 

-question by sarvesh

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×
×
  • Create New...

Important Information

Terms of Use | Privacy Policy | Guidelines | We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.