Advertising (This ad goes away for registered users. You can Login or Register)

[Tutorial] Introduction to programming using C (VII)

Discuss about your favorite (gaming...or not) devices here. The most popular ones will end up getting their own categories
Programming discussions for your favorite Device
Forum rules
Forum rule Nº 15 is strictly enforced in this subforum.
User avatar
m0skit0
Guru
Posts: 3817
Joined: Mon Sep 27, 2010 6:01 pm

[Tutorial] Introduction to programming using C (VII)

Post by m0skit0 » Fri Jun 08, 2012 6:54 am

Back to index
<< Prev Next >>

What are pointers

For most new programmers, one of the most confusing things is pointers. It actually is a very simple concept. Let's look at an analogy: email addresses. Your email address is unique, which means no other one has the same email address. This also means emails sent to that email address will be correctly delivered with no confusion. Well, a pointer is also an address, but an address to main memory (RAM).

Main memory is a set of cells where each one has a unique address, represented by a number. Memory addresses (also called "pointers") start at 0 and go as high as the hardware allows. For example in x86-32, maximum memory allowed is 4 GiB, which means the highest memory address is 4,294,967,295 (2^32 - 1 ). Pointers (which are memory addresses, yes I know this is boring, but this must be incrusted in your mind) are usually represented using hexadecimal notation. I want to stress that hexadecimal are not different numbers from decimal or binary. All of them are the same numbers. It's only the way we represent the value that changes. So the previous highest memory address in x86-32 architecture would be written like 0xFFFFFFFF in hexadecimal (the leading 0x is just to denote that the following number is written in hexadecimal).

In previous lesson we already used pointers. Character strings are actually pointers. Let's check this:

Code: Select all

#include <stdio.h>

int main()
{
   char* example = "Hello my friend!\n";
   printf("%d, %x\n", example, example);
   return 0;
}
In this code you can see how we're printing the real value of example, and not what it points to. That is, we're printing the actual value of the memory address and not the content of that memory address. Running this yields this result (for me, for you the address will most likely be different)

Code: Select all

4206692, 403064
Same value but the first number is written in decimal while the second is the same but in hexadecimal.

Ok so now we're going to do a nasty trick. We're going to assign this address to another pointer and print the contents. Of course this will print the "Hello my friend!\n" string because it's the data that resides at that address (remember an address is unique).

Code: Select all

#include <stdio.h>

int main()
{
   char* example = "Hello my friend!\n";
   printf("%d, %x\n", example, example);

   char* example2 = 0x403064;
   printf("%s\n", example2);

   return 0;
}
(Remember to substitute 0x403064 by the address your execution showed!)

This shows:

Code: Select all

4206692, 403064
Hello my friend!
This is of course equivalent of doing char* example2 = example; and as we know this don't mean we're copying the string, but the address of the string. And the address being a number (an int in x86-32) we can have more fun, like:

Code: Select all

#include <stdio.h>

int main()
{
   char* example = "Hello my friend!\n";
   printf("%s\n", example);

   char* example2 = example + 6;
   printf("%s\n", example2);

   return 0;
}
Using pointers

We can specify a pointer to anything that resides in main memory, namely any data or even code. To do so, we use the * modifier, just like we used it in char*. In the following code, I will use a pointer to int data type, and also show other modifiers to work with pointers.

Code: Select all

#include <stdio.h>

int main()
{
   int *a;            // Pointer to int
   int b = 2251;
   a = &b;            // Assigning to a the address of b
   printf("%d\n", *a);   // Printing the value pointed by a

   return 0;
}
The things we said for character strings apply to other pointers as well. In the previous example, we declared int *a. This means we declared the pointer but not the space to store the data it points to. This is a very important concept to keep in mind. And I insist again: declaring pointers doesn't make up space for the data the pointer is pointing to. Please keep this in mind at all times while programming in C.

Ok, but how do we make space (a.k.a. reserve memory) for our variables? Here comes malloc() and friends. malloc() stands for memory allocation. This system call is standard and allows us to reserve memory for our use. Since this is dynamic memory allocation (done during runtime and not during compile-time) we must also take care of freeing this memory using free(). Here's an example:

