12.07.2015 Views

C Pointers (1/2)

C Pointers (1/2)

C Pointers (1/2)

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Chapter 7 - <strong>Pointers</strong>Outline7.1 Introduction7.2 Pointer Variable Definitions and Initialization7.3 Pointer Operators7.4 Calling Functions by Reference7.5 Using the const Qualifier with <strong>Pointers</strong>7.6 Bubble Sort Using Call by Reference7.7 Pointer Expressions and Pointer Arithmetic7.8 The Relationship between <strong>Pointers</strong> and Arrays7.9 Arrays of <strong>Pointers</strong>7.10 Case Study: A Card Shuffling and Dealing Simulation7.11 <strong>Pointers</strong> to Functions© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.Objectives•In this chapter, you will learn:–To be able to use pointers.–To be able to use pointers to pass arguments tofunctions using call by reference.–To understand the close relationships among pointers,arrays and strings.–To understand the use of pointers to functions.–To be able to define and use arrays of strings.© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.1


7.1 Introduction•<strong>Pointers</strong> ( 指 標 )–Powerful, but difficult to master–Simulate call-by-reference–Close relationship with arrays and strings© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.7.2 Pointer Variable Definitions andInitialization‧ 位 址 (address) 也 是 一 種 資 料 型 態‧ 指 標 變 數 ( 或 簡 稱 指 標 ): 資 料 型 態 為 位 址 的 變 數– 一 般 變 數 儲 存 某 個 特 定 資 料 ( 直 接 透 過 此 變 數 去 access此 資 料 稱 為 direct reference)– 指 標 變 數 儲 存 另 一 變 數 的 位 址 address ( 間 接 透 過 指 標 去access 該 變 數 儲 存 的 資 料 稱 為 indirect reference)–Indirection –referencing a pointer valuecountPtrcount7count7© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.2


指 標 變 數 的 宣 告• 若 你 想 用 某 指 標 變 數 p 儲 存 變 數 a 的 位 址 , 而 變數 a 的 型 態 是 int, 則 你 必 須 宣 告 p 為 一 個 指 向 int變 數 的 指 標 變 數int *p;p 是 int * (p 是 一 個 指 向 int 的 指 標 )*p 是 int(p 指 標 指 向 的 位 置 儲 存 的 資 料 型 態 是 int)這 是 因 為 如 果 要 透 過 p 來 間 接 存 取 變 數 a 的 內容 , 除 了 要 知 道 變 數 a 的 位 址 外 , 還 要 知 道 該位 址 儲 存 資 料 的 型 態© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.多 個 指 標 變 數 的 宣 告 及 初 值 化•Multiple pointers require using a * before eachvariable definitionint *myPtr1, *myPtr2;•Can define pointers to any data type•Initialize pointers to 0, NULL, or an address–0 or NULL –points to nothing (NULL preferred)© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.3


7.3 Pointer Operators•& (address operator)–Returns address of operandint y = 5;int *yPtr;yPtr = &y; /* yPtr gets address of y */yPtr “points to” yyPtry5yptr500000 600000y600000 5Address of yis value ofyptr© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.& 運 算•& 運 算 子 可 取 得 運 算 元 ( 某 個 變 數 ) 的 儲 存 位 址• 當 我 們 要 更 改 (write) 變 數 的 儲 存 內 容 時 , 一 定要 讓 編 譯 程 式 得 知 變 數 的 儲 存 位 址 。• 因 此 在 呼 叫 某 些 函 數 時 , 我 們 會 使 用 & 運 算 子取 得 並 傳 入 變 數 的 位 址 , 而 非 變 數 名 稱int a;…scanf(“%d”, &a);傳 入 變 數 a 的 儲 存 位址 以 便 scanf 函 數 將使 用 者 輸 入 的 內 容儲 存 到 a 的 位 置© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.4


