introduction to computer and program designocw.nctu.edu.tw/course/icp011/ch04.pdfthe basic data...

49
Lesson 4 Data Types Introduction to Computer and Program Design James C.C. Cheng Department of Computer Science National Chiao Tung University

Upload: lydiep

Post on 12-Apr-2018

229 views

Category:

Documents


2 download

TRANSCRIPT

Lesson 4Data Types

Introduction to Computer and Program Design

James C.C. Cheng

Department of Computer Science

National Chiao Tung University

The basic data types There are 13 basic data types in C

In C++, bool represents boolean value, true or false.

The size of bool depends on compiler, 1 byte in most case. 2

Name Size (byte) Rangechar 1 -128 to 127

unsigned char 1 0 to 255

short 2 -32768 to 32767

unsigned short 2 0 to 65535

int 4 -231 to 231 - 1

unsigned int 4 0 to 232 - 1

long 4 -231 to 231 - 1

unsigned long 4 0 to 232 - 1

__int64, long long 8 -263 to 263 – 1

unsigned __int64 8 0 to 264 - 1

float 4 ±(1.175494351e-38 to 3.402823466e38 )

double 8 ±(2.2250738585072014e-308 to 1.7976931348623158e308 )

long double 12 in DevC++, 8 in MSC x86 80-bit extended precision format

The basic data types sizeof operator

return the number of byte for a variable or a data type

size_t sizeof( name ); size_t

In 32-bit environment: unsigned long

In 64-bit environment: unsigned long long

sizeof(type name)

ex: sizeof(int); sizeof(double);

sizeof(variable name)

ex: int x; sizeof(x); double d; sizeof(d);

Integers The integer data types are:

bool, char, short, int, long, __int64 bool in C99: #include <stdbool.h>

unsigned char, unsigned short, unsigned int, unsigned long, unsigned __int64

4

5

Integers Decimal system

Each digit = {0, 1, …, 9 } 347210 = ( 3 x 103 ) + ( 4 x 102 ) + ( 7 x 101 ) + ( 2 x 100 )

Binary system Each digit = {0, 1} Binary Decimal

10112 = (1 x 23)10 + (0 x 22)10 + (1 x 21)10 + (1 x 20)10 = 1110

Decimal Binary 13 mod 2 = 1 13/2 = 6 mod 2 = 0 6/2 = 3 mod 2 = 1 3/2 = 1 mod 2 = 1 1/2 =0

Addition: 1+0 = 12 ; 1+1 = 102

Subtraction: 1-0 = 12 ; 10-1 = 12

1310 = 11012

Integers Hexadecimal system

Each digit = {0-9, A, B, C, D, E, F} Hex Decimal

3A7C = (3 x 163)10 + (10 x 162)10 + (7 x 161)10 + (12 x 160)10= 1497210

Decimal Hex Method 1: the same as Dec binary Method 2: decbinhex

Addition (2+7)16 = 916

(1+9)16 = A16

(2+B)16 = D16

(9+9)16 = 1216

Subtraction (5-2)16 = 316

(F-2)16 = D16

(10-1)16 = F16 6

7

Integers Binary Hex

Grouping each 4 digits from the smallest digit 11001110101101 = 0011,0011,1010,1101

Check the hex bin table 0011,0011,1010,1101 = 33AD

Hex Binary

0 0000

1 0001

2 0010

3 0011

4 0100

5 0101

6 0110

7 0111

8 1000

9 1001

A 1010

B 1011

C 1100

D 1101

E 1110

F 1111

8

Integers The limits of unsigned integers

1 bit: 0, 1

4 bit: 0 ~ (24 – 1)10 = 0 ~ 1510

1 byte: 0 ~ (28 – 1)10 = 0 ~ 25510

2 byte: 0 ~ (216 – 1)10 = 0 ~ 65,53510

4 byte: 0 ~ (232 – 1)10 = 0 ~ 4,294,967,29510

8 byte: 0 ~ (264 – 1)10 = 0 ~ 18,446,744,073,709,551,61510

