C Arrays and Pointers
C Arrays List of contiguous values in memory Array Declaration: Type Name Count int vec[5]; Type: Type of each element Name: Identifier for the entire array Count: Number of elements in the list Label Address Value 0xFFFF FFFC 0xDEAD BEEF 0xFFFF FFF8 0xDEAD BEEF 0xFFFF FFF4 0xDEAD BEEF 0xFFFF FFF0 0xDEAD BEEF vec[4] 0x0000 0C14 0x1111 1111 vec[3] 0x0000 0C10 0x1111 1111 vec[2] 0x0000 0C0C 0x1111 1111 vec[1] 0x0000 0C08 0x1111 1111 vec[0] 0x0000 0C04 0x1111 1111. 0x0000 000C 0x0000 000C 0x0000 0008 0x0000 0009 0x0000 0004 0x0000 0006 0x0000 0000 0x0000 0003
Inverted Arrays Standard representation of arrays in CS is top to bottom. int vec[5]={365,366,367,368,369}; vec vec[0]=365 vec[1]=366 vec[2]=367 vec[3]=368 vec[4]=369 Label Address Value 0xFFFF FFFC 0xDEAD BEEF 0xFFFF FFF8 0xDEAD BEEF 0xFFFF FFF4 0xDEAD BEEF 0xFFFF FFF0 0xDEAD BEEF vec[4] 0x0000 0C14 0x0000 011C vec[3] 0x0000 0C10 0x0000 011B vec[2] 0x0000 0C0C 0x0000 011A vec[1] 0x0000 0C08 0x0000 0119 vec[0] 0x0000 0C04 0x0000 0118. 0x0000 000C 0x0000 000C 0x0000 0008 0x0000 0009 0x0000 0004 0x0000 0006 0x0000 0000 0x0000 0003
Array Element Access Square Bracket Operator Argument: Index from 0 to (Count-1) Example: for(i=0;i<5;i++) { vec[i]=280+i; } Can be used to read or write an array element Label Address Value 0xFFFF FFFC 0xDEAD BEEF 0xFFFF FFF8 0xDEAD BEEF 0xFFFF FFF4 0xDEAD BEEF 0xFFFF FFF0 0xDEAD BEEF vec[4] 0x0000 0C14 0x0000 011C vec[3] 0x0000 0C10 0x0000 011B vec[2] 0x0000 0C0C 0x0000 011A vec[1] 0x0000 0C08 0x0000 0119 vec[0] 0x0000 0C04 0x0000 0118. 0x0000 000C 0x0000 000C 0x0000 0008 0x0000 0009 0x0000 0004 0x0000 0006 0x0000 0000 0x0000 0003
Array Name In C, by convention, the array name is the address of the first element of the array vec=&(vec[0]) Therefore, the following holds: &(vec[i]) == (char *)vec + sizeof(vec[0]) * i
A Pointer points to one or more elements of a specific type (Actually, zero or more, but who s counting) 6
Pointer Arithmetic You can do math (+-*/%) with pointers, but A unit in pointer arithmetic is the size of the data type pointed to by the pointer int *x; int vec[5]; for (x=vec; x<&vec[5]; x++) (*x)=3; Label Address Value 0xFFFF FFFC 0xDEAD BEEF 0xFFFF FFF8 0xDEAD BEEF x 0x0000 0D10 0x0000 0C18 vec[4] 0x0000 0C14 0x0000 0003 vec[3] 0x0000 0C10 0x0000 0003 vec[2] 0x0000 0C0C 0x0000 0003 vec[1] 0x0000 0C08 0x0000 0003 vec[0] 0x0000 0C04 0x0000 0003. 0x0000 000C 0x0000 000C 0x0000 0008 0x0000 0009 0x0000 0004 0x0000 0006 0x0000 0000 0x0000 0003
Integer Vector in Memory int v[4]={11,12,13,14}; Vector v[0] v[1] v[2] v[3] Value x0000000b x0000000c x0000000d x0000000e Address x00c00014 x00c00018 x00c0001c x00c00020 int *vp=v; // vp=x00c00014 printf( vp-> %d %d %d \n,*vp,*(vp+1),*(vp+2)); vp-> 11 12 13 8
Abstraction An array is an indexable list of data items char buffer[200]; // buffer is a list of 200 characters buffer[0]= H ; // set the first item in buffer to H int length[3]; // length is a list of 3 integers length[0]=12; length[1]=12; length[2]=12;
Leaky Abstraction Under the covers, C treats an array as a pointer to zero or more data items Therefore, you can program as if an array is a pointer or a pointer is an array! int array[10]; array == &(array[0]) or (*array)==array[0] array[i] ==*(array+i);
Pointer / Array Ambiguity In C, we can treat pointers like arrays, and arrays like pointers Using array notation int strlen(char str[]) { } int i=0; while(str[i]!=0) { } i++; return i; Using pointer notation int strlen(char *str) { int i=0; while((*str)!=0) { i++; str++; } return i; }
Multi-Dimensional Arrays int xyz[2][3]; // 2 rows/3 cols xyz xyz[0][0] xyz[0][1] xyz[0][2] xyz[1][0] xyz[1][1] xyz[1][2] Row Major order like odometer, right digit changes fastest Label Address Value 0xFFFF FFFC 0xDEAD BEEF 0xFFFF FFF8 0xDEAD BEEF 0xFFFF FFF4 0xDEAD BEEF xyz[1][2] 0x0000 0C18 0x0000 011D xyz[1][1] 0x0000 0C14 0x0000 011C xyz[1][0] 0x0000 0C10 0x0000 011B xyz[0][2] 0x0000 0C0C 0x0000 011A xyz[0][1] 0x0000 0C08 0x0000 0119 xyz[0][0] 0x0000 0C04 0x0000 0118. 0x0000 000C 0x0000 000C 0x0000 0008 0x0000 0009 0x0000 0004 0x0000 0006 0x0000 0000 0x0000 0003
Matrix Pointer Arithmetic int mat[3][4]; int r; int c &(mat[r][c]) == mat + (r*4)+c Or elementsize=sizeof(int); rowsize=4*elementsize; &(mat[r][c]) == (char *)mat + (r*rowsize) + c * elementsize
Arrays of Pointers int *xyz[2]; // Array of two pointers xyz xyz[0] xyz[1] (*xyz[0])[0] (*xyz[0])[1] (*xyz[0])[2] (*xyz[1])[0] (*xyz[1])[1] Label Address Value xyz[1] 0x0000 CA0C 0x0000 C708 xyz[0] 0x0000 CA08 0x0000 C000 xyz[1][1] 0x0000 C70C 0x0000 0004 xyz[1][0] 0x0000 C708 0x0000 0003 xyz[0][2] 0x0000 C008 0x0000 0002 xyz[0][1] 0x0000 C004 0x0000 0001 xyz[0][0] 0x0000 C000 0x0000 0000
Difference between Arrays and Pointers Array Fixed, pre-defined length Space reserved by compiler All 2D rows equal length Pointers to List No pre-defined length No space reserved 2D rows may be varying length
Dealing with Undefined lengths Implicit Explicit Guard int triperim(int sides[]) { return side[0] + side[1] + side[2]; } Agreement: sides is an array with three elements Probably better to use sides[3] in argument definition int perim(int n, int sides[]) { int j; int sum=0; for(j=0;j<n;j++) sum+=sides[j]; return sum; } Agreement: Caller specifies how many elements are in sides with an extra argument int perim(int sides[]) { int j; int sum=0; for(j=0;sides[j]>0;j++) sum+=sides[j]; return sum; } Agreement: Caller puts a guard value after last significant element of sides Guard value is an invalid value
Character Strings In C, there is no string type Text consists of an array of characters char nextline[80]; char bgcolor[]= magenta ; // bgcolor has 8 values Guard is a null terminator = 0x00 When we are dealing with strings, we almost always use pointer notation Length is not important BECAUSE we have a null terminator char * string; // is very similar to char string[100]
Pointers and Memory When you declare an int or array of ints, the compiler reserves memory for that int or array of ints When you declare a pointer to an int or array of ints, the compiler reserves memory for the POINTER, but does NOT reserve memory for the actual data being pointed to! Typical C bug: char* name; // similar to char name[100] but strcpy(name, Tom Bartenstein ); Segmentation Violation
Pointers and Constants Pointer notation does NOT reserve space! char * string; string[0]=0x00; // may result in SEGMENTATION VIOLATION! Space IS reserved for a constant! char * string= This is a test ; string[0]= X ; printf( String is: %s\n,string); // prints String is: Xhis is a test
Initialized Pointers In some cases, it looks like pointers ARE reserving memory char * name = Tom Bartenstein ; In this case, the compiler is creating a LITERAL value in memory Possibly read only memory Possibly shared with other instances of Tom Bartenstein literal in this code The name variable points to the LITERAL value May get segmentation violation if written to May get bizarre future errors if compiler re-used this literal
Arrays as Arguments We ve already been doing this with string functions! Here as some examples char name[100]; strcpy(name, Tom Bartenstein ); int n=strlen(name); if (0==strncmp(name, Tom,3)) printf( My name is %s\n,name); scanf( %s,name);
Array Return Values C does not support returning an array C will allow returning a POINTER to an array The array name with no brackets is a pointer to the array The array must be static cannot be an automatic variable! int * coldest3(int n,int temps[ ]) { static int cold3[3] = { -1, -1, -1} ; return cold3; }
Using a returned pointer You can use a pointer to an array as if it were an array You must know the size of the array! int * c3 = coldest3(10,temps); printf( The three coldest temps are %d, %d, and %d\n, c3[0],c3[1],c3[2]); See also: examples/xmp_hw3_ptr and examples/xmp_hw3_ptr2
Resources The C Programming Language, (K&R) Chapter 5 Computer Systems, Section 3.8 Wikepedia Pointers : https://en.wikipedia.org/wiki/pointer_(computer_programming) C Pointer Tutorial : http://www.tutorialspoint.com/cprogramming/c_pointers.htm C FAQ Arrays and Pointers Section: http://cfaq.com/aryptr/index.html 25