7.3 Pointer Operators•* (indirection/dereferencing operator)11F4506E11F4506F11F4507011F45071240FFF5Bp = &a*p 表 示 將 指 標 變 數 p 的值 當 位 址 所 取 出 來 的 內容 ( 某 個 值 )…240FFF5B240FFF5C240FFF5D240FFF5Ea = *p若 p = &a, 則 *p 與 a 均為 儲 存 在 該 位 址 資 料 的別 名 (alias)© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.1 /* Fig. 7.4: fig07_04.c2 Using the & and * operators */3 #include 45 int main()6 {7 int a; /* a is an integer */8 int *aPtr; /* aPtr is a pointer to an integer */910 a = 7;11 aPtr = &a; /* aPtr set to address of a */1213 printf( "The address of a is %p"14 "\nThe value of aPtr is %p", &a, aPtr );1516 printf( "\n\nThe value of a is %d"17 "\nThe value of *aPtr is %d", a, *aPtr );18The address of a is thevalue of aPtr.19 printf( "\n\nShowing that * and & are complements of "20 "each other\n&*aPtr = %p"21 "\n*&aPtr = %p\n", &*aPtr, *&aPtr );2223 return 0; /* indicates successful termination */2425 } /* end main */© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.fig07_04.cThe * operator returns an aliasto what its operand points to.aPtr points to a, so *aPtrreturns a.Notice how * and& are inverses5


Program OutputThe address of a is 0012FF7CThe value of aPtr is 0012FF7CThe value of a is 7The value of *aPtr is 7Showing that * and & are complementsof each other.&*aPtr = 0012FF7C*&aPtr = 0012FF7C© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.練 習 一• 宣 告 一 整 數 變 數 a 與 指 向 整 數 資 料 的 指 標 p• 設 定 p 的 內 容 為 a 的 位 址• 使 用 scanf 函 數 輸 入 變 數 a 的 值• 使 用 printf 函 數 及 指 標 p 來 印 出 a 的 內 容• 使 用 scanf 函 數 及 指 標 p 再 次 輸 入 變 數 a 的 值• 使 用 printf 函 數 印 出 a 的 內 容• 最 後 使 用 printf 函 數 印 出 指 標 p 的 內 容© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.6


練 習 一 參 考 解 答#include int main(){int a, *p;}p = &a;scanf("%d", &a);printf("a=%d\n", *p);scanf("%d", p);printf("a=%d\n", a);printf("p=%p\n", p);return 0;© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.7.3 Pointer OperatorsOperatorsAssociativity Type() [] left to right highest+ - ++ -- ! * & (type) right to left unary* / % left to right multiplicative+ - left to right additive< >= left to right relational== != left to right equality&& left to right logical and|| left to right logical or?: right to left conditional= += -= *= /= %= right to left assignment, left to right comma© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.7


7.4 Calling Functions by Reference•Call by reference with pointer arguments–Pass address of argument using & operator–Allows you to change actual location in memory–Arrays are not passed with & because the array nameis already a pointer•* operator–Used as alias/nickname for variable inside of functionvoid double( int *number ){*number = 2 * ( *number );}– *number used as nickname for the variable passed© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.傳 遞 位 址 範 例#include f1(int *r){printf(“%d\n”, *r);*r = 5;}main(){int x = 3;printf(“%d\n”, x);f1(&x);printf(“%d”\n”, x);}傳 入 的 位 址 將 成為 指 標 r 的 初 值將 5 放 入 r 指 過 去 的 位 址x 與 *r 成 為 同 一筆 資 料 的 alias將 x 的 位 址 傳 入© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.8


3 #include fig07_06.c5 int cubeByValue( int n ); /* prototype */67 int main()8 {9 int number = 5; /* initialize number */1011 printf( "The original value of number is %d", number );14 number = cubeByValue( number );16 printf( "\nThe new value of number is %d\n", number );18 return 0; /* indicates successful termination */20 }2223 int cubeByValue( int n )24 {25 return n * n * n;27 } /* end function cubeByValue */© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.Program OutputThe original value of number is 5The new value of number is 125© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.9


