Download Pointers, Arrays and Strings in C Overview and more Exercises Printing in PDF only on Docsity!
CSC 8400: Computer Systems
Pointers, Arrays and Strings in C Overview
- Pointers
- Variables that hold memory addresses
- Using pointers to do “call-by-reference” in C
- Arrays
- List of elements of the same type
- Array name is alias for the address of the first array element
- Array name can be used as a constant pointer
- Strings
- Array of characters ending in ‘\0’
- Special functions for manipulating strings
Insight: Write a swap function void swap(int x, int y) {
} int main(void) { int a = 11, b = 22; swap(a,b); printf(“a=%d, b=%d\n”); } Output should be a=22, b=
- C always passes arguments BY-VALUE − Memory allocated for parameters when function is called − Argument VALUES copied into newly allocated memory − Memory automatically de-allocated when function ends
Function Parameters
void swap(int x, int y) {
} int main(void) { int a = 11, b = 22; swap(a,b); printf(“a=%d, b=%d\n”); }
Pointers and Addresses
- We can declare that a pointer iPtr points to an int by saying int * iPtr;
- Suppose that we have: int i = 5; int j = 7;
- We can make iPtr point to i by assigning to iPtr the memory location where i is stored. Thus iPtr = &i; sets iPtr to point to i. 5 7 100 ... ... (&i) 100 (&j) 180 260 i j iPtr 5 iPtr i Declaring Pointers
- When declaring several pointer variables in one statement - the asterisk does not distribute throughout the statement: int *p, q; int * p; int q; equivalent to int * p, * q; int^ *^ p; int * q; equivalent to
Initializing Pointers
- We can also initialize iPtr at the point of declaration: int i; int * iPtr = &i;
- Here is a common error: int i; int * iPtr = i; // ERROR: i is not an address ??? iPtr i **Dereference ***
- The value of the data being pointed at is obtained by using the operator *
- If p is a pointer value, then
*p
refers to the variable pointed to by p. Since reference is another name for address, the operator * is called dereference operator.
swap Function Revisited void swap(int *x, int *y) {
} int main(void) { int a = 11, b = 22; swap(____, ____); printf(“a=%d, b=%d\n”); } Output should be: a=22, b= Note the Difference … ptr 5 i ptr 7 j Assume: ptr 5 i ptr 7 j After ptr1 = ptr2; ptr 7 i ptr 7 j After *ptr1 = *ptr2;
Uninitialized Pointers
- Suppose that we have the following declarations: int i; int * iPtr; *iPtr = 100;
- What is the value of iPtr? Undefined. What could happen? - iPtr could hold an address that does not make sense at all, causing your program to crash if dereferenced. - iPtr could point to an address which is accessible. Then the assignment *iPtr = 100; would accidentally change some other data, which could result in a crash at a later point. This is a tough error to detect since the cause and symptom may be widely separated in time. ??? iPtr i The null Pointer
- The value of a pointer can be:
- some garbage (pointer unassigned)
- the address of some variable (eg., int * p = &i; )
- the constant 0 (the null pointer , points to absolutely nothing) somePointer = 0; This statement does not cause somePointer to point to memory location zero; it guarantees that somePointer does not point to anything.
- The null pointer is a special pointer value that a program can test for: if (somePointer == 0) ...
Array Indices
- Logically, valid indices for an array range from 0 to MAX-1, where MAX is the dimension of the array
- Memory int a[6]; stands for a[0], a[1], a[2], a[3], a[4] and a[5] Logically, there is no a[6]! a[0] a[1] a[2] a[3] a[4] a[5] Arrays: C vs. Java Java C Arrays int [] a = new int [10]; int a[10]; int a = (int)malloc(10sizeof(int)); float [][] b = new float [5][20]; float b[5][20]; float b = (float)malloc(520sizeof(float); Array bound checking // run-time check / no run-time check */
C Does Not Do Bounds Checking! int a[5]; a[0] = 217; a[3] = 226;
a 320 a[-1] = 55; a[7] = 320; Unpleasant if you happened to have another variable before the array variable a, or after it! Address 400 404 408 412 416 Label a[0] a[1] a[2] a[3] a[4] Activity
- Write a small program to test what happens when you use invalid array indices.
Stack vs. Data Local variables and function parameters Global variables TEXT^ Instructions (code) RODATA DATA HEAP STACK
- At run-time, memory devoted to program is divided into sections : Read-only data (string constants)
FFFF
Local Variables
- Are allocated on the stack
- The stack grows from high memory addresses towards low memory addresses. b[0] b[1] a[1] a[0] b[2] b[3] Stack grows
Address Label
Clobbering Example 2 /* This program accesses an invalid array cell. ** Why does it work? Draw the memory map. / int a[2]; / 2 cells, each cell 4 bytes (32 bits) / int b[4]; / 4 cells, each cell 4 bytes (32 bits) / int c[4]; / 4 cells, each cell 4 bytes (32 bits) / char d[5]; / 5 cells, each cell 1 bytes (8 bits) / main() { a[0]=5; b[1]=4; c[0]=9; d[4]='a'; b[4]=10; printf("%d\n",b[4]); printf("%d\n",c[0]); / Why did c[0] change? */ } Arrays vs. Pointers
Arrays are NOT Pointers
- Declaring an array sets aside space for its elements char a[5];
- Declaring a pointer variable sets aside only space to hold the variable char * p;
- You can change a pointer variable, but not the address of an array char b[6]; p = b; // OK b = p; // ERROR! a a[0] a[1] a[2] a[3] a[4] p b b[0] b[1] b[2] b[3] b[4] p b[5] Indexing Pointers int a[5]; int *p, *q;
a q p[1]= 44; p 44 p = a; q = p + 2; q[-1] = 43;
q[2] = 46;
Pointer Arithmetic int a[5];
a p Subscript: a[i] “means” *(a+i) int *p; p = a + 2;
Note: arithmetic scales by data size (e.g., int of 4 bytes)
4 bytes
Quaint usage of pointer arithmetic Add up the elements of an array: int a[100]; int sum, *p; ... for (p=a; p<a+100; p++) sum += *p; More straightforwardly: int a[100]; int sum, i; ... for (i=0; i<100; i++) sum += a[i];
Activity: Reverse Array
- Reverse the values in an array
- Inputs: integer array a, and number of elements n
- Output: values of a stored in reverse order
- Algorithm
- Swap the first and last elements in the array
- Swap the second and second-to-last elements
- … 77 31 94 5 186 Implement using pointers (no array indices) C Strings
C vs. Java Strings Java C Strings String s1 = "Hello"; String s2 = new String("hello"); char s1[] = "Hello"; char s2[6]; strcpy(s2, "hello"); String concatenation s1 = s1 + s s1 += s #include <string.h> strcat(s1, s2); Strings
- Unlike Java, there is no String data type in C
- A string is just an array of characters (pointer to character), terminated by a ‘\0’ char (a null, ASCII code 0). char mystring[6] = {’H’,’e’,’l’,’l’,’o’,’\0’}; char mystring[6] = “Hello”; char mystring[] = “Hello”; Equivalent H e l l o
mystring