23
1 C - Memory C - Memory Simple Types • Arrays • Pointers Pointer to Pointer Multi-dimensional Arrays Dynamic Memory Allocation

1 C - Memory Simple Types Arrays Pointers Pointer to Pointer Multi-dimensional Arrays Dynamic Memory Allocation

Embed Size (px)

Citation preview

1

C - MemoryC - Memory

• Simple Types• Arrays• Pointers• Pointer to Pointer• Multi-dimensional Arrays• Dynamic Memory Allocation

2

Memory and PointersSIMPLE TYPESSIMPLE TYPES

159.234

When we create a variable in a program, we use the name of the variable to access its value.The computer only knows about memory locations (addresses) and contents (values).The compiler translates our instructions into something meaningful to the computer,

int int ii, , jj;;allocates storage for two integers (sizeof(int), 4 bytes) and remembers their addresses

ii may be at address 100 and may be at address 100 and jj at 104. at 104.ii = = jj;;

is translated by the compiler into: copy 4 bytes at location 104104 to location 100100

3

C-Memory

SIMPLE TYPESSIMPLE TYPES

159.234

When we include a numeric or character constant in a program:

i = 6;i = 6;

the compiler places the value '66' into the machine instruction.If we also have

j = 6;j = 6;

there will be two '66' s in our executable file.

4

C-Memory

ARRAYSARRAYS

159.234

When we create an array, the compiler allocates as much memory as requested and remembers the address of the first element.

char s[80];char s[80];

allocates 80 bytes starting at 108*.

*that is, continuing with our previous example*that is, continuing with our previous example

5

C-MemoryArray name

159.234

The name 's' is different from 'i‘

'i' refers to the value stored at address 100's' refers to the address 108We are not allowed to say:

s = 'a';s = 'a';

To access the value stored at s:

s[0] = 'a';s[0] = 'a';or (*s) = 'a';(*s) = 'a';

s is an address. The indirection operator * The indirection operator * accesses the contents stored at the address.

6

C-MemoryARRAYS

159.234

s[i] s[i] is a shorthand way of writing *(s+i)*(s+i)

We can add an integer to an address – the result is an address. (The integer is first multiplied by the size of the element being pointed to)

The result of subtracting two addresses is an integer. The number of elements.

We cannot multiply an address with an integer.

Adding addresses

Subtracting addresses

Multiplying addresses

7

C-MemoryARRAY CONSTANTS

159.234

A string cannot be 'part of an instruction'. Instructions are fixed length – 44 or 88 bytes.

The compiler allocates memory for the string and remembers its location.

strcpy(s,"Napoleon");strcpy(s,"Napoleon");

"Napoleon" is stored in memory at address 1889 bytes are allocated (8 plus a NULL).

The text "Napoleon" is stored in the executable file and is placed at location 188 when the program starts.

8

C-MemoryARRAY CONSTANTS

159.234

If the constant appears twice in the program:

strcpy(s,"Napoleon"); strcpy(t,"Napoleon");

the compiler has the choice of creating two separate memory areas each with the word "Napoleon", or using the same area for both.

To save space it will normally do the latter.

9

C-Memory

Size of ARRAYS

159.234

Do we need to say how big arrays are? - Yes, otherwise the compiler does not know how many bytes to allocate.

What about when we initialise strings?

char s[] = "Napoleon";

We don't need to give the size of the string – but the compiler works it out itself.

See AddressArray.cppSee AddressArray.cpp

10

C-Memory

2-D ARRAYS

159.234

What about 2 dimensional arrays?

The compiler fools us a little – there is no such thing as a 2D array. Only 1D arrays.

char array[20][80];

allocates 1600 bytes of memory. 'array' is the address of the first byte.

array[3][5]

is converted by the compiler to:*(array + 3*80 + 5)

similarly for 3 and 4 dimensional arrays.

See AddressArray.cppSee AddressArray.cpp

11

C-Memory

Specifying the array dimension at run-time

159.234

Can we specify the dimension at run-time? - Not unless we use pointers.

A pointer is a variable that contains an address.

char *p;

Now we have two addresses!

p is a variable, its value is an address. This is the address we normally want.

p is somewhere in memory so it has an address associated with its own position.

The && operator gets the address of a variable.

char *p; char c; p = &c;

p is at location 100c is at location 104the contents of p is 104.

The indirection operator * accesses the contents of an address

12

C-Memory

Using the subscripting operator with pointersUsing the subscripting operator with pointers

159.234

(*p) = ‘N';

pointers and arrays look very similar! We can use the [ ] operator with pointers

p[0] = ‘N';

p points to a single character, so we can only access the 00'th element.

Writing to p[1] causes the program to failfail.

If we allocate memory from the heap, p can point to as many bytes as we want:

Subscript operatorSubscript operator

void *malloc(size_t void *malloc(size_t sizesize););

13

C-Memory

mallocmalloc

159.234

p = (char *)malloc(80*sizeof(char));