Before main calls cubeByValue :int main(){int number = 5;number=cubeByValue(number);}number5int cubeByValue( int n ){return n * n * n;}nundefinedAfter cubeByValue receives the call:int main()number{int number = 5;5number = cubeByValue( number );}int cubeByValue( int n ){return n * n * n;}n5After cubeByValue cubes parameter n and before cubeByValue returns to main :int main()number{int number = 5; 5number = cubeByValue( number );}int cubeByValue( int n ){125return n * n * n;}n5Analysis of a typical call-by-value. (Part 1 of 2.)© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.After cubeByValue returns to main and before assigning the result to number:int main()number{int number = 5; 5125number = cubeByValue( number );}int cubeByValue( int n ){return n * n * n;}nundefinedAfter main completes the assignment to number:int main()number{int number = 5; 125125125number = cubeByValue( number );}int cubeByValue( int n ){return n * n * n;}nundefinedAnalysis of a typical call-by-value. (Part 2 of 2.)© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.10


1 /* Fig. 7.7: fig07_07.c2 Cube a variable using call-by-reference with a pointer argument */34 #include 56 void cubeByReference( int *nPtr ); /* prototype */78 int main()9 {10 int number = 5; /* initialize number */1112 printf( "The original value of number is %d", number );1314 /* pass address of number to cubeByReference */15 cubeByReference( &number );1617 printf( "\nThe new value of number is %d\n", number );1819 return 0; /* indicates successful termination */2021 } /* end main */2223 /* calculate cube of *nPtr; modifies variable number in main */24 void cubeByReference( int *nPtr )25 {26 *nPtr = *nPtr * *nPtr * *nPtr; /* cube *nPtr */27 } /* end function cubeByReference */Notice that the function prototypetakes a pointer to an integer.© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.fig07_07.cNotice how the address ofnumber is given -cubeByReference expects apointer (an address of a variable).Inside cubeByReference, *nPtr isused (*nPtr is number).Program OutputThe original value of number is 5The new value of number is 125© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.11


Before main calls cubeByReference :int main()number{5int number = 5;cubeByReference( &number );}void cubeByReference( int *nPtr ){*nPtr = *nPtr * *nPtr * *nPtr;}nPtrundefinedAfter cubeByReference receives the call and before*nPtr is cubed:int main(){int number = 5;}numbercubeByReference( &number );5void cubeByReference( int *nPtr ){*nPtr = *nPtr * *nPtr * *nPtr;}nPtrcall establishes this pointerAfter *nPtr is cubed and before program control returns to main :int main()number{125int number = 5;cubeByReference( &number );}void cubeByReference( int *nPtr ){125*nPtr = *nPtr * *nPtr * *nPtr;}called function modifiesnPtrcaller’s variableAnalysis of a typical call-by-reference with a pointerargument.© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.7.5 Using the const Qualifier with <strong>Pointers</strong>•const qualifier–Variable cannot be changed–Use const if function does not need tochange a variable–Attempting to change a const variableproduces an errorconst int x = 5;x 為 整 數 ; 值 為 5 不 能 被 改 變© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.12


•const pointersConst <strong>Pointers</strong>–Point to a constant memory location–Must be initialized when definedmyPtr 的 值 不int *const myPtr = &x;能 改•Type int *const –constant pointer to an intconst int *myPtr = &x;•Regular pointer to a const intconst int *const Ptr = &x;•const pointer to a const int•x can be changed, but not *Ptr© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.不 能 改 *myPtr的 值myPtr, *myPtr的 值 皆 不 能 改( 但 透 過 x 間 接 改*myPtr 是 可 以 的 )5 #include fig07_10.c (1/2)6 #include 78 void convertToUppercase( char *sPtr ); /* prototype */910 int main() 陣 列 名 稱 本 身 就 是 指 標 需 傳 入 字 元 指 標11 {12 char string[] = "characters and $32.98";1314 printf( "The string before conversion is: %s", string );傳 入 陣 列 名 稱15 convertToUppercase( string );16 printf( "\nThe string after conversion is: %s\n", string );18 return 0; /* indicates successful termination */1920 } /* end main */21© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.13


