Presentation is loading. Please wait.

Presentation is loading. Please wait.

Memory, Arrays & Pointers

Similar presentations


Presentation on theme: "Memory, Arrays & Pointers"— Presentation transcript:

1 Memory, Arrays & Pointers

2 Memory int main() {    char c;    int i,j;    double x;             c i j x

3 Arrays Defines a block of consecutive cells
int main() {    int i;    int a[3];       i a[0] a[1] a[2]

4 Arrays - the [ ] operator
int arr[5] = { 1, 5, 2, 1 ,3 }; /*arr begins at address 40*/ Address Computation Examples: arr[0]   40+0*sizeof(int) = 40 arr[3]   40+3*sizeof(int) = 52 arr[i]   40+i*sizeof(int) = 40 + 4*i arr[-1]  40+(-1)*sizeof (int) = 36  // can be the code // segment or other variables 1 5 2 3 40 44 48 52 56 60

5 Arrays C does not provide any run time checks
int a[4]; a[-1] = 0; a[4] = 0; This will compile and run (no errors?!) …but can lead to unpredictable results. It is the programmer’s responsibility to check whether the index is out of bounds… May run, may crash, and may do many other things.

6 Arrays C does not provide array operations: int a[4]; int b[4]; a = b; // illegal if( a == b ) // legal. ==0, address comparison.

7 0[a]= 42;// first element of array is 42
Arrays a[i] is just translated to (*(a+i)), thus this code will compile and run fine int a[4]; 0[a]= 42;// first element of array is 42 1[a]= -1;// second element of array is -1

8 Array Initialization // Works, but IMHO in some cases, bad style
int arr[3] = {3, 4, 5}; // Good (robust to changes) int arr[] = {3, 4, 5}; // Bad style - Init all items to 0 takes O(n) int arr[3] = {0}; // Bad style - The last is 0 int arr[4] = {3, 4, 5};

9 Array Initialization // Does not compile int arr[2] = {3, 4, 5};
// Does not compile - array assignment // only in initialization int arr[3]; arr = {2,5,7}; Compiler should be able to deduce array size on compilation.

10 Array Initialization – multidimensional (more on this later)
// Good, works same as arr[2][3] int arr[][3] = {{2,5,7},{4,6,7}}; // Bad style, but same as above int arr[2][3] = {2,5,7,4,6,7}; // Does not compile int arr[3][2] = {{2,5,7},{4,6,7}}; Compiler should be able to deduce array size on compilation.

11 Pointers Data type for addresses (almost) all you need to know is: & *

12 &x - the pointer to x(x’s address)
Pointers Declaration <type> *p; <type>* p; Both, p points to objects of type <type> Pointer  value *p = x; y = *p; *p refers to the object p points to Value  pointer &x - the pointer to x(x’s address)

13 Pointers - 64 bit! int main() {    int i,j;    int *x; // x points to an integer i = 1;    x = &i;    j = *x;    x = &j;    (*x) = 3;     i j x ? 1 2 3 4 5 7 8 9 10 11 12 13 14 15 16 17 18 6

14 Pointers - 64 bit! int main() {    int i,j;    int *x; // x points to an integer i = 1;    x = &i;    j = *x;    x = &j;    (*x) = 3;     i j x 1 ? 1 2 3 4 5 7 8 9 10 11 12 13 14 15 16 17 18 6

15 Pointers - 64 bit! int main() {    int i,j;    int *x; // x points to an integer i = 1;    x = &i;    j = *x;    x = &j;    (*x) = 3;     Little Endian i j x Endian – from end – Gulliver in Liliput – from what end should the egg be opend? 1 ? 1 2 3 4 5 7 8 9 10 11 12 13 14 15 16 17 18 6

16 Pointers - 64 bit! int main() {    int i,j;    int *x; // x points to an integer i = 1;    x = &i;    j = *x;    x = &j;    (*x) = 3;     i j x 1 ? 1 2 3 4 5 7 8 9 10 11 12 13 14 15 16 17 18 6

17 Pointers - 64 bit! int main() {    int i,j;    int *x; // x points to an integer i = 1;    x = &i;    j = *x;    x = &j;    (*x) = 3;     i j x 1 1 2 3 4 5 7 8 9 10 11 12 13 14 15 16 17 18 6

18 Pointers - 64 bit! int main() {    int i,j;    int *x; // x points to an integer i = 1;    x = &i;    j = *x;    x = &j;    (*x) = 3;     i j x 1 4 1 2 3 4 5 7 8 9 10 11 12 13 14 15 16 17 18 6

19 Pointers - 64 bit! int main() {    int i,j;    int *x; // x points to an integer i = 1;    x = &i;    j = *x;    x = &j;    (*x) = 3;     i j x 1 3 4 1 2 3 4 5 7 8 9 10 11 12 13 14 15 16 17 18 6

20 Example – the swap function
Does nothing Works void swap(int a, int b) {    int temp = a;    a = b;    b = temp; } int main() {    int x, y;    x = 3; y = 7;    swap(x, y);    // now x==3, y==7 void swap(int *pa, int *pb) {    int temp = *pa;    *pa = *pb;    *pb = temp; } int main() {    int x, y;    x = 3; y = 7;    swap(&x, &y);    // x == 7, y == 3

21 Pointers & Arrays int *p; int a[3]; p = &a[0]; // same as p = a *(p+1) = 1; // assignment to a[1]! P a[0] a[1] a[2] 8 1

22 Pointers & Arrays Arrays are can sometimes be treated as address of the first member. int *p; int a[4]; p = a; // same as p = &a[0]; p[1] = 102; // same as *(p+1)=102; *(a+1) = 102; // same as prev. line p++; // p == a+1 == &a[1] a = p; // illegal a++; // illegal

23  Size of the array is known in compile time
Pointers & Arrays But: int *p; int a[4]; sizeof (p) == sizeof (void*) sizeof (a) == 4 * sizeof (int)  Size of the array is known in compile time

24 Pointers & Arrays int main() { int arr[] = {1,3,5,4};
int sum = 0;    size_t i;    for (i=0; i<sizeof(arr)/sizeof(arr[0]); ++i)    { sum += arr[i]; } }

25 size_t

26 size_t an unsigned data type, defined in stddef.h
It can be imported by inclusion of stdlib.h (as this file includes stddef.h) This type is used to represent the size of an object. Library functions that take or return sizes expect them to be of type or have the return type of size_t The most frequently used compiler-based operator sizeof should evaluate to a constant value that is compatible with size_t As an implication, size_t is a type guaranteed to hold any array index.

27 size_t size_t is a type guaranteed to hold any array index.
Use size_t indices and not int. Why? Because it tells the story better Because the C standard uses it (you will get warnings against int) Because int range might be too small for large arrays Danger: You cannot test that a variable of an unsigned type is smaller than 0, because it never happens!

28 size_t Danger: You cannot test that a variable of an unsigned type is smaller than 0, because it never happens! Instead make sure that it doen’t happen For example: use the “arrow operator”: for (size_t i=ARR_SIZE-1; i-- > 0;) { arr[i] = ...;

29 ptrdiff_t ptrdiff_t is the signed integer type of the result of subtracting two pointers More info:

30 Pointers & Arrays

31 Are declaring the same interface.
Pointers & Arrays int foo( int *p ); and int foo( int a[] ); Are declaring the same interface. In both cases, a pointer to int is being passed to the function foo

32 Are declaring the same interface.
Pointers & Arrays int foo( int *p ); and int foo( int a[3] ); Are declaring the same interface. In both cases, a pointer to int is being passed to the function foo

33 Pointers & Arrays int* ≡ arr[] !≡ arr[N]
int sum (int arr[]) {    size_t i; int sum = 0;    for (i=0; i<sizeof(arr)/sizeof(arr[0]); ++i)    { sum += arr[i]; }    return sum; } // error: sizeof (arr) = sizeof (void*) int* ≡ arr[] !≡ arr[N]

34 Pointers & Arrays int* ≡ arr[] !≡ arr[N]
int sum (int arr[42]) {    size_t i; int sum = 0;    for (i=0; i<sizeof(arr)/sizeof(arr[0]); ++i)    { sum += arr[i]; }    return sum; } // error: sizeof (arr) = sizeof (void*) int* ≡ arr[] !≡ arr[N]

35 Array size must be passed as a parameter
Pointers & Arrays int sum (int arr[], size_t n) {    size_t i; int sum = 0;    for (i=0; i<n; ++i) {     sum += arr[i]; // = arr+ i*sizeof(int) } return sum; } Array size must be passed as a parameter

36 Pointer Arithmetic int a[3]; int *p = a; char *q = (char *)a; // Explicit cast // p and q point to the same location p++; // increment p by 1 int (4 bytes) q++; // increment q by 1 char (1 byte) a[0] a[1] a[2] a[3] q P

37 Pointer Arithmetic Preferable
int FindFirstNonZero( int a[], size_t n ) {    int *p= a;    while( (p<a+n) && ((*p) == 0) ) ++p;    return p-a; } Same as int FindFirstNonZero( int a[], size_t n ) {    int i= 0;    while( (i<n) && (a[i] == 0) ) ++i;    return i; } Preferable

38 Be careful: Pointer arithmetic works just with pointers
int a[4]; int *p= a; long i= (long)a; long j= (long)(a+1); // add 1*sizeof(int) to a; long dif= (long)(j-i); // dif= sizeof(int) Be careful: Pointer arithmetic works just with pointers

39 void* p defines a pointer to undetermined type
int j; int* p= &j; void* q= p; // no cast needed p = (int*)q ; // cast is needed

40 void* address jumps in bytes (like char*)
We cannot access to the content of the pointer int j; void *p = &j; int k = *p; // illegal int k = (int)*p ; // still illegal int k = *(int*)p; // legal

41 NULL pointer Special value: points to “nothing” (defined in stdlib.h, usually as 0 of type void*): int *p = NULL; if( p != NULL ) {     }

42 … but will lead to runtime error
NULL pointer int *p = NULL; *p = 1; Will compile… … but will lead to runtime error

43 Pointers to pointers Pointer is a variable type, it also has an address: int main() {    int n = 17;    int *p = &n;    int **p2 = &p;    printf("the address of p2 is %p \n",&p2);    printf("the address of p is %p \n",p2);    printf("the address of n is %p \n",*p2);    printf("the value of n is %d \n",**p2);    return 0; } More on it in coming weeks

44 const

45 C’s “const” C’s “const” is a qualifier that can be applied to the declaration of any variable to specify its value will not be changed.

46 C’s “const” Examples: const double E = ; E= 3.14; // compile error! const int arr[] = {1,2}; arr[0] = 1; // compile error!

47 C’s “const” C’s “const” can be cast away Helps to find errors.
Doesn't protect from evil changes ! const int arr[] = {1,2}; int* arr_ptr = (int*)arr; arr_ptr[0] = 3; // compile ok! // but might give a run-time error

48 Const and Pointer’s Syntax
Const protects his left side, unless there is nothing to his left and only then it protects his right side (examples next slide).

49 Const and Pointer’s Syntax
// Both, cannot change the int pointed by p // using p const int * p = arr; int const * p = arr; // Cannot change the address stored in p int * const p = arr; // and the int pointed by p using p int const * const p = arr;

50 Const and Pointer’s Syntax
// Both, cannot change the int pointed by p // using p const int * p = arr; int const * p = arr; // Cannot change the address stored in p int * const p = arr; // and the int pointed by p using p int const * const p = arr; Very Useful Never saw it being used

51 C’s “const” Do not confuse what the “const” declaration “protects”!
A pointer to a const variable: A const pointer to a variable: int arr[] = {1,2,3}; int const * p = arr; p[1] = 1; // illegal! *(p+1) = 1; // illegal! p = NULL; // legal ptr value `` int arr[] = {1,2,3}; int* const const_p = arr; const_p[1] = 0; // legal! const_p = NULL; // illegal! ptr value ``

52 C’s “const” How about arr itself?
int arr[] = {1,2,3}; int* const const_p = arr; const_p[1] = 0; // legal! const_p = NULL; // illegal! int *p; arr=p; // compile error!

53 Const and User Defined Types
typedef struct Complex {    int _real, _img;    int *_imgP; } Complex; Complex const COMP1 = comp2; // ok, init. using comp2 Complex const COMP3 = {3,2,&someInt}; // ok, copying values COMP1._img = 3; // illegal! COMP3._imgP = &someOtherInt; // illegal! *(COMP3._imgP) = 5; // legal! All the members of a const variable are immutable!

54 Compare to Java’s “final”
All (methods as well as data ) are Class members. “final” makes primitive types constants and references to objects constant. The values inside the referred final objects are not necessarily constant ! final int LIMIT = 10; LIMIT = 11; // illegal! final MyObject obj1 = new MyObject(); MyObject obj2 = null; MyObject obj3 = new MyObject(); obj2 = obj1; // fine, both point now to the same object obj1 = obj3; // illegal! obj1.setSomeValue(5); // legal!

55 “Const” Usage The const declaration can (and should!) be used in the definition of a function’s arguments, to indicate it would not change them: Why use? (This is not a recommendation but a must) clearer code avoids errors part of the interfaces you define! can be used with const objects More of “const” meaning and usage in C++ size_t strlen(const char []);

56 C strings manipulation
#include <string.h> strcmp strcpy strlen e/cstring/

57 C Strings

58 Strings Java: C: Char: is 2 bytes (Unicode)
String: an object which behaves as a primitive type (an immutable object, passed by value) C: char: usually 1 byte. An Integer. string: an array of characters. char* txt1 = "text"; char txt2[] = "text"; char txt3[] = {’t’,’e’,’x’,’t’,’\0’}; Addr. \0 t x e ``

59 C Strings Strings are always terminated by a null character, (a character with integer value 0). There is no way to enforce it automatically when you create your own strings, so: remember it’s there allocate memory for it specify it when you initialize char by char char* text = "string"; // means text[5] = g and text[6] = \0 // 7 chars are allocated!

60 C string literals ("") When working with char*, C string literals ("") are written in the code segment (part) of the memory. Thus, you can't change them!

61 C string literals ("") When working with char*, C string literals ("") are written in the code segment (part) of the memory. Thus, you can't change them! char* msg = "text"; msg[0] = ‘w’; // seg fault! – error caught only in runtime ! Stack Code part of memory msg Addr. \0 t x e `` OS is protecting this area !

62 C string literals ("") with const
So, what we do is: const char* msg = "text"; msg[0] = ‘t’; // compile error! // better! Stack Code part of memory msg Addr. \0 t x e `` OS is protecting this area !

63 Difference between initialzing a pointer and an array with C string literals ("")
char* msg = "text"; // msg is a pointer that points to a memory that is in the code part Stack Code part of memory msg Addr. \0 t x e `` Stack t e x \0 char msg2[] = "text"; // msg2 is an array of chars that are on the stack

64 Difference between initialzing a pointer and an array with C string literals ("")
char* msg = "text"; msg[0]= 'n'; // seg fault - trying to change what is written in the code part of the memory char msg2[] = "text"; msg2[0]= 'n'; // ok - changing what is written in the stack part of the memory

65 C Strings Examples char txt1[] = "text"; char* txt2 = "text";
int i = strlen(txt1); // i = 4, same for strlen(txt2) txt1[0] = ’n’; // now txt1="next“ *txt2 = ’n’; // illegal! “text” is in the code // segment txt2 = txt1; // legal. now txt2 points to the // same string. txt1 = txt2; // illegal! if (! (strcmp(txt2,"next")) //This condition is now true { ...

66 C Strings Manipulation
To manipulate a single character use the functions defined in ctype.h Manipulation of Strings is done by including the string.h header file #include <ctype.h> char c = ‘A’; isalpha(c); isupper(c); islower(c); … // copy a string char* strcpy(char * dest, const char* src); // append a string char* strcat(char * dest, const char* src);

67 C Strings Manipulation (2)
// compare two strings. // when str1 < str2 lexicographically return < 0 // when str1 > str2 lexicographically return > 0 // when identical return 0 int strcmp(const char * str1, const char* str2); // return strings length, not including the \0!! size_t strlen(const char * str); // Other functions: strncpy(),strncat(),strncmp() … NOTE : All C library functions assumes the usages of ‘\0’ and enough storage space. No boundary checks! You are responsible.

68 C Strings Functions An “array” version of strcpy():
void strcpy(char * dest, const char* src) {    size_t i = 0;    while ((dest[i] = src[i])!= '\0')) i++; }

69 C Strings Functions A “pointers” version of strcpy():
void strcpy(char * dest, const char* src) {    while ((*dest = *src)!= '\0'))    {       dest++;       src++;    } }

70 C Strings Functions (2) A shorter version:: Actually the comparison against \0 is redundant: Style note: Unlike K&R book, we do NOT encourage you to write such code. However, you should be able to read and understand it. void strcpy(char * dest,const char* src) {    while ((*dest++ = *src++)!= '\0')); } void strcpy(char * dest,const char* src) {    while (*dest++ = *src++); }


Download ppt "Memory, Arrays & Pointers"

Similar presentations


Ads by Google