Code: Select all

#include <stdio.h>
#include <stdlib.h>

int main()
{
   int *a = (int*) malloc(sizeof(int));   // Allocating sizeof(int) bytes of space
   int b = 2251;
   *a = b;                           // Copying content of b to a
   printf("%d\n", *a);                  
   free(a);                        // Free a's reserved memory
   return 0;
}
Another important thing about pointers is what I call intelligent math: the compiler knows what data type you're pointing to due to the pointer declaration (char* points to a char, int* points to an int, etc...), so it makes sure that when you do math operations with the pointer, the compiler does so taking into account the size of the data type pointed to. This is more clear with an example:

Code: Select all

#include <stdio.h>

int main()
{
   // We have a string
   char* string = "This is a pointer use example";
   printf("String at memory address: 0x%08X -> '%s'\n", (unsigned int)string, string);

   // Now let's have 2 different pointer types point to it as well
   char* p1 = string;
   int* p2 = (int*) string;

   // We increment a char pointer -> incremented by sizeof(char) = 1 byte
   p1++;
   printf("p1 = 0x%08X, points at: '%s'\n", (unsigned int)p1, p1);

   // We increment an int pointer -> incremented by sizeof(int) = 4 bytes (x86)
   p2++;
   printf("p2 = 0x%08X, points at: '%s'\n", (unsigned int)p2, (char*)p2);

   return 0;
}
As you can see, incrementing p1 is not the same as incrementing p2 because they point to data types with different sizes. This is a source of quite hard to track bugs if you don't pay attention.

Array decay convention

In C, arrays can "decay" into pointers and viceversa, which means that arrays are equivalent to pointers. Thus for example char[] is the equivalent of char*. Example:

Code: Select all

#include <stdio.h>

int main()
{
   char *string = "This is a pointer use example";
   printf("%s\n", string);
   printf("%c, %c\n", string[1], string[5]); // Print second and sixth character

   return 0;
}
And finally here are some exercises to practice this stuff :)
  • Using only pointers: declare an array of signed integers and assing it a size of 50 integers.
  • Same as the last exercise but also assign positions 5, 6, and 8, and then print them.
  • Using only pointers: given a random string, print from the 5th character onwards.
  • Given 2 strings of length 5, encrypt the first one using the second one using an XOR operation.
EDIT: I removed some exercises and put new ones since we haven't seen functions yet :?
EDIT2: changed the exercises since we haven't seen flow control yet :oops:

<< Prev Next >>
Advertising
I wanna lots of mov al,0xb
Image
"just not into this RA stuffz"

Wdingdong
Posts: 92
Joined: Tue Aug 02, 2011 5:34 pm

Re: [Tutorial] Introduction to programming using C (VII)

Post by Wdingdong » Fri Jun 08, 2012 6:50 pm

First of all, a very basic doubt, What's the difference between int* a; and int *a?
m0skit0 wrote:

Code: Select all

#include <stdio.h>

int main()
{
   char* example = "Hello my friend!\n";
   printf("%s\n", example);

   char* example2 = example + 6;
   printf("%s\n", example2);

   return 0;
}

Code: Select all

int main()
{
   // We have a string
   char* string = "This is a pointer use example";
   printf("String at memory address: 0x%08X -> '%s'\n", (unsigned int)string, string);

   // Now let's have 2 different pointer types point to it as well
   char* p1 = string;
   int* p2 = (int*) string;

   // We increment a char pointer -> incremented by sizeof(char) = 1 byte
   p1++;
   printf("p1 = 0x%08X, points at: '%s'\n", (unsigned int)p1, p1);

   // We increment an int pointer -> incremented by sizeof(int) = 4 bytes (x86)
   p2++;
   printf("p2 = 0x%08X, points at: '%s'\n", (unsigned int)p2, (char*)p2);

   return 0;
}

Code: Select all

#include <stdio.h>

int main()
{
   char *string = "This is a pointer use example";
   printf("%s\n", string);
   printf("%c, %c\n", string[1], string[5]); // Print second and sixth character

   return 0;
}
Cool.
m0skit0 wrote:

Code: Select all

#include <stdio.h>
#include <stdlib.h>