#include <limits.h>…unsigned char uc = UCHAR_MAX;unsigned short us = USHRT_MAX;unsigned int u = UINT_MAX;unsigned long ul = ULONG_MAX;unsigned long long ull = ULLONG_MAX;

Integers The limits of signed integers

9

#include <limits.h>…char c = CHAR_MIN;

c = CHAR_MAX;short s = SHRT_MIN;

s = SHRT_MAX;int i = INT_MIN;

i = INT_MAX;long l = LONG_MIN;

l = LONG_MAX;long long ll = LLONG_MIN;

ll = LLONG_MAX;

10

Integers Signed integer

How to store a signed integer?

Method 1: Sign bit

The range is ( 0 ~ 27 – 1) = (0 ~ 127)

pros: simple

cons:

negative zero

Addition and subtraction problems1001,10112 + 0001,10112 = 1011,01102 -27+27 = -54 …!?

1 0 0 1 1 0 1 1

0 0 0 1 1 0 1 1Sign bit

= -27

= 27

11

Integers Signed integer

Method 2: One’s complement

27 = 0001,10112

-27 = -(0001,10112) 0/1 inversion 1110,01002

The range is ( 0 ~ 27 – 1) = (0 ~ 127)

Pros:

Simple

No addition and subtraction problems

1110,01002 + 0001,10112 = 1111,11112 -27 + 27 = -0

1110,01002 + 0000,00012 = 1110,01012 -27 + 1 = -26

Cons:

Negative zero

12

Integers Signed integer

Method 3: Two’s complement

27 = 0001,10112

-27 = 1,0000,00002 - 0001,10112 = 1110,01012

The range is - 27 ~ -1, 0, 1 ~ (27 – 1) = -128 ~ 127

Pros:

No negative zero

No addition and subtraction problems

1110,01012 + 0001,10112 =

1,0000,00002 (max 8 bit) = 0000,00002 -27 + 27 = 0

1110,01012 + 0000,00012 = 1110,01102

= -(1,0000,00002 - 1110,01102 ) = -(0001,1010)2 -27 + 1 = -26

Cons:

It needs more conversion cost

Integers Constants:

bool bT = true, bF = false, bTrue = 5438, bFalse = 0;

The zero is false; Non-zero is true.

char cA = ‘A’, cB = 66, cC= 65603, cD = 0x43, cE = 0105, cEnter = ‘\n’; Hex constant: Using the prefix "0x" Octal constant: Using the prefix "0"

short i = 10, j = 32767, k = -32768, s = 32768, t = -32769;

int x = 10, y = -100, z = 0x02AB2F;

int nMax = 2147483647;

int nMinA = -2147483648; // It causes a warning message

int nMinB = (-2147483647 – 1); // OK!

13

- 2147483648 - ( 2147483648 )

Integers Constants:

long n = 120, m = 12345L, a = 0xFFFFL;

long integer constant : Using the suffix “L”

__int64 nn = 10, mm = 9876543210LL;

long long constant : Using the suffix “LL”

64-bit integer in scanf and printf: ll or I64

14

__int64 nn = 10;long long mm = 9876543210LL ;scanf("%I64d%lld", &nn, &mm);printf("%lld, %I64d \n", nn, mm); // OK, using “ll” or “I64” // Notice that "l" is lowercase. "L" means "long double", %Ld ==> %d

nn = 7; mm = 1;printf("%d, %I64d \n", nn, mm); // In x86, the second output is wrong!?

07, 00, 00, 00 00, 00, 00, 00 01, 00, 00, 00 00, 00, 00, 00

nn mm

Integers Constants:

unsigned char, unsigned short and unsigned int

unsigned long : The suffix is “UL”

unsigned __int64 :

In Dev C++, the suffix is “LLU”

In VC++, the suffix is “ULL”

15

unsigned char uc = -1;unsigned short us = -1;unsigned int ui = -1;printf("%u, %u, %u\n", uc, us, ui);

unsigned long un0 = 123UL, un1 = -1UL;printf("%u, %u\n", un0, un1);