allocates 80 bytes. p contains the address of the first character.

malloc can have a variable as an argument, so the size of the 'string' p can be set at runtime.

char *p; int i; printf("How big is the string:"); scanf("%d", &i ); p = (char *)malloc(i*sizeof(char));

void *malloc(size_t void *malloc(size_t sizesize););

14

C-MemoryDeclaring an ARRAY vs. Declaring a Pointer

159.234

char s[80]; char *p; p = (char *)malloc(80*sizeof(char));

p and s behave very much the same.p[12] = 'a'; s[12] = 'b';strcpy(p,"Napoleon"); strcpy(s,"Napoleon");printf("%s",p); printf("%s",s);

There is a difference: char s[80]; char *p; char c; p = &c; this is certainly ok s = &c; this is NOT

ss is not variable. Its value cannot change.

15

C-MemoryARRAYS

159.234

Be very careful when 'initialising' a pointerchar *p = "Napoleon";

If "Napoleon" is a constant, used in many places in the program then

p[0] = 'X';

Will change all “Napoleon"s into "Xapoleon".

16

C-Memory

2D arrays on the heap?

159.234

Several possibilities, but the syntax becomes very difficult.

char (*p)[80];p = (char (*)[80])malloc(10*80*sizeof(char));p[0][0] = 'a';

is correct (and the round brackets are required!)typedef char string[80];string *q;

q = (string *)malloc(10*sizeof(string));

is equivalent and looks better, although the typedef is a bit strange.

char (*p)[80]; //pointer to a char array

char *(p[80]); //array of pointers to char

only the very brave or foolish use these.

17

C-Memory

POINTER TO A POINTER

159.234

A third method is more common and uses a pointer to a pointer. char **p;

We have to do more work to set this up as a 2D array, but we have a lot more flexibility in the size of the array.The number of rows in the array is set first, by making p point to an array of pointers. p = (char **)malloc(rows*sizeof(char *));each pointer is then set to point to an array of characters.

for (i=0; i<row; i++) { p[i] = (char *)malloc(cols*sizeof(char));}

p is a pointer to a pointerp[i] is a stringp[i][j] is a character

18

C-Memory2-D Array doesn’t have to be square

159.234

We can still use the [] operator to access elements of each array.We do not need to allocate the same number of characters to each string – the array does not have to be square.for (i=0;i<row;i++) { p[i] = (char *)malloc((i+1)(i+1)*sizeof(char));}

When we have finished with memory allocated from the heap, we must give it back. char *p; p = (char *)malloc(80*sizeof(char)); … free(p);

In the case of pointers to pointers, we must be careful to free memory in the correct order.

for (i=0;i<row;i++) { free(p[i]); } free(p);

Do not access heap memory after it has been free'd.

19

C-Memory

How does freefree know how much memory to release?

159.234

malloc has to remember how many bytes were allocated. How it does this is not specified, but one common way is to allocate an extra 4 bytes, at the start, that contain the size.

If we write to p[-1] at any time, then our program will explode when we free(p)

Local variables are kept on a 'stackstack'. This is created each time a function is called. The stack is destroyed when a return is executed.

The stack is not set to zero each time it is created (too expensive) – and so local variables contain arbitrary data.

Local variables Local variables need to be need to be initialised.initialised.

20

C-Memory

POINTERS

159.234

A pointer may be on the stack – but what it points to may be on the heap. Failing to free heap memory before exiting a function will leave memory on the heap that no longer has a pointer pointing to it.

This memory can never be recovered – it is called a memory memory leakleak.

Get into the habit of always freeing memory. Even when the program exits.

21

C-Memory

POINTERS

159.234

When a function wants to change the value of an actual parameter, an address must be passed to the function.

For strings the syntax looks ok, because the name is itself an address: strcpy(s,“Napoleon"); …void strcpy(char *p, char *q) {

inside strcpy we access the original using p[i].

To alter an integer the syntax is more clumsy twice(&i); …void twice(int *ip) { (*ip) = (*ip)*2;}

22

C-Memory

POINTERS

159.234

We have to be brave to alter a pointer! char *s; allocate_and_check(&s); …void allocate_and_check(char **p) { (*p) = (char *)malloc(80); if ((*p) == NULL) { …It is a lot easier to use return values.C++ tidies up the problems associated with malloc and free by introducing 2 new keywords, newnew and deletedelete.Reference parameters also are a new feature, to make it easier to alter arguments.

23

C-Memory

POINTERS & MULTIDIMENSIONAL ARRAYS

159.234

int (*x)[20];

int x[10][20];

rather than

x

(x +1)

(x +2)

First array

Second array

Third array

……

*(x +2) *(x +2)+5

*(*(x +2) + 5)

2D INTEGER ARRAY

((x+1x+1) ) automatically takes automatically takes into account the number into account the number of elements in an arrayof elements in an array

See See AddressArray2.cppAddressArray2.cpp