int main()
{
   int *a = (int*) malloc(sizeof(int));   // Allocating sizeof(int) bytes of space
   int b = 2251;
   *a = b;                           // Copying content of b to a
   printf("%d\n", *a);                  
   free(a);                        // Free a's reserved memory
   return 0;
}
This program works fine without the malloc() function, I mean value of b is copied to memory pointed by a, right?(I tested it).

And do malloc() function reserve the succeeding memory to the memory pointed by pointer?
Advertising
// Big thanks to people who share information !!!

snailface
Posts: 95
Joined: Tue May 24, 2011 8:02 pm

Re: [Tutorial] Introduction to programming using C (VII)

Post by snailface » Fri Jun 08, 2012 10:36 pm

Wdingdong wrote:First of all, a very basic doubt, What's the difference between int* a; and int *a?
Nothing, it compiles the same.

Wdingdong wrote: This program works fine without the malloc() function, I mean value of b is copied to memory pointed by a, right?(I tested it).

And do malloc() function reserve the succeeding memory to the memory pointed by pointer?

Code: Select all

    #include <stdio.h>
    #include <stdlib.h>

    int main()
    {
       int *a;  // *not* allocating sizeof(int) bytes of space
       int b = 2251;
       *a = b;                           // Copying content of b to a
       printf("%d\n", *a);
       free(a);                        // Free a's reserved memory
       return 0;
    }
You sure? Removing malloc crashes the program in my computer and it will certainly for yours too if you make b a large data block. In any event, it is bad practice to remove malloc. Always reserve enough memory.
Image

Wdingdong
Posts: 92
Joined: Tue Aug 02, 2011 5:34 pm

Re: [Tutorial] Introduction to programming using C (VII)

Post by Wdingdong » Sat Jun 09, 2012 12:27 pm

snailface wrote:You sure? Removing malloc crashes the program in my computer and it will certainly for yours too if you make b a large data block. In any event, it is bad practice to remove malloc. Always reserve enough memory.
No, It does not crashes in mine(I uses gcc and Eclipse BTW). But, I won't do that as I was just testing what happens.
Thanks snailface.

Also, I have a doubt in '*' symbol.

Code: Select all

int *a;
Here, it just defines a as a pointer?

Code: Select all

*a = b;
 printf("%d\n", *a);
Here, it points to the contents stored to address pointed by the pointer?

I liked the various tricks shown.
I think, if understood in proper sense, Pointers is the most interesting topic. Thanks m0skit0, I'm working on exercise.

EDIT: Cannot I increment an array pointer? I tried, but I get errors.Eg,

Code: Select all

char a[10];            //Array
char *b = a;                    //Decayed into pointer
a++;
// Big thanks to people who share information !!!

User avatar
m0skit0
Guru
Posts: 3817
Joined: Mon Sep 27, 2010 6:01 pm

Re: [Tutorial] Introduction to programming using C (VII)

Post by m0skit0 » Sat Jun 09, 2012 9:58 pm

Wdingdong wrote:No, It does not crashes in mine(I uses gcc and Eclipse BTW). But, I won't do that as I was just testing what happens.
Thanks snailface.
Probably doesn't crash now. If you don't assign it you're writing that value to a random address, and the OS doesn't know you're doing this. It could claim this memory later and let someone else (or your own program) overwrite your value. Or it could have a non-valid address pointer, and thus raising a segment violation (as happened to snailface).
Wdingdong wrote:Here, it just defines a as a pointer?
Wdingdong wrote:Here, it points to the contents stored to address pointed by the pointer?
Yes and yes.
Wdingdong wrote:EDIT: Cannot I increment an array pointer? I tried, but I get errors.Eg,
To increment it you must use b, that's why you decay it into a pointer ;) Anyway why would you add to an array if you can just use indexes (e.g. a[3] - which is the same as b + 3)? An array is more powerful in that sense.
Wdingdong wrote:And do malloc() function reserve the succeeding memory to the memory pointed by pointer?
Nope. Your pointer variable is assigned a new value pointing to the reserved memory. Before calling malloc() it had random (undefined) value since you didn't assing it one. It's the same as doing:

Code: Select all

