Chapter 7 Simple Data Types and Function Calls Yuksel / Demirer Representation and Conversion of Numeric Types • Simple data type is the data type used to store a single value. – e.g., int, double, and char. • Operations involving integer are faster than those involving double. • Operations with integer are always precise, whereas loss of accuracy may occur when dealing with double. Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-2 Internal Formats of Type int and Type double • Integers are represented by standard binary numbers. – e.g., 7 = 01101. • Doubles are represented by two sections: mantissa and exponent. – real number = mantissa * 2exponent – 4.0 = 0010 * 20001 = 2 * 21 Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-3 Integer Types in C Type Range short -32767 .. 32767 unsigned short 0 .. 65535 int -32767 .. 32767 unsgined 0 .. 65535 long -2147483647 .. 2147483647 unsgined long 0 .. 4294967295 Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-4 Floating-Point Types in C Type Range float 10-37 .. 1038 double 10-307 .. 10308 long double 10-4931 .. 104932 Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-5 An Example to Print Ranges for Positive Numeric Data You can determine the maximal or minimal int and double values of your C environment by the following program. %e is the format in scientific notation Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-6 Numerical Inaccuracies • The representation error (or round-off error) is an error due to coding a real number by a finite number of digits. – e.g., the fraction of 1/3 is 0.3333… – It is impossible to code the precise value of 1/3. • The representation error depends on the number of digits used in the mantissa. – The more bits, the smaller the error. Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-7 An Example of the Representation Error • for (trial = 0.0; trial != 10.0; trial = trial + 0.1) { … } • The result of adding 0.1 for one hundred times is not exactly 10.0. – The above loop may fail to terminate on some computers. Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-8 Other Problems When Manipulating Numbers • Cancellation error is an error resulting from applying an operation to a large number and a small number, and the effect of the smaller number is lost. – e.g., 1000.0 + 0.0000001234 is equal to 1000.0. • Arithmetic underflow is an error in which a very small computational result is represented as zero. – e.g., 0.00000001 * 10-1000000 is equal to 0. Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-9 Other Problems When Manipulating Numbers • Arithmetic overflow is an error in which the result is too large to be represented. – The error may be detected in compiling time or run time. – Some machine may let the arithmetic overflow occur and the computational result is unexpected. – e.g., 999999999 * 109999999 may become a negative value in some machine. Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-10 Automatic Conversion of Data Types (1/2) • The data of one numeric type may be automatically converted to another numeric type. e.g., int k = 5, m = 4, n; double x = 1.5, y = 2.1, z; Context Expression with binary operator and operands of different types Example k + x value is 6.5. Copyright ©2004 Pearson Addison-Wesley. All rights reserved. Explanation Value of k is converted to double before the operation. 7-11 Automatic Conversion of Data Types (2/2) Context Example Explanation z = k / m; Assignment with type double target expression value is 1.25; z is 1.0. variable and type int expression Expression is evaluated first. Then the result is converted to double. n = x * y; Assignment with type int target expression value is 3.15; n is 3. variable and type double expression Expression is evaluated first. Then the result is converted to int. Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-12 Explicit Conversion of Data Types • C also provides an explicit type conversion operation called cast. • For example, frac = n1 / d1; if n1 = 2 and d1 = 4, frac would be 0. • Cast: place the name of the desired type in parentheses immediately before the value to be converted. – e.g., frac = (double)n1 / (double)d1; – frac is evaluated to 0.5. Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-13 Representation and Conversion of Type char (1/2) • Character values can be compared by the equality operators == and !=, or by the relational operators <, <=, >, and >=. e.g., letter = ‘A’; if (letter < ‘Z’) … • Character values may also be compared, scanned, printed, and converted to type int. Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-14 Representation and Conversion of Type char (2/2) • Each character has its own unique numeric code. • A widely used standard is called American Standard Code for Information Interchange (ASCII). (See Appendix A in the textbook) – The printable characters have codes from 32 to 126, and others are the control characters. – For example, the digit characters from ‘0’ to ‘9’ have code values from 48 to 57 in ASCII. • The comparison of characters (e.g., ‘a’<‘c’) depends on the the corresponding code values in ASCII. Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-15 An Example of the Conversion between char and int C permits conversion of type char to type int and vice versa. Convert char to int Convert int to char Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-16 Enumerated Types (1/2) • Enumerated type is a data type whose list of values is specified by the programmer. • Syntax: typedef enum {identifier_list} enum_type; • e.g., typedef enum {entertainment, rent, food, clothing} expense_t; Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-17 Enumerated Types (2/2) • In the above example, a new data type expense_t is created, and we can declare a variable with this type: e.g., expense_t expense_kind; • The variable expense_kind can be manipulated as any other integer. e.g., switch(expense_kind){ case entertainment: printf(“entertainment”); break; case rent: case food: … Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-18 Functions: Arguments are passed by values • Argument lists are used to communicate information from the main function to its function subprograms. – Arguments make functions more versatile because they allow us to execute the same function with different sets of data. • Return values are used to communicate information from the function subprogram back to the main program. • We can use output parameters to return multiple results from a function. • When a function is called, it is given a copy of the values that are passed in as arguments. – If you manipulate the value of an argument, it has no impact on its value in the main function – Therefore, these are called input parameters, because they can only bring information into the function, and not back out. Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-19 Function Parameters (1/2) • When invoking a function call, we can include function parameters in the parameter list. • Declaring a function parameter is accomplished by simply including the prototype of the function in the parameter list. A function parameter Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-20 Function Parameters (2/2) • Suppose there are two existed functions: double sqrt(double) , and double sin(double). • evaluate is a function that includes a function parameter as shown in the previous slide. • We can invoke evaluate as follows. evaluate(sqrt, 0.25, 25.0, 100.0); evaluate(sin, 0.0, 3.14159, 0.5*3.14159); Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-21 Example with pass by value void myFunc(int arg); int main(void) { int x = 5; myFunc(x); printf(“%d\n”, x); } void myFunc(int arg) { arg = 4; } /* Output */ 5 Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-22 In main: int x = 5; In main, x is assigned the value 5. This places the value 5 in the memory cell reserved for x In this case, it is at address 0x234 Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-23 In main: myFunc(x); We call the function myFunc and pass it the value of x myFunc allocates a new memory cell for its formal parameter arg The value 5 (a copy of the value in x) is placed in arg Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-24 In myFunc: arg = 4; In myFunc, arg is assigned the value of 4 This places the value 4 in the memory cell for arg This is not the same cell as x Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-25 In main: printf(“%d\n”, x); Back in main, when we print out x, the value it points to is still 5. Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-26 Functions: Arguments are passed by Reference • What if we want our changes to the value in the function to affect the value in the main function? • We can accomplish that by passing the address of a variable as argument to a function and manipulate that variable inside the function. • In the formal parameter list, we put a * in front of the parameter name. – This defines a pointer, which means that we will be passing the address of the value, rather than the value itself. • In the function call, we put an & in front of the argument name. – The & tells the compiler to pass the address of the variable, not its value. • When we need to access the value of the argument in the function, we put a * in front of the variable name – This * tells the compiler to access the value pointed to by the address in the variable. Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-27 Example with pass by reference void myFunc(int* arg); int main(void) { int x = 5; myFunc(&x); printf(“%d\n”, x); } void myFunc(int* arg) { *arg = 4; } /* Output */ 4 Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-28 In main: int x = 5; In main, x is assigned the value 5, just like before. The address of the memory cell for x is 0x234 The value of &x is 0x234 Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-29 In main: myFunc(&x); When we call myFunc, we pass it &x, the address of x This value is stored in the memory cell for arg. arg == 0x234, *arg == 5 Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-30 In myFunc: *arg = 4; When we set the value of *arg, we are setting the value pointed to by arg – the value at 0x234 Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-31 In main: printf(“%d\n”, x); Back in main, the value of x is now 4 Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-32 #include <stdio.h> #include <math.h> void separate(double num, char *signp, int *wholep, double *fracp); int main(void) { double value, fr; char sn; int whl; printf("Enter a value to analyze> "); scanf("%lf", &value); separate(value, &sn, &whl, &fr); printf("Parts of %.4f\n sign: %c\n", value, sn); printf(" whole number magnitude: %d\n", whl); printf(" fractional part: %.4f\n", fr); return 0; } Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-33 void separate(double num, char *signp, int *wholep, double *fracp) { double magnitude; if (num < 0) *signp = ’-’; else if (num == 0) *signp = ’ ’; else *signp = ’+’; magnitude = fabs(num); *wholep = floor(magnitude); *fracp = magnitude - *wholep; } Parts of 35.8170 sign: + whole number magnitude: 35 fractional part: 0.8170 Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-34 Figure 6.4 Parameter Correspondence for separate(value, &sn, &whl, &fr); Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-35 Common Errors with Pointers • Note that this is a run-time error. It will not cause a compiler error. • Therefore, make sure you set a pointer equal to the address of some variable (of the correct type!) before you attempt to use it. ERROR! • For example: double x = 10.0, y = 20.0, p_x = &x; This will cause the program to crash as p_y has not been initialized. *p_x, *p_y; printf(“x = %f and y = %f\n”, *p_x, *p_y); Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-36 The Conditional Expression Operator • Condition ? expression 1: expression 2 • Max_value = (a>b) ? a : b; • S = (x <0) ? -1 : x*x Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-37 Scope of Names • The scope of a name refers to the region of a program where a particular meaning of a name is visible or can be referenced. • #define variables scope begins at their definition and ends at the end of the source file. All functions can “see” these variables. • The scope of the name of a function begins with the function prototype and ends with the end of the source file. • All formal parameter names and local variables are visible only from their declarations to the closing brace of the function in which they are declared. Copyright ©2004 Pearson Addison-Wesley. All rights reserved. 7-38