SE250:lab-2:llay008

From Marks Wiki
Jump to navigation Jump to search

This lab was straightforward. The main problem was that it was very time consuming.


Task One

Declaring pointers of different types...

int *ip;
long *lp;
double *dp;

... and printing their size found that they all had a size of 4 byte, independent of what they pointed to. 4 bytes is the same size as an int, long and float. Running the program on the Linux server produced the same results.

Task Two

In this excercise I found the address of two local variables, x and y and how far apart they are.

int x;
int y;

printf("&x = %p, &y = %p, diff = %ld\n", &x, &y, (long)(&x - &y));

Output: &x = 0x22cc90, &y = 0x22cc8c, diff = 1


printf("&x = %p, &y = %p, diff = %ld\n", &x, &y, (long)(&x) - (long)(&y));
 
Output: &x = 0x22cc90, &y = 0x22cc8c, diff = 4

Casting the variables separately changes the perceived space between them, the addresses not changing from the first time the printf statement is executed to the next. Using Linux produced the same differences between &x and &y, however the addresses were stored in completely different parts of memory.

Task Three

In this task, an array of 4 chars is declared between x and y.

int x;
char arr[4];
int y;

Using the sizeof command gives the array a size of 4 bytes. This is also true in Linux.


printf("&arr = %p, arr + 4 = %p, &arr[4] = %p\n", &arr, arr + 4, &arr[4]);
Output: &arr = 0x22cc94, arr + 4 = 0x22cc98, &arr[4] = 0x22cc98

In Linux

Output: &arr = 0xffa90738 arr + 4 = 0xffa9073c, &arr[4] = 0xffa9073c
When char arr[0]
printf("&x = %p, &y = %p, diff = %ld\n", &x, &y, (long)(&x) - (long)(&y));
Output: &x = 0x22cc98, &y = 0x22cc90, diff = 20
char arr[1] gives
&x = 0x22cc98, &y = 0x22cc90, diff = 8
char arr[4] gives
&x = 0x22cc98, &y = 0x22cc90, diff = 8
char arr[5] gives
&x = 0x22cc90, &y = 0x22cc7c, diff = 20
char arr[8] gives
&x = 0x22cc98, &y = 0x22cc8c, diff = 12
char arr[10] gives
&x = 0x22cc90, &y = 0x22cc7c, diff = 20

When the program is run on Linux, the difference is always 4. The size of the array does not give an indication of the space in memory. The fact that the 8-byte array took less space than the 5-byte array suggests that it is to do with how the data is organised within the program.

int x = 0;
char arr[4];
int y = 0;
arr[4] = 10;

On emacs this gives 'x' a value of 10 and on Linux x = 167772160. 'y' is 0. The reason for this is that the array is accessing a space in memory outside the bounds of the array. On the PC, the address it accessed was where the address of x. On Linux, this was not the case.

Task Four

int x and int y are declared as global variables.

When the following code is compiled (from Task 2):

printf("&x = %p, &y = %p, diff = %ld\n", &x, &y, (long)(&x - &y));
printf("&x = %p, &y = %p, diff = %ld\n", &x, &y, (long)(&x) - (long)(&y));

the output is

&x = 0x403030, &y = 0x403020, diff = 4
&x = 0x403030, &y = 0x403020, diff = 16
&x = 0x403040, &y = 0x403020, diff = 8

On Linux, in the first case, there is difference of -1 and, in the second, a difference of -4.

The values have changed from when they were local variables and the difference is also much larger.

In an interesting note, when I ran the program with char arr[4], below (as opposed to in between) int x and y the output is:

&x = 0x403040, &y = 0x403020, diff = 32

On Linux, there is difference of -2 and -8.

Setting x and y to 0 I noticed that there was a change

&x = 0x403010, &y = 0x403014, diff = -4

Printing the values of x and y gives

 x = 0, y = 0

On Linux

 x = 0, y = 0

The array char arr[4] is added between x and y again. The size of the array is still 4, both on emacs and Linux.

Printing the address of arr gives:

&arr = 0x403030, arr + 4 = 0x403034, &arr[4] = 0x403034

On Linux

&arr = 0x10010be0, arr + 4 = 0x10010be4, &arr[4] = 0x10010be4

This is nowhere near its previous location as it is now stored in a different part of memory.

When char arr[0]

printf("&x = %p, &y = %p, diff = %ld\n", &x, &y, (long)(&x) - (long)(&y));

gives

&x = 0x403040, &y = 0x403020, diff = 32

Changing the size of the array does not change this.

On Linux

 array size  &x - &y
    0          -4 
    1          -8
    2          -8
    3          -8
    4          -8
    5          -12
    6          -12
    7          -12
    8          -12
    9          -4
    10         -4

Setting x and y to 0 and printing the values gives

x = 0, y = 0

On Linux

x = 0, y = 0

On an interesting note, I noticed that though changing the size of the array did not change &x - &y, this did.

&x = 0x403010, &y = 0x403014, diff = -4

Task Five

 int  *p1, *p2;
 {int q; p1 = &q;}
 {int r; p2 = &r;}
 printf("p1 = %d, p2 = %d\n", p1, p2);

What are the values of p1 and p2?

This is the output:

p1 = 2280604, p2 = 2280600

On Linux

p1 = -5249196, p2 = -5249196


Task Six

These are the functions:

    char *local_str(){
	 char s[8] = "0123456";
	 return s;
    }

    char *local_str2(){
	char s[8] = "abcdefg";
	return s;
    }

   char *static_str(){
	static char s[8] = "tuvwxyz";
	return s;
   }

   char *malloc_str(){
       char *s = malloc(8);
       strcpy(s, "hijklmn");
       return s;
   } 

I had some problem with this task as it would not compile. Due to time constraints I decided to move on to the next task and tackle it later.

Task Seven

This task was straightforward. I declared the structure with a char, short, int, long, float and double, (in that order) and found the offset.

These are the results:

&my_struct = 0x22cc80

The structure was declared inside the main function.

offsets:
my_char: 0
my_short: -2
my_int: -4
my_long: -8
my_float: -12
my_double: -16 

On Linux the same results are produced. The structure is in a different part of memory which is consistant of my results so far.

Replacing the struct with a union produces some interesting results:

&my_union = 0x611021a0
offsets:
my_char: 0
my_short: 0
my_int: 0
my_long: 0
my_float: 0
my_double: 0

The union is treated completely differently to the struct. We have not covered structs so I don't know how they work and in what ways they are different from a struct. This information may help explain why the offset is zero.

On Linux the address is

&my_union = 0xffc7f748

The offset is the same (0).

Task Nine

Typing

   char *sp1, *sp2, *sp3;
   sp1 = malloc(10);
   sp2 = malloc(10);
   free(sp1);
   sp3 = malloc(10);
   printf("sp1 = %p\nsp2 = %p\nsp3 = %p\n", sp1, sp2, sp3);

gives this output

sp1 = 0x1041f28
sp2 = 0x1041f38
sp3 = 0x1041f28

By looking at the address it is easy to see that the pointers are stored in a different part of memory to the variables, whose addresses we have looked at so far in this lab. This was expected because we asigned them to the malloc part of memory. We can also see that the address for sp1 is the same as the address for sp3. This is because sp1 was freed by the free statement and the sp3, which was assigned after, was given its space in memory.