unsigned long long unn0 = 9876543210000001234LLUunsigned long long unn1 = -1LLU;printf("%llu, %I64u\n", unn0 , unn1 );

Integers integers in printf and scanf

In printf <= 4byte argument 4byte

long long 8 byte

%d: singed decimal

%i: signed decimal integer (In scanf, including hex and octal)

%u: unsigned integer

%o: unsigned octal integer

%x: unsigned lowercase hex integer (in scanf, including lowercase and uppercase)

%X: uppercase unsigned hex integer (Only in printf)

%c: character

%p: Address in hex digits. 32-bit: 8-digit, 64-bit: 16-digit (only in printf)

%n: output the number of characters written/read so far, the argument shall be an integer point. In VC++, this function is disabled. 16

Integers integers in printf and scanf

data length: hh: chat

h: short

l: long

ll long long

17

char c = -1; printf("%02hhX\n", c); // Failed in DevC++short s = -1; printf("%04hX\n", s);long l = -1L; printf("%08lX\n", l);long long ll = -1LL; printf("%016llX\n", ll);

Integers Implicit typecast

small large

signed unsigned

18

short s1 = 10; int n1 = 0xFF0000;if(n1 > s1) // short int

printf("Hello\n");

long long nn = 0x7FFFFFFF00000000ULL; if(nn > n1) // int long long

printf("World!\n");

unsigned int u= 0;int i = -1;if(i>u) // int unsigned int

printf("-1 > 0\n");

Float point numbers float , 32-bit IEEE-754 float point number

double , 64-bit IEEE-754 float point number

long double In VC++, long double = double

In GCC 4.3 or above, sizeof( long double) is 12 byte,

In x86 environment, it only uses 10 byte

Why it need 12 byte? In 32-bit environment, the data access unit is 4 byte.

x86 80-bit extended precision format

19

20

Float point numbers Decimal fraction Binary?

0.5 10 = 2-110 = 0.1 2

0.25 10 = 2-210 = 0.01 2

0.125 10 = 2-310 = 0.001 2

….

0.10112 = (1 x 2-1) 10 + (0 x 2-2) 10 + (1 x 2-3) 10 + (1 x 2-4) 10

= 0.510 + 0.12510 + 0.062510

= 0.687510

0.37510 = 0.0110.375 * 2 = 0.750.75 * 2 = 1.50.5 * 2 = 1.0

Some decimal fraction cannot be converted to binary system 0.410 = 0.001100110011……2

= 0.00112

21

Float point numbers Decimal fraction Binary?

integer part binary

fraction part binary

13.562510 = 1101.10012

1310 = 1101

0.562510 = 0.10012

22

Float point numbers IEEE 754 (The IEEE Standard for Floating-Point Arithmetic)

IEEE, Institute of Electrical and Electronics Engineers 國際電子電機學會 32-bit IEEE-754

Sign: 1bit Exponent: 8 bit (127 offset) Fraction: 23 bit

64-bit IEEE-754 Sign: 1bit Exponent: 11 bit (1023 offset) Fraction: 52 bit

mantissa

Float point numbers IEEE 754 (The IEEE Standard for Floating-Point Arithmetic)

Example:

23

13.562510= 1101.10012= 1.10110012 * 23

For 32 bit float:= (-1)0 * 1.10110012 * 2130-127

Sign = 0Exponent = 130 = 100000102Fraction = 10110010…02

For 64 bit float:= (-1)0 * 1.10110012 * 21026-1023

Sign = 0Exponent = 1026= 100,0000,00102Fraction = 10110010…02

0 1 0 0 0 0 0 1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x41590000

, , , , , ,0 1 0 0 0 0 0 0 0 0 1 0 1 0 1 1 0 0 1 0 0 0 0 0 … 0 0x402B20...0

, , , , , , ,

