1 / 17

Modular Programming H&K Chapter 6

Modular Programming H&K Chapter 6. Instructor – Gokcen Cilingir Cpt S 121 (July 7, 2011) Washington State University. Functions with Output Parameters (1).

alayna
Download Presentation

Modular Programming H&K Chapter 6

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Modular Programming H&K Chapter 6 Instructor – GokcenCilingir Cpt S 121 (July 7, 2011) Washington State University

  2. Functions with Output Parameters (1) • In many application, we felt the need of a mechanism that will allow us to define a function that computes more than one value, and passes those values to the caller. Examples: • A function that computes the min and max of numbers. • A function that returns change in a transaction in the format of bill counts. Function Function we have this model for but, we want to have this model all functions now… for some functions… • We’re going to learn about output parameters today which enables programmers to design functions that can pass more than one value to the outside world.

  3. Functions with Output Params (2) • Let’s first remember what happens when we call a function from another function, say main: void foo (int a, char b, double c); int main (void) { intmyint = 12; char mychar = 'a'; double mydouble = 23.45; foo (myint, mychar, mydouble); … } void foo (int a, char b, double c) { /* This does random, meaningless stuff */ ++a; b = 'd'; c *= 2; } Function maindata area myint 12 mychar 'a' mydouble 23.45 Values are copied Function foo data area a 12 b 'a' c 23.45

  4. Functions with Output Params (3) Remember that each function has a separate area of memory for storing its local variables and parameters. Each data area exists only when the function is active. The state of memory is thus as it was prior to the call to foo: Function maindata area myint 12 mychar 'a' mydouble 23.45

  5. Functions with Output Params (4) Function maindata area myint 12 mychar 'a' When function foo is called from main, the foo function's data area becomes active, and the actual parameter values passed to foo are copied to spaces in its memory area: mydouble 23.45 Values are copied Function foo data area a 12 b 'a' c 23.45

  6. Functions with Output Params (5) Finally, when the function foo finishes executing, its memory area disappears, and control returns to the main function. The state of memory is thus as it was prior to the call to foo: Function maindata area myint 12 mychar 'a' mydouble 23.45

  7. Functions with Output Params(6) • Let’s look at the definition of a pointer • A variable that stores as its contents the address of another variable intmyint = 12; int *p = &myint; p myint A variable that stores an address of another variable (memory location) A variable (memory location) that stores an integer value 1000 12 1000 memory address • We should be able to use these address values to access a variable (memory location) indirectly • Indirect access to these memory locations also will allow for modification to the contents

  8. Functions with Output Params (7) • In C, we can achieve the effect of output parameters by passing memory addresses (pointers) instead of values. Here's how we could modify the previous code to accomplish this: void foo (int a, char b, double c); int main (void) { intmyint = 12; char mychar = 'a'; double mydouble = 23.45; /* pass memory locations of variables, not vars themselves */ foo (&myint, &mychar, &mydouble); … } void foo (int *a, char *b, double *c) { ++(*a); *b = 'd'; *c *= 2; } increment the value at memory pointed to by a by 1 assign to memory pointed to by b assign to memory pointed to by c

  9. Functions with Output Params (8) • In order to visualize what the previous code is doing, we'll need make up the memory addresses that identifies the memory locations at which the variable values are stored: Function maindata area Function foo data area myint &myint a 12 100 100 b &mychar mychar 200 'a' c 200 300 &mydouble mydouble 23.45 300 • Since foo's parameters contain memory locations and not values, foo can use those memory locations to access, and ultimately to change, the original values in the main function.

  10. Aside: The Many Faces of * • By now, you might find the multiple meanings of the '*' operator confusing. Let's review them. • Arithmetic operator multiplication • e.g., 5 * 3 • Used while declaring pointer type variables, read as “pointer to“. • e.g., char *c; • The type of variable/parameter c is “pointer to char” • Unary indirection operator, read as "follow the pointer“. • e.g., *i = 4; • *i means follow the pointer in i • Each of these meanings is markedly different!

  11. Let’s apply what we learned • Problem statement: Design a function divide that accepts four arguments: • number: an integer input parameter • divisor: an integer input parameter • result: an integer output parameter • remainder: an integer output parameter The function divides number by divisor. The result is placed into the output parameter result, and the remainder is placed into the output parameter remainder. Also show how a main function would call divide.

  12. Let’s apply what we learned(2) void divide (int num, int div, int *result_p, int *remainder_p) { *result_p = num / div; *remainder_p = number % divisor; } int main(void) { int num = 10, divisor = 3, result = 0, remainder = 0; divide(num, divisor,&result,&remainder); /*We can expect here that result and remainder variables now hold new values*/ }

  13. Let’s find what output will be n1 n2 int n1 = 5, n2 = 10, *p1 = NULL, *p2 = NULL; p1 = &n1; p2 = &n2; printf("%d %d %d %d\n", n1, n2, *p1, *p2); *p1 = 6; printf("%d %d %d %d\n", n1, n2, *p1, *p2); *p2 = *p1; printf("%d %d %d %d\n", n1, n2, *p1, *p2); *p2 = 7; printf("%d %d %d %d\n", n1, n2, *p1, *p2); p1 = p2; printf("%d %d %d %d\n", n1, n2, *p1, *p2); Output: 5 10 5 10 6 10 6 10 6 6 6 6 6 7 6 7 6 7 7 7 10 p1 5 p2 100 200 100 200 n1 n2 10 p1 6 p2 100 200 100 200 n1 n2 6 p1 6 p2 100 200 100 200 n1 n2 7 p1 6 p2 100 200 100 200 n1 n2 7 p1 6 p2 100 200 200 200

  14. Scope (1) • As has been discussed in previous lectures, the scope of an identifier is the region of a program within which the identifier is defined. In general: • #define macro definitions have global scope, meaning that they are defined within the entire source file • A function is visible to all functions defined below it. However, its local variables are visible only to itself.

  15. Identify the scope of the identifiers in the following example: #define MAX 950 #define LIMIT 200 void one(intarg, double second); void two(char one, double arg); int main(void) { intlocalVar; ... } void one(intarg, double second) { intone_local; ... } void two(char one, double arg) { intlocalVar; ... }

  16. Pitfalls of Pointers and Output Parameters • Not assigning a pointer with a valid memory address • Improper use of the dereference or indirection operator • *ptr = &variable // most likely incorrect • ptr = number // intention is *ptr = number • Overusing pointers • Defining a function to compute too many results and breaking our notion of proper top-down design • Overcomplicating the concept of a pointer • Recall it’s just a variable  • Others?

  17. References • J.R. Hanly & E.B. Koffman, Problem Solving and Program Design in C (6th Ed.), Addison-Wesley, 2010 • P.J. Deitel & H.M. Deitel, C How to Program (5th Ed.), Pearson Education , Inc., 2007.

More Related