int a;
printf("%d", a); // Undefined value
I wanna lots of mov al,0xb
Image
"just not into this RA stuffz"

Wdingdong
Posts: 92
Joined: Tue Aug 02, 2011 5:34 pm

Re: [Tutorial] Introduction to programming using C (VII)

Post by Wdingdong » Sun Jun 10, 2012 3:09 pm

m0skit0 wrote:To increment it you must use b, that's why you decay it into a pointer Anyway why would you add to an array if you can just use indexes (e.g. a[3] - which is the same as b + 3)? An array is more powerful in that sense.
Oh, I thought if I declare an array eg. int a[20], a[n] would be a variable storing data and not a pointer. Also, if I use it in printf function like this,

Code: Select all

printf("%d, %x", a[n], a[n]);
It displays the value stored in it and not the pointing address.
// Big thanks to people who share information !!!

waratte
Posts: 1320
Joined: Wed Oct 20, 2010 12:03 am

Re: [Tutorial] Introduction to programming using C (VII)

Post by waratte » Sun Jun 10, 2012 4:28 pm

By using it as "a[n]", you are trying to get the value of that element in the array. To get the address, you would use prepend it with a '&' like so:

Code: Select all

printf("%d, %x", &a[n], &a[n]);
'&' can be read as the "address-of", to make things simpler.

User avatar
m0skit0
Guru
Posts: 3817
Joined: Mon Sep 27, 2010 6:01 pm

Re: [Tutorial] Introduction to programming using C (VII)

Post by m0skit0 » Sun Jun 10, 2012 8:23 pm

Wdingdong wrote:I thought if I declare an array eg. int a[20], a[n] would be a variable storing data and not a pointer
Well, same as int* a = malloc(20*sizeof(int)), *(a+n) would be a variable storing data ;)
I wanna lots of mov al,0xb
Image
"just not into this RA stuffz"

Wdingdong
Posts: 92
Joined: Tue Aug 02, 2011 5:34 pm

Re: [Tutorial] Introduction to programming using C (VII)

Post by Wdingdong » Mon Jun 11, 2012 3:14 pm

m0skit0 wrote:Using only pointers: declare an array of signed integers and assing it a size of 50 integers.
Same as the last exercise but also assign positions 5, 6, and 8, and then print them.
Using only pointers: given a random string, print from the 5th character onwards.
Given 2 strings of length 5, encrypt the first one using the second one using an XOR operation.

EDIT: I removed some exercises and put new ones since we haven't seen functions yet
EDIT2: changed the exercises since we haven't seen flow control yet
:o I just saw it now. The last two questions of the previous exercise were taking me forever to think. Though, I tried to solve the first three:

Code: Select all

#include <stdio.h>
#include <string.h>

void exercise1()	//print character string without using %s
{
	char *s = "Hey there!";
	int i;
	for(i = 0; i < 10; i++)
	{
		printf("%c",s[i]);	//Decaying pointer into array
	}
	printf("\n");

}

void exercise2()	//Copy one array into another by decaying them into pointers
{
	int a[5] = {1,2,3,4,5};
	int b[5];
	int i;
	for(i = 0; i<5; i++)
	{
		b[i] = a[i];
		printf("%d",b[i]);
	}
	printf("\n");

}

void exercise3()	//Same as above but without using any loops (no for or while keywords allowed)
{
	int a[5] = {1,2,3,4,5};
	int b[5];
	b[0] = a[0];
	printf("%d %d %d %d %d",b[0],b[1],b[2],b[3],b[4]);

}//CMIIW:P


int main()
{
	exercise1();
	exercise2();
	exercise3();
	return 0;
}

Working on the new exercises :geek:
// Big thanks to people who share information !!!

User avatar
m0skit0
Guru
Posts: 3817
Joined: Mon Sep 27, 2010 6:01 pm

Re: [Tutorial] Introduction to programming using C (VII)

Post by m0skit0 » Mon Jun 11, 2012 3:59 pm

Well I see you already know functions and flow control, that's nice ;) Although I will recover this exercises soon enough :)
I wanna lots of mov al,0xb
Image
"just not into this RA stuffz"

Post Reply

Return to “Programming and Security”