Float point numbers x86 0-bit extended precision format ( for gcc's long double)

Sign: 1bit Exponent: 15 bit (16383 offset) Integer part: 1bit

In 80387 or above, this bit always be 1 Fraction: 63 bit

Value = (-1)sign 2exponent – 16383 (1.fraction)2

Reference: http://en.wikipedia.org/wiki/Extended_precision

24

… 1 …Sign Exponent Integer Fraction

Float point numbers Addition and subtraction

13.562510 + 0.1562510 = 13.7187510

= (-1)0 * 23 * 1.10110012 + (-1)0 * 2-3 * 1.012

= 23 * 1.10110012 + 23 * 2-6 * 1.012

= 23 * 1.10110012 + 23 * 0.000001012

= 23 * 1.101101112

= 13.7187510

13.562510 - 0.1562510 = 13.4062510

= (-1)0 * 23 * 1.10110012 + (-1)1 * 2-3 * 1.012

= 23 * 1.10110012 + (-1) * 23 * 2-6 * 1.012

= 23 * 1.10110012 + (-1) * 23 * 0.000001012

= 23 * 1.10110012 + 23 * 1.111110112

= 23 * 11.101011012 (Overflow) 23 * 1.101011012

= 13. 406251025

} 2's complement

Float point numbers Truncation and Rounding

Example:

26

1234567.210= 1,0010,1101,0110,1000,0111. 0011,0011,0011... 2= 1. 0010,1101,0110,1000,0111 0011,0011,0011... 2 * 220

For 32 bit float:= (-1)0 * 1. 0010,1101,0110,1000,0111 0011,0011,0011... 2 * 2147-127

Sign = 0Exponent = 147 = 100100112Fraction (23 bit) = 0010,1101,0110,1000,0111 0011,0011,0011 2 Truncation

= 0010,1101,0110,1000,0111 010 2 Rounding (1234567.25)

1234567.1510= 1,0010,1101,0110,1000,0111. 0010,0110,0110,... 2= 1. 0010,1101,0110,1000,0111 0010,0110,0110... 2 * 220

For 32 bit float:= (-1)0 * 1. 0010,1101,0110,1000,0111 0010,0110,0110... 2 * 2147-127

Sign = 0Exponent = 147 = 100100112Fraction (23 bit) = 0010,1101,0110,1000,0111 0010,0110,0110 2 Truncation

= 0010,1101,0110,1000,0111 001 2 (1234567.125)

27

Float point numbers Limits

Float Values (b = bias)

Sign Exponent (e ) Fraction (f ) Value

0 00..00 00..00 0

0 00..0000..01~ Positive Denormalized Real

11..11 0.f × 2(-b+1)

000..01~

XX..XXPositive Normalized Real

11..10 1.f × 2(e-b)

0 11..11 00..00 +Infinity

0 11..1100..01~

NaN11..11

28

Float point numbers Limits

Sign Exponent (e) Fraction (f) Value

1 00..00 00..00 -0

1 00..0000..01~ Negative Denormalized Real

11..11 -0.f × 2(-b+1)

100..01~

XX..XXNegative Normalized Real

11..10 -1.f × 2(e-b)

1 11..11 00..00 -Infinity

1 11..1100..01~

NaN11.11

Float point numbers Limits

29

#include <float.h>…float f = FLT_MIN;

f = FLT_MAX;double d = DBL_MIN;

d = DBL_MAX;long double ld = LDBL_MIN;

ld = LDBL_MAX;printf("%f\n", f);printf("%f\n", d);printf("%Lf\n", ld); // only in GCC 4.3 or above

30

Float point numbers printf()

float will be converted to double

%f, %e, %E, %g, and %G need 8 byte argument

%+width+.precision + {f/e/E/g/G},

width: the minimum number of characters printed, if width is not given, all characters of the value are printed.

precision:

for f/e/E : the number of digits after the decimal point,

for g/G: the maximum number of significant digits printed.

default is sixfloat r = 0.00000123;printf("%10.8f, %4.2e, %4.2g\n", r, r, r);

0.00000123, 1.23e-006, 1.2e-006Output:

Float point numbers scanf()

%f: float, 4 byte data

%lf: double 8 byte data

%Lf: long double Only in GCC 4.3 or above *.c file

G++ does not accept %Lf

31

Float point numbers Constants:

float f = 1.1234f; Using the suffix "f"

double r0 = 1.12345, r1 = 123, r2 = 0x64, r3 = 123LLU;

Without any prefix and suffix

Typecast integer float

float double

32

float fx = 33.3f;printf("%f\n", fx * 2 / 3 );

#include <float.h>…float fx = 0.0f;double dx = fx + DBL_MIN;printf("%f\n", dx);

Float point numbers Never check a floating number to EQUAL a value

33

float A = 1.2f;float B = 12.0f;scanf("%f%f", &A, &B); // type 1.2 and 12float D = A - B / 10.0f; // D = 1.2 – 12/10.0 should be zeroif(D == 0.0) // Oops!

printf("!\n");else

printf("%f\n", D); // This line will be show up

Float point numbers Be careful with using a floating number to be an iterator

34

float i;for(i=0.0f; i<=1.0f; i+=0.1f)

printf("%f\n", i);

// How many lines will be displayed?

35

Union One memory space to be accessed as different data types

The size of the union is at least the size of the largest member.

union U{unsigned long i;float f;

};

int main(){U u;u.f = 13.5625f;

printf("%08X\n", u.i); // 41590000printf("%08X\n", u.f); // In x86: 00000000printf("%08X%08X\n", u.f); // In x86: 00000000402B2000

// Three printing method for float. Which one is the best?};

Characters ASCII (American Standard Code for Information Interchange)

'0'~'9': 48~57

'A'~'Z': 65~90

'a'~'z': 97~122

http://en.wikipedia.org/wiki/ASCII

Constants:

Using the single quotation marks ' '

36

char a = 'A';printf("%c: %d\n", a, a);a = '9';printf("%c: %d\n", a, a);a = 'xyz';printf("%c: %d\n", a, a);

a = "uvw"; // Compiling error!

char a = 50, b = 70, c= 100;printf("%c%c%c\n", a, b, c);

Characters Escape Sequences

\n: (10) newline

\t: (9) tab

\b: (8) backspace

\r: (13) return key In MS Windows, the end of line consists of two characters: \r\n (13, 10)

\': single quotation

\": double quotation

\\: backslash

\0: null

\OOO: OOO is 3-digit octal ASCII char e = '\050',

\xOO: OO is 2-digit hex ASCII char i = '\x41',

37

char a = '\n', b = '\t', c= '\b';char d = '\r', i = '\'', j = '\"';char f = '\\', g = '\0';

Strings A character array

The last character of a string must be \0

Constant string: Using the double quotation marks " "

String declaration and initialization:

38

char s1[5] = "abcd"; // a writable char arraychar s2[5] = {'A', 'B', 'C', 'D', 0}; // a writable char arraychar s3[] = "xyz"; // a writable char arraychar s4[] = { 'X', 'Y', 'Z', 0}; // a writable char arraychar* s5 = "uvw"; // a char pointer that points a read-only data

printf("%s\n%s\n%s\n%s\n%s\n", s1, s2, s3, s4, s5);

s1[0] = 'T'; // OK!

s5[0] = 'T'; // Runtime errorchar* s6 = { 'U', 'V', 'W', 0}; // Compiler error

Strings Misuse

39

char *s1 = "abcd";char s2[] = "ABCD";printf("%s\n%s\n", s1, s2);

s1 = s2; // The pointer can be an l-valueprintf("%s\n%s\n", s1, s2); // ABCD, ABCDs2[0] = 'T'; // Watch the side effect!printf("%s\n%s\n", s1, s2); // TBCD, TBCD

char s1[] = "abcd";char s2[] = "ABCD";s1 = s2;// Compiling error! The array name cannot be an l-value

side effectA expression returns one or more additional values.That means it modifies some observable state.

Strings scanf()

%[ ]: Read the specified characters Input ends when a non-matching character is reached or the field width is reached.

40

char A[20] = {0}; // Declare a string of 20 zero charactersscanf("%s", A); // type "ABC EFG XYZ" printf("%s\n", A);

char A[20] = {0}, B[20] = {0}, C[20] = {0};scanf("%s%s%s", A , B, C); // type "ABC EFG XYZ" printf("%s %s %s\n", A, B, C);

char A[20] = {0}, B[20] = {0}, C[20] = {0};scanf("%[0-9]%[A-Z]%[a-z]", A , B, C);printf("%s%s%s\n", A, B, C);

scanf("%[ -~, '\t']", A); // Read ASCII 9 and 32 to 126

printf("%s\n", A);scanf("%[ -~, '\t', '\n' ]", A); // Oops….

Strings scanf()

%[^ ]: Read the characters except the specified characters

41

char A[20] = {0}, B[20] = {0}, C[20] = {0};scanf("%[^0-9]%[^A-Z]%[^a-z]", A , B, C);printf("%s %s %s\n", A, B, C);

scanf("%[^'\n']", A); // Read all characters except '\n'printf("%s\n", A);

Strings gets()

char* gets ( char *s);

It reads characters from the stdin and stores them into s until a newline character or the end-of-file is reached.

On success, it returns s. Otherwise, it returns NULL

42

#include <stdio.h>…char A[100] = {0};while( gets(A) != NULL ){

printf("%s\n", A);}