22 /* convert string to uppercase letters */23 void convertToUppercase( char *sPtr )fig07_10.c (2/2)24 {25 while ( *sPtr != '\0' ) {傳 入 字 元 指 標2627 if ( islower( *sPtr ) ) {28 *sPtr = toupper( *sPtr );29 }30此 指 標 指 到 的 字 元 內 容 被 變 更 ( 轉 換 成 大 寫 字 母 )31 ++sPtr; /* move sPtr to the next character */32 }指 標 內 容 被 變 更 ( 指 到 陣 列 中 下 一 個 字 元 位 置 )3334 } /* end function convertToUppercase */© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.Program OutputThe string before conversion is:characters and $32.98The string after conversion is:CHARACTERS AND $32.98© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.14


Example: <strong>Pointers</strong> pointing to constants任 何 sPtr 指 到 的 字 元 內 容 不 會 在 此 函 數 中 被 變 更24 void printCharacters( const char *sPtr )25 {26 /* loop through entire string */27 for ( ; *sPtr != '\0'; sPtr++ ) {28 printf( "%c", *sPtr );29 } /* end for */3031 } /* end function printCharacters */ In fig07_11.c© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.如 果 在 程 式 中 偷 偷 去 改 …8 int main()9 {10 int y;12 f( &y );14 return 0;16 } /* end main */1720 void f( const int *xPtr )21 {22 *xPtr = 100;23 }*xPtr 是 constant編 譯 時 會 產 生 錯 誤In fig07_12.c© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.15


Example: Constant <strong>Pointers</strong>3 #include In fig07_13.c5 int main()6 {7 int x;8 int y;12 int * const ptr = &x;1314 *ptr = 7;15 ptr = &y;17 return 0; 19 }ptr 是 constantpointer改 變 *ptr 是 允 許 的 ;*ptr 並 非 const編 譯 時 會 產 生 錯 誤ptr 不 可 被 變 更© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.Constant <strong>Pointers</strong> Pointing to Constants5 int main()6 {7 int x = 5; /* initialize x */8 int y; /* define y */13 const int *const ptr = &x;1415 printf( "%d\n", *ptr );17 *ptr = 7;18 ptr = &y;20 return 0;22 } /* end main */In fig07_14.cptr 是 constant*ptr 也 是 constant錯 誤 ! 改 變 *ptr 是 不允 許 的編 譯 時 會 產 生 錯 誤ptr 不 可 被 變 更© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.16


7.6 Bubble Sort Using Call-by-reference•Implement bubblesort using pointers– 請 自 行 閱 讀 fig07_15.c– 主 要 差 別 : 使 用 下 列 swap 函 數 來 交 換 兩 個 陣 列 元 素 的 值64 void swap( int *element1Ptr, int *element2Ptr )65 {66 int hold = *element1Ptr;67 *element1Ptr = *element2Ptr;68 *element2Ptr = hold;69 } /* end function swap */© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.•sizeofsizeof–Returns size of operand in bytes–For arrays: size of 1 element * number of elements–if sizeof( int ) equals 4 bytes, thenint myArray[ 10 ];printf( "%d", sizeof( myArray ) );•will print 40•sizeof can be used with–Variable names–Type name–Constant values© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.17


sizeof Example (fig07_16.c)8 int main()9 {10 float array[ 20 ]; /* create array */1112 printf( "The number of bytes in the array is %d"13 "\nThe number of bytes returned by getSize is %d\n",14 sizeof( array ), getSize( array ) );16 return 0;18 } /* end main */1921 size_t getSize( float *ptr )22 {23 return sizeof( ptr );25 } /* end function getSize */The number of bytes in the array is 80The number of bytes returned by getSize is 4© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.測 試 各 種 資 料 型 態 的 大 小 (fig07_17.c)這 是 在 Intel 32 位 元 電 腦 上 執 行 的 結 果sizeof c = 1 sizeof(char) = 1sizeof s = 2 sizeof(short) = 2sizeof i = 4 sizeof(int) = 4sizeof l = 4 sizeof(long) = 4sizeof f = 4 sizeof(float) = 4sizeof d = 8 sizeof(double) = 8sizeof ld = 8 sizeof(long double) = 8sizeof array = 80sizeof ptr = 4float array[20];© Copyright 1992–2004 by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.18

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!