Typecast Change the data type of variable

x = (x's type name) y;

Ex:

43

int n = 1234;float f = (float) n; char c = (char) f;double d = (double) c;

#define The text replacement

Usage:

#define replacement target_text

Ex:

#define PI 3.14159

#define EXP 2.71828

#define NULL_STR

double p = PI;

printf("%f\n", p); // 3.14159

printf("%f\n", EXP); // 2.71828

printf("%f\n", NULL_STR); // Compile Error

printf("%f\n", NULL_STREXP); // Compile Error

printf("%f\n", NULL_STR EXP); // 2.71828 44

#define Macro, 巨集

Ex:#define MIN_INT(x) (-2147483647 – 1)

#define INC(x) (++x)

#define ADD(x, y) (x+y)

#define MIN(x, y) (x<y?x:y)

#define _MIN(x, y) x<y?x:ytice

float x = PI * MIN(2.0f, 3.0f); // x = 6.28298

float y = PI * _MIN(2.0f, 3.0f); // y = 3.0 !?

45

請注意括號!

#define Do not use #define to define a data type

Ex:

46

#define uint unsigned intuint a, b ;// OK! a and b are unsigned int

char *s1 = " Hello ", *s2 = " World ";#define CSTR char *CSTR s3 = " OK ", s4 = " oops ";

// s4 is not a char *

typedef To define a datatype

The usage:typedef original_typename new_typename;

EX:

47

注意要加分號

typedef unsigned int uint;uint a, b ; // OK! a and b are unsigned int

typedef char * cstr;cstr sA = "Hello", sB = "world!";printf("%s, %s\n", sA, sB ); // OK!

練習題 設計一個函式,名為inverseN,用來反轉一個unsigned long

例如:12345則回傳54321;12321則回傳12321;0則回傳0須注意overflow,若數字2223334445則回傳0並顯示overflow。請用最節省空間方式完成,不可用64bit整數、字串及陣列

給一個double陣列A,用來儲存某數學函數的運算結果,即A[i] = f(ix)。

請寫一個函式來計算f 的微分: ′ ≅ ′ ≅

void dev(const double* A, double* B, int n);其中A為輸入陣列,B為微分結果,n為陣列元素個數。A[i] = 0 if i < 0 or i >= n

48

練習題 請設計generic min & max functions,可處理所有C語言的基本資料型

態,並回傳最大值及最小值。void GMin(const void *pa, const void *pb, void *pOut, size_t n); void GMax(const void *pa, const void *pb, void *pOut, size_t n); pa及pb兩者為指向同一資料型態的輸入,pOut為輸出,n為資料大小(byte)

請以上題來實作generic 的bubble sortvoid bbsort(void *p, int n, size_t m, char dir);p為指向欲排序的資料陣列,n為陣列元素個數,m為每個元素的資料大小(byte)若dir為0,則由小排到大,若不為0 ,則由大排到小

49