Lecture 09-1

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 83

1

9
C Structures, Unions, Bit
Manipulations and
Enumerations
2

課程目標
▪ Introduction
▪ Structure Definitions
▪ Initializing Structures
▪ Accessing Members of Structures
▪ Using Structures with Functions
▪ typedef
▪ Unions
▪ Bitwise Operators
▪ Bit Fields
▪ Enumeration Constants
3

Main Topics
▪ Structure
– Collections of related variables (aggregates) under
one name
– Can contain variables of different data types
– Commonly used to define records to be stored in
files
– Combined with pointers, can create linked lists,
stacks, queues, and trees
▪ Union
– Allowed data type being overloaded
▪ Bit fields
▪ Enumeration
4

C Program Design
C Structures, Unions, Bit
Manipulations and Enumerations
▪ Structure Definitions
5

Structure Definitions
struct PersonalData
{
char name[NAMESIZE];
char address[ADDRSIZE];
int YearOfBirth;
int MonthOfBirth;
int DayOfBirth;
};

▪ A structure definition does not reserve


space in memory.
▪ Instead, creates a new data type used to
define structure variables.
6

Define Structure Variables (I)

struct PersonalData
{
char name[NAMESIZE];
char address[ADDRSIZE];
int YearOfBirth;
int MonthOfBirth;
int DayOfBirth;
};

struct PersonalData teacher, students[51], *p;


7

Define Structure Variables (II)

struct PersonalData
{
struct
char PersonalData
name[NAMESIZE];
{
char address[ADDRSIZE];
int char name[NAMESIZE];
YearOfBirth;
int char address[ADDRSIZE];
MonthOfBirth;
int int YearOfBirth;
DayOfBirth;
}; int MonthOfBirth;
int DayOfBirth;
} teacher,
struct students[51],
PersonalData teacher, *p;
students[51], *p;
// variable identifier follows type
8

Define Structure Variables (III)

struct PersonalData
{
struct
char PersonalData
name[NAMESIZE];
{
char address[ADDRSIZE];
typedef struct _tagPersonalData
int char name[namesize];
YearOfBirth;
{
int char address[addresssize];
MonthOfBirth;
char name[NAMESIZE];
int int YearOfBirth;
DayOfBirth;
char address[ADDRSIZE];
}; int MonthOfBirth;
int YearOfBirth;
int DayOfBirth;
int students[51],
} teacher, MonthOfBirth; *p;
struct PersonalData
int teacher, students[51], *p;
DayOfBirth;
// variable identifier follows type
} PersonalData;

PersonalData teacher, students[51], *p;


9
struct PersonalData
{
char name[NAMESIZE];

Valid Operations char address[ADDRSIZE];


int YearOfBirth;
int MonthOfBirth;
int DayOfBirth;
};

struct PersonalData x, teacher,


students[51], *p;

▪ Assigning a structure to a structure of the same type


x = teacher;
teacher = *p;
students[i] = x;
▪ Taking the address (&) of a structure
p = &students[i];
▪ Accessing the members of a structure
gets(students[0].name);
p->YearOfBirth = 88;
▪ Using the sizeof to determine the size of a structure
size = sizeof(struct PersonalData);
size = sizeof(x);
10
#include <stdio.h>

#define NAMESIZE 50
Example #define ADDRSIZE
struct PersonalData
80

{
char name[NAMESIZE];
char address[ADDRSIZE];
int YearOfBirth;
int MonthOfBirth;
int DayOfBirth;
};

main()
{
struct PersonalData student;

// Enter the student's record


printf("Enter name of the student: ");
gets(student.name);
printf("Enter address: ");
gets(student.address);
printf("Enter birthday: yy/mm/dd: ");
scanf("%2d/%2d/%2d", &student.YearOfBirth,
&student.MonthOfBirth, &student.DayOfBirth);

printf("\n\n");

// Print out the student record


printf("Student name: %s\n", student.name);
printf("Address: %s\n", student.address);
printf("Bithday: %2d/%2d/%2d\n", student.YearOfBirth,
student.MonthOfBirth, student.DayOfBirth);
}
11
#include <stdio.h>

#define NAMESIZE 50
Example #define ADDRSIZE
struct PersonalData
80

{
char name[NAMESIZE];
char address[ADDRSIZE];
int YearOfBirth;
int MonthOfBirth;
int DayOfBirth;
};

main()
{
struct PersonalData student;

// Enter the student's record


printf("Enter name of the student: ");
gets(student.name);
printf("Enter address: ");
gets(student.address);
printf("Enter birthday: yy/mm/dd: ");
scanf("%2d/%2d/%2d", &student.YearOfBirth,
&student.MonthOfBirth, &student.DayOfBirth);

printf("\n\n");

// Print out the student record


printf("Student name: %s\n", student.name);
printf("Address: %s\n", student.address);
printf("Bithday: %2d/%2d/%2d\n", student.YearOfBirth,
student.MonthOfBirth, student.DayOfBirth);
}
12
#include <stdio.h>

#define NAMESIZE 50
Example #define ADDRSIZE
struct PersonalData
80

{
char name[NAMESIZE];
char address[ADDRSIZE];
int YearOfBirth;
int MonthOfBirth;
int DayOfBirth;
};

main()
{
struct PersonalData student;

// Enter the student's record


printf("Enter name of the student: ");
gets(student.name);
printf("Enter address: ");
getPersonInfo(&student);
gets(student.address);
printf("Enter birthday: yy/mm/dd: ");
scanf("%2d/%2d/%2d", &student.YearOfBirth,
&student.MonthOfBirth, &student.DayOfBirth);

printf("\n\n");

// Print out the student record


printf("Student name: %s\n", student.name);
printf("Address: %s\n", student.address);
showPersonInfo(&student);
printf("Bithday: %2d/%2d/%2d\n", student.YearOfBirth,
student.MonthOfBirth, student.DayOfBirth);
}
13
// person.h
#define NAMESIZE 50
#define ADDRSIZE 80
Example struct PersonalData
{
char name[NAMESIZE];
char address[ADDRSIZE];
int YearOfBirth;
int MonthOfBirth;
int DayOfBirth;
};
// main.c
#include <stdio.h> void getPersonInfo(struct PersonalData *);
#include "person.h" void showPersonInfo(struct PersonalData *);

main()
{
struct PersonalData student;

// Enter the student's record


getPersonInfo(&student);

printf("\n\n");

// Print out the student record


showPersonInfo(&student);
}
14
// person.h
#define NAMESIZE 50
#define ADDRSIZE 80
Example// person.c
struct PersonalData
{
#include <stdio.h> char name[NAMESIZE];
#include "person.h" char address[ADDRSIZE];
int YearOfBirth;
void getPersonInfo(structint
PersonalData *p)
MonthOfBirth;
{ int DayOfBirth;
printf("Enter name:};");
// main.c gets(p->name);
void getPersonInfo(struct PersonalData *);
#include <stdio.h>printf("Enter address: ");
void showPersonInfo(struct PersonalData *);
#include "person.h"
gets(p->address);
main() printf("Enter birthday: yy/mm/dd: ");
{ scanf("%2d/%2d/%2d", &p->YearOfBirth,
struct PersonalData&p->MonthOfBirth,
student; &p->DayOfBirth);
}
// Enter the student's record
getPersonInfo(&student);
void showPersonInfo(struct PersonalData *p)
{
printf("\n\n");
printf("Name: %s\n", p->name);
printf("Address:
// Print out the student record %s\n", p->address);
printf("Bithday: %2d/%2d/%2d\n", p->YearOfBirth,
showPersonInfo(&student);
} p->MonthOfBirth, p->DayOfBirth);
}
15
// person.h
#define NAMESIZE 50
#define ADDRSIZE 80
Example// person.c
struct PersonalData
{
#include <stdio.h> char name[NAMESIZE];
#include "person.h" char address[ADDRSIZE];
int YearOfBirth;
void getPersonInfo(structint
PersonalData
MonthOfBirth;*p)
{ int DayOfBirth;
printf("Enter name:};");
// main.c gets(p->name);
void getPersonInfo(struct PersonalData *);
#include <stdio.h>printf("Enter address: ");
void showPersonInfo(struct PersonalData *);
#include "person.h"
gets(p->address);
main() printf("Enter birthday: yy/mm/dd: ");
{ scanf("%2d/%2d/%2d", &p->YearOfBirth,
struct PersonalData&p->MonthOfBirth,
student; &p->DayOfBirth);
}
// Enter the student's record
getPersonInfo(&student);
void showPersonInfo(struct PersonalData *p)
{
printf("\n\n");
printf("Name: %s\n", p->name);
printf("Address:
// Print out the student record %s\n", p->address);
printf("Bithday: %2d/%2d/%2d\n", p->YearOfBirth,
showPersonInfo(&student);
} p->MonthOfBirth, p->DayOfBirth);
}
16

sizeof Operator

struct SomeData
{
char aChar;
int anInt;
float aFloat;
double aDouble;
};

sizeof(struct SomeData) = ?
17

#include <stdio.h>

sizeof Operator
#include <limits.h>
#include <float.h>

struct SomeData
{
char aChar;
int anInt;
float aFloat;
double aDouble;
};

main()
{
char mark[]={'M', 'A', 'R', 'K'};
struct SomeData x;

printf("sizeof(struct SomeData) = %d\n\n",


sizeof(struct SomeData));

x.aChar = 'A'; x.anInt = INT_MAX;


x.aFloat = FLT_MAX; x.aDouble = DBL_MAX;

printf("Address of x: %p\n", &x);


printf("Address of x.aChar: %p\n", &x.aChar);
printf("Address of x.anInt: %p\n", &x.anInt);
printf("Address of x.aFloat: %p\n", &x.aFloat);
printf("Address of x.aDouble: %p\n", &x.aDouble);
}
18

#include <stdio.h>

sizeof Operator
#include <limits.h>
#include <float.h>

struct SomeData
{
char aChar;
int anInt;
float aFloat;
double aDouble;
};

main()
{
char mark[]={'M', 'A', 'R', 'K'};
struct SomeData x;

printf("sizeof(struct SomeData) = %d\n\n",


sizeof(struct SomeData));

x.aChar = 'A'; x.anInt = INT_MAX;


x.aFloat = FLT_MAX; x.aDouble = DBL_MAX;

printf("Address of x: %p\n", &x);


printf("Address of x.aChar: %p\n", &x.aChar);
printf("Address of x.anInt: %p\n", &x.anInt);
printf("Address of x.aFloat: %p\n", &x.aFloat);
printf("Address of x.aDouble: %p\n", &x.aDouble);
}
19

sizeof Operator

struct SomeData ▪ Because the size of data


{ items of a particular type is
char aChar; machine dependent and

int anInt; because storage alignment


considerations are machine
float aFloat;
dependent, so too is the
double aDouble; representation of a structure.
};

sizeof(struct SomeData) = ?
20

C Program Design
C Structures, Unions, Bit
Manipulations and Enumerations
▪ Initializing Structures
21

Example

// person.c
#include <stdio.h>
#include "person.h"

void getPersonInfo(struct PersonalData *p)


{
printf("Enter name: ");
gets(p->name);
printf("Enter address: ");
gets(p->address);
printf("Enter birthday: yy/mm/dd: ");
// person.h scanf("%2d/%2d/%2d", &p->YearOfBirth,
#define NAMESIZE 50 &p->MonthOfBirth, &p->DayOfBirth);
#define ADDRSIZE 80 }
struct PersonalData
{ void showPersonInfo(struct PersonalData *p)
char name[NAMESIZE]; {
char address[ADDRSIZE]; printf("Name: %s\n", p->name);
int YearOfBirth; printf("Address: %s\n", p->address);
int MonthOfBirth; printf("Bithday: %2d/%2d/%2d\n", p->YearOfBirth,
int DayOfBirth; p->MonthOfBirth, p->DayOfBirth);
}; }

void getPersonInfo(struct PersonalData *);


void showPersonInfo(struct PersonalData *);
22

Example

// person.c
#include <stdio.h>
#include "person.h"
// main.c
void getPersonInfo(struct PersonalData *p)
#include <stdio.h>
{ #include "person.h"
printf("Enter name: ");
gets(p->name);
main() address: ");
printf("Enter
{
gets(p->address);
struct
printf("Enter PersonalData
birthday: student = {
yy/mm/dd: ");
// person.h scanf("%2d/%2d/%2d", &p->YearOfBirth,
"Hale-Evans, Ron",
#define NAMESIZE 50 &p->MonthOfBirth, &p->DayOfBirth);
#define ADDRSIZE 80
"Seattle, Washington",
}
struct PersonalData 1965,
{ 6,
void showPersonInfo(struct PersonalData *p)
char name[NAMESIZE]; { 27
char address[ADDRSIZE]; }; %s\n", p->name);
printf("Name:
int YearOfBirth; printf("Address: %s\n", p->address);
int MonthOfBirth; printf("Bithday: %2d/%2d/%2d\n", p->YearOfBirth,
int DayOfBirth;
// Print out the student record
p->MonthOfBirth, p->DayOfBirth);
}; showPersonInfo(&student);
}
}
void getPersonInfo(struct PersonalData *);
void showPersonInfo(struct PersonalData *);
23

Example

// person.c
#include <stdio.h>
#include "person.h"
// main.c
#include <stdio.h> void getPersonInfo(struct PersonalData *p)
#include "person.h" {
printf("Enter name: ");
main() gets(p->name);
printf("Enter address: ");
{
gets(p->address);
struct PersonalData persons[] = {
printf("Enter birthday: yy/mm/dd: ");
// person.h{"Hale-Evans, Ron", "Seattle, Washington", 1965, 6, 27},
scanf("%2d/%2d/%2d", &p->YearOfBirth,
#define NAMESIZE 50
{"Liddell, Alice", "Wonderland", 1852, 5, 4},
&p->MonthOfBirth, &p->DayOfBirth);
#define ADDRSIZE 80 } "The Galaxy", 1961, 11, 15}
{"Adams, Douglas",
struct PersonalData
{
};
void showPersonInfo(struct PersonalData *p)
struct
char PersonalData *p;
name[NAMESIZE]; {
int address[ADDRSIZE];
char i; printf("Name: %s\n", p->name);
int YearOfBirth; printf("Address: %s\n", p->address);
int
// MonthOfBirth;
Print out the records printf("Bithday: %2d/%2d/%2d\n", p->YearOfBirth,
int DayOfBirth;
for(i p->MonthOfBirth, p->DayOfBirth);
= 0, p = persons; i < sizeof(persons)/sizeof(struct PersonalData); i++){
}; }
ShowPersonInfo(p++);
printf("\n"); PersonalData *);
void getPersonInfo(struct
void }showPersonInfo(struct PersonalData *);
}
24

Example

// person.c
#include <stdio.h>
#include "person.h"
// main.c
#include <stdio.h> void getPersonInfo(struct PersonalData *p)
#include "person.h" {
printf("Enter name: ");
main() gets(p->name);
printf("Enter address: ");
{
gets(p->address);
struct PersonalData persons[] = {
printf("Enter birthday: yy/mm/dd: ");
// person.h{"Hale-Evans, Ron", "Seattle, Washington", 1965, 6, 27},
scanf("%2d/%2d/%2d", &p->YearOfBirth,
#define NAMESIZE 50
{"Liddell, Alice", "Wonderland", 1852, 5, 4},
&p->MonthOfBirth, &p->DayOfBirth);
#define ADDRSIZE 80 } "The Galaxy", 1961, 11, 15}
{"Adams, Douglas",
struct PersonalData
{
};
void showPersonInfo(struct PersonalData *p)
struct
char PersonalData *p;
name[NAMESIZE]; {
int address[ADDRSIZE];
char i; printf("Name: %s\n", p->name);
int YearOfBirth; printf("Address: %s\n", p->address);
int
// MonthOfBirth;
Print out the records printf("Bithday: %2d/%2d/%2d\n", p->YearOfBirth,
int DayOfBirth;
for(i p->MonthOfBirth, p->DayOfBirth);
= 0, p = persons; i < sizeof(persons)/sizeof(struct PersonalData); i++){
}; }
ShowPersonInfo(p++);
printf("\n"); PersonalData *);
void getPersonInfo(struct
void }showPersonInfo(struct PersonalData *);
}
25

Example

// person.c
#include <stdio.h>
#include "person.h"
// main.c
#include <stdio.h> void getPersonInfo(struct PersonalData *p)
#include "person.h" {
printf("Enter name: ");
main() gets(p->name);
printf("Enter address: ");
{
gets(p->address);
struct PersonalData persons[] = {
printf("Enter birthday: yy/mm/dd: ");
// person.h{"Hale-Evans, Ron", "Seattle, Washington", 1965, 6, 27},
scanf("%2d/%2d/%2d", &p->YearOfBirth,
#define NAMESIZE 50
{"Liddell, Alice", "Wonderland", 1852, 5, 4},
&p->MonthOfBirth, &p->DayOfBirth);
#define ADDRSIZE 80 } "The Galaxy", 1961, 11, 15}
{"Adams, Douglas",
struct PersonalData
{
};
void showPersonInfo(struct PersonalData *p)
struct
char PersonalData *p;
name[NAMESIZE]; {
int address[ADDRSIZE];
char i; printf("Name: %s\n", p->name);
int YearOfBirth; printf("Address: %s\n", p->address);
int
// MonthOfBirth;
Print out the records printf("Bithday: %2d/%2d/%2d\n", p->YearOfBirth,
int DayOfBirth;
for(i p->MonthOfBirth, p->DayOfBirth);
= 0, p = persons; i < sizeof(persons)/sizeof(struct PersonalData); i++){
}; }
ShowPersonInfo(p++);
printf("\n"); PersonalData *);
void getPersonInfo(struct
void }showPersonInfo(struct PersonalData *);
}
26

Initializing Structures

// initialized when defined


struct PersonalData persons[] = {
{"Hale-Evans, Ron", "Seattle, Washington", 1965, 6, 27},
{"Liddell, Alice", "Wonderland", 1852, 5, 4},
{"Adams, Douglas", "The Galaxy", 1961, 11, 15}
};

struct PersonalData classLeader, friend;

// initialized using assignment operator


classLeader = persons[1];

// Initialized field by field


strcpy(friend.name, "George Lin");
strcpy(friend.address, "Taipei Taiwan");
friend.YearOfBirth = 1978;
friend.MonthOfBirth = 12;
friend.DayOfBirth = 24;
27

Initializing Structures

// initialized when defined


struct PersonalData persons[] = {
{"Hale-Evans, Ron", "Seattle, Washington", 1965, 6, 27},
{"Liddell, Alice", "Wonderland", 1852, 5, 4},
{"Adams, Douglas", "The Galaxy", 1961, 11, 15}
};

struct PersonalData classLeader, friend, *p;

// initialized using assignment operator


classLeader = persons[1];

// Initialized field by field using a pointer


p = &friend;
strcpy(p->name, "George Lin");
strcpy(p->address, "Taipei Taiwan");
p->YearOfBirth = 1978;
p->MonthOfBirth = 12;
p->DayOfBirth = 24;
28

C Program Design
C Structures, Unions, Bit
Manipulations and Enumerations
▪ Accessing Members of Structures
29

Accessing structure members

▪ Dot operator (.) for structure variables


struct PersonalData friend;
strcpy(friend.name, "George Lin");
strcpy(friend.address, "Taipei Taiwan");
friend.YearOfBirth = 1978;
friend.MonthOfBirth = 12;
friend.DayOfBirth = 24;

▪ Arrow operator (->) for pointers


struct PersonalData friend, *p;
p = &friend;
strcpy(p->name, "George Lin");
strcpy(p->address, "Taipei Taiwan");
p->YearOfBirth = 1978;
p->MonthOfBirth = 12;
p->DayOfBirth = 24;
30

More on Arrow Operator

▪ Dot operator
struct PersonalData(.) for*p;
friend, structure variables
p struct
= &friend;
PersonalData friend;
strcpy((*p).name, "George Lin");
strcpy(friend.name, "George Lin");
strcpy((*p).address, "Taipei Taiwan");
strcpy(friend.address,
(*p).YearOfBirth "Taipei Taiwan");
= 1978;
friend.YearOfBirth = 1978;= 12;
(*p).friend.MonthOfBirth

equivalent
(*p).DayOfBirth = 24;
friend.MonthOfBirth = 12;
friend.DayOfBirth = 24;

▪ Arrow operator (->) for pointers


struct PersonalData friend, *p;
p = &friend;
strcpy(p->name, "George Lin");
strcpy(p->address, "Taipei Taiwan");
p->YearOfBirth = 1978;
p->friend.MonthOfBirth = 12;
p->DayOfBirth = 24;
31

C Program Design
C Structures, Unions, Bit
Manipulations and Enumerations

▪ Using Structures with Functions


32

typedef struct _tagComplex


Parameter {
Passings double real;
▪ Passing Value double imag;
} Complex;
Complex AddByVal(Complex a, Complex b);

▪ Passing Reference

void AddByRef(const Complex *a, const Complex *b,


Complex *c);
33
// complex.h
typedef struct _tagComplex
{
Example double real;
double imag;
} Complex;

Complex AddByVal(Complex, Complex);


void AddByRef(Complex*, Complex*, Complex*);

// complex.c
#include "complex.h"

Complex AddByVal(Complex a, Complex b)


{
Complex c;

c.real = a.real + b.real;


c.imag = a.imag + b.imag;

return c;
}

void AddByRef(Complex* a, Complex* b, Complex* c)


{
c->real = a->real + b->real;
c->imag = a->imag + b->imag;
}
34
// complex.h
typedef struct _tagComplex
{
Example double real;
double imag;
} Complex;

Complex AddByVal(Complex, Complex);


void AddByRef(Complex*, Complex*, Complex*);

// main.c
#include <stdio.h>
// complex.c
#include "complex.h"
#include "complex.h"
main()
Complex AddByVal(Complex a, Complex b)
{
{
Complex x = {12.0, 5};
Complex c;
Complex y = {4.0, 8.0};
Complex z, w;
c.real = a.real + b.real;
c.imag = a.imag + b.imag;
// Call by value
z = AddByVal(x, y);
return c;
printf("(%.1f + i%.1f) + (%.1f + i%.1f) = (%.1f + i%.1f)\n",
}
x.real, x.imag, y.real, y.imag, z.real, z.imag);
void AddByRef(Complex* a, Complex* b, Complex* c)
// Call by reference
{
AddByRef(&x, &y , &w);
c->real = a->real + b->real;
printf("(%.1f + i%.1f) + (%.1f + i%.1f) = (%.1f + i%.1f)\n",
c->imag = a->imag + b->imag;
x.real, x.imag, y.real, y.imag, w.real, w.imag);
}
}
35

Passing arrays by value


▪ Create a structure with the array as a
member

▪ Pass the structure


36

C Program Design
C Structures, Unions, Bit
Manipulations and Enumerations

▪typedef
37

typedef
typedef type-declaration synonym;

▪ Creates synonyms for previously defined data


types
– typedef does not create a new data type
– Only creates an alias

▪ Create shorter type names


▪ Make a program more portable.
38

Example
// complex.h
struct _tagComplex
{
double real;
double imag;
};

typedef struct _tagComplex Complex;


typedef struct _tagComplex *ptrComplex;

Complex AddByVal(Complex, Complex);


void AddByRef(ptrComplex, ptrComplex, ptrComplex);
39

Some More Examples

// complex.h
struct _tagComplex
// SomeTypeDef.h {
double real;
#include "complex.h" double imag;
};

typedef char CHAR; typedef struct _tagComplex Complex;


typedef struct _tagComplex *ptrComplex;
typedef CHAR* PSTR;
typedef unsigned char BYTE; Complex AddByVal(Complex, Complex);
void AddByRef(ptrComplex, ptrComplex, ptrComplex);

typedef int INT;


typedef unsigned UINT;
typedef UINT DWORD;

typedef Complex (*COMPLEXOP)(Complex, Complex);


typedef INT (*ARITHOP)(INT, INT);

INT sum(INT a, INT b);


INT substract(INT a, INT b);
INT mul(INT a, INT b);
INT div(INT a, INT b);
40

Some More Examples


/* arith.c */
#include <SomeTypedef.h>

INT sum(INT a, INT b)


// complex.h
{ struct _tagComplex
return a + b; {
double real;
} double imag;
};

typedef struct _tagComplex Complex;


INT substract(INT a, INT b) typedef struct _tagComplex *ptrComplex;
{
return a - b; Complex AddByVal(Complex, Complex);
void AddByRef(ptrComplex, ptrComplex, ptrComplex);
}
// SomeTypeDef.h
#include "complex.h"
INT mul(INT a, INT b)
{ typedef char CHAR;
typedef CHAR* PSTR;
return a * b; typedef unsigned char BYTE;

} typedef int INT;


typedef unsigned UINT;
typedef UINT DWORD;
INT div(INT a, INT b)
typedef Complex (*COMPLEXOP)(Complex, Complex);
{ typedef INT (*ARITHOP)(INT, INT);

if(b) return a / b; INT sum(INT a, INT b);


INT substract(INT a, INT b);
else return 0;
INT mul(INT a, INT b);
} INT div(INT a, INT b);
41

Some More Examples

#include <stdio.h>
// complex.h
#include "SomeTypedef.h" struct _tagComplex
{
double real;
double imag;
ARITHOP arith[4]={sum, substract, mul, div}; };

typedef struct _tagComplex Complex;


main() typedef struct _tagComplex *ptrComplex;

{
Complex AddByVal(Complex, Complex);
INT val1, val2, op; void AddByRef(ptrComplex, ptrComplex, ptrComplex);

printf("Enter two numbers: "); // SomeTypeDef.h


#include "complex.h"
scanf("%d %d", &val1, &val2);
typedef char CHAR;
typedef CHAR* PSTR;
typedef unsigned char BYTE;
printf("0: Add, 1: Sub, 2: Mul, 3: Div\n");
do { typedef int INT;
typedef unsigned UINT;
printf("Enter number of operation: "); typedef UINT DWORD;

scanf("%d", &op); typedef Complex (*COMPLEXOP)(Complex, Complex);


} while(op<0 || op>3); typedef INT (*ARITHOP)(INT, INT);

INT sum(INT a, INT b);


INT substract(INT a, INT b);
printf("%d", (*arith[op])(val1, val2)); INT mul(INT a, INT b);
INT div(INT a, INT b);
}
42

Some More Examples

#include <stdio.h>
// complex.h
#include "SomeTypedef.h" struct _tagComplex
{
double real;
double imag;
ARITHOP arith[4]={sum, substract, mul, div}; };

typedef struct _tagComplex Complex;


main() typedef struct _tagComplex *ptrComplex;

{
Complex AddByVal(Complex, Complex);
INT val1, val2, op; void AddByRef(ptrComplex, ptrComplex, ptrComplex);

printf("Enter two numbers: "); // SomeTypeDef.h


#include "complex.h"
scanf("%d %d", &val1, &val2);
typedef char CHAR;
typedef CHAR* PSTR;
typedef unsigned char BYTE;
printf("0: Add, 1: Sub, 2: Mul, 3: Div\n");
do { typedef int INT;
typedef unsigned UINT;
printf("Enter number of operation: "); typedef UINT DWORD;

scanf("%d", &op); typedef Complex (*COMPLEXOP)(Complex, Complex);


} while(op<0 || op>3); typedef INT (*ARITHOP)(INT, INT);

INT sum(INT a, INT b);


INT substract(INT a, INT b);
printf("%d", (*arith[op])(val1, val2)); INT mul(INT a, INT b);
INT div(INT a, INT b);
}
43

Exercise (HW #10)


1. Implement a program similar to the
above example but for complex
numbers.
44

C Program Design
C Structures, Unions, Bit
Manipulations and Enumerations

▪Unions
45

union
▪ It is sometimes desirable to define a variable
which can be of two or more different types
according to different circumstances
(overloading).
▪ The distinction between a union and a structure:
– The members of a structure define different
variables
– The members of a union define different
manifestations of the same variable.
▪ The space need only be allocated to
accommodate the largest type specified in a
union.
46

union Definition

union Remark { typedef union _tagRemark {


int age; int age;
double tall; double tall;
char month[4]; char month[4];
} rem; } REMARK;

REMARK rem;
union Remark {
int age;
double tall;
char month[4];
sizeof(union Remark)=?
};
sizeof(REMARK)=?
union Remark rem;
47

Valid union Operations

▪ Assignment to union of same type: =


x = y; y = *p; union Remark {
▪ Taking address: & int age;
p = &x; double tall;
char month[4];
▪ Accessing union members: . } x, y, *p;
int n = x.age;
printf("%s\n", y.month);
▪ Accessing members using pointers: ->
int m = p->age;
printf("%s\n", p->month);
48

Example // main.c
#include <stdio.h>
#include <string.h>
#include "remark.h"

void ShowData(VarRemark data)


{
switch(data.typeRemark){
case 0:
printf("Age = %d\n", data.rem.age);
break;
// remark.h
case 1:
printf("Tall = %f\n", data.rem.tall);
typedef union _tagRemark {
break;
int age;
double tall; case 2:
printf("Month = %s\n", data.rem.month);
char month[4];
break;
} REMARK;
}
} A union may only be initialized with a
typedef struct _tagVarRemark { value of the type of its first
int typeRemark; // 0: age
// 1: tall main() member.
{
// 2: month
VarRemark datas[3]={{0, 35}, {1}, {2}};
REMARK rem;
int i;
} VarRemark;
datas[1].rem.tall = 174.5;
strcpy(datas[2].rem.month, "Jul");

for(i=0; i< sizeof(datas) / sizeof(VarRemark); i++)


ShowData(datas[i]);
}
49

Example // main.c
#include <stdio.h>
#include <string.h>
#include "remark.h"

void ShowData(VarRemark data)


{
switch(data.typeRemark){
case 0:
printf("Age = %d\n", data.rem.age);
break;
// remark.h
case 1:
printf("Tall = %f\n", data.rem.tall);
typedef union _tagRemark {
break;
int age;
double tall; case 2:
printf("Month = %s\n", data.rem.month);
char month[4];
break;
} REMARK;
}
}
typedef struct _tagVarRemark {
int typeRemark; // 0: age
main()
// 1: tall
{
// 2: month
VarRemark datas[3]={{0, 35}, {1}, {2}};
REMARK rem;
int i;
} VarRemark;
datas[1].rem.tall = 174.5;
strcpy(datas[2].rem.month, "Jul");

for(i=0; i< sizeof(datas) / sizeof(VarRemark); i++)


ShowData(datas[i]);
}
50

C Program Design
C Structures, Unions, Bit
Manipulations and Enumerations

▪Bitwise Operators
51

Bits
▪ All data is represented internally as
sequences of bits
– Each bit can be either 0 or 1
– Sequence of 8 bits forms a byte

▪ What operations needed?


52

Bitwise Operators
Operator Description
& bitwise AND The bits in the result are set to 1 if the corresponding bits
in the two operands are both 1 .
| bitwise inclusive The bits in the result are set to 1 if at least one of the corresponding bits
OR in the two operands is 1.
^ bitwise exclusive The bits in the result are set to 1 if exactly one of the corresponding bits
OR in the two operands is 1.
<< left shift Shifts the bits of the first operand left by the number of bits specified by
the second operand; fill from the right with 0 bits.
>> right shift Shifts the bits of the first operand right by the number of bits specified by
the second operand; the method of filling from the left is machine
dependent.
~ one’s complement All 0 bits are set to 1 and all 1 bits are set to 0.
53

Example (I)

// displayBits.c

void displayBits( unsigned value )


{
unsigned c; // counter
unsigned displayMask = 1 << 31; // displayMask

printf( "%10u = ", value );

for ( c = 1; c <= 32; c++ ) {// loop through bits


putchar( value & displayMask ? '1' : '0' );
value <<= 1; // shift value left by 1
// output space per 8 bits
if ( c % 8 == 0 ) putchar( ' ' );
} /* end for */

putchar( '\n' );
} /* end function displayBits */
54

Example (I)

// main.c
#include <stdio.h>
// displayBits.c
void displayBits( unsigned value ); // prototype
void displayBits( unsigned value )
{ int main( void )
unsigned c; // counter {
unsigned
unsigned displayMask = 1 << 31; // x; // variable to hold user input
displayMask

while(1){
printf( "%10u = ", value );
printf( "Enter an unsigned integer: " );
scanf(
for ( c = 1; c <= 32; c++ ) {// loop"%u", &x );
through bits
putchar( value & displayMask ? '1' : '0' );
value <<= 1; // shift valuedisplayBits(
left by 1 x );
}
// output space per 8 bits
if ( c % 8 == 0 ) putchar( ' ' );
} /* end for */ return 0; // indicates successful termination

putchar( '\n' ); } /* end main */


} /* end function displayBits */
55

Example (I)

// main.c
#include <stdio.h>
// displayBits.c
void displayBits( unsigned value ); // prototype
void displayBits( unsigned value )
{ int main( void )
unsigned c; // counter {
unsigned
unsigned displayMask = 1 << 31; // x; // variable to hold user input
displayMask

while(1){
printf( "%10u = ", value );
printf( "Enter an unsigned integer: " );
scanf(
for ( c = 1; c <= 32; c++ ) {// loop"%u", &x );
through bits
putchar( value & displayMask ? '1' : '0' );
value <<= 1; // shift valuedisplayBits(
left by 1 x );
}
// output space per 8 bits
if ( c % 8 == 0 ) putchar( ' ' );
} /* end for */ return 0; // indicates successful termination

putchar( '\n' ); } /* end main */


} /* end function displayBits */
56

Example (II)

// displayBits.c

void displayBits( char* heading, unsigned value )


{
unsigned c; // counter
unsigned displayMask = 1 << 31; // displayMask

printf( "%8s", heading );

for ( c = 1; c <= 32; c++ ) {// loop through bits


putchar( value & displayMask ? '1' : '0' );
value <<= 1; // shift value left by 1
// output space per 8 bits
if ( c % 8 == 0 ) putchar( ' ' );
} /* end for */

putchar( '\n' );
} /* end function displayBits */
57

Example (II)
// main.c
#include <stdio.h>

void displayBits( char*, unsigned ); // prototype

int main( void )


{
// displayBits.c unsigned x, y; // variable to hold user input
void displayBits( char* while(1){
heading, unsigned value )
{ printf( "Enter two unsigned integers in hex.: " );
unsigned c; // counter scanf( "%x %x", &x, &y );
unsigned displayMask = 1 << 31; // displayMask
displayBits( "x =", x );
printf( "%8s", heading );
displayBits( "y =", y );
for ( c = 1; c <= 32; c++ ) {// loop "~x
displayBits( through bits
=", ~x );
putchar( value & displayMask ? '1' : '0' );
displayBits( "~y =", ~y );
value <<= 1; // shift value left by 1
// output space per 8displayBits(
bits "x & y =", x & y);
if ( c % 8 == 0 ) putchar( ' ' );
displayBits( "x | y =", x | y);
} /* end for */ displayBits( "x ^ y =", x ^ y);
putchar( '\n' ); printf("\n");
} /* end function displayBits
} */
} /* end main */
58

Example (II) // main.c


#include <stdio.h>

void displayBits( char*, unsigned ); // prototype

int main( void )


{
// displayBits.c unsigned x, y; // variable to hold user input
void displayBits( char* while(1){
heading, unsigned value )
{ printf( "Enter two unsigned integers in hex.: " );
unsigned c; // counter scanf( "%x %x", &x, &y );
unsigned displayMask = 1 << 31; // displayMask
displayBits( "x =", x );
printf( "%8s", heading );
displayBits( "y =", y );
for ( c = 1; c <= 32; c++ ) {// loop "~x
displayBits( through bits
=", ~x );
putchar( value & displayMask ? '1' : '0' );
displayBits( "~y =", ~y );
value <<= 1; // shift value left by 1
// output space per 8displayBits(
bits "x & y =", x & y);
if ( c % 8 == 0 ) putchar( ' ' );
displayBits( "x | y =", x | y);
} /* end for */ displayBits( "x ^ y =", x ^ y);
putchar( '\n' ); printf("\n");
} /* end function displayBits
} */
} /* end main */
59

Bitwise Assignment Operators

Bitwise assignment operators


&= Bitwise AND assignment operator.
|= Bitwise inclusive OR assignment operator.
^= Bitwise exclusive OR assignment operator.
<<= Left-shift assignment operator.
>>= Right-shift assignment operator.
60

Operator precedence and associativity

Operators Associativity Type

() [ ] . -> left to right highest

+ -- ++++ -- ! & * ~ sizeof (type) right to left unary

* / % left to right multiplicative

+ - left to right additive

<< >> left to right shiting

< <= > >= left to right relational

== != left to right equality

& left to right bitwise AND


61

Operator precedence and


associativity

Operators Associativity Type

() [ ] . -> left to right highest

+ -- ++++ -- ! & * ~ sizeof (type) right to left unary

* / % left to right multiplicative


Operators left to right
Associativity
additive
Type
+ -

<< >> ^ left to right leftshiting


to right bitwise OR

< <= > >= | left to right leftrelational


to right bitwise OR

== != && left to right leftequality


to right logical AND

& || left to right leftbitwise


to rightAND logical OR

?: right to left conditional

= += -= *= /= &= |= ^= <<= >>= %= right to left assignment

, left to right comma


62

Exercise: On-Off Bits Counting

Write a pair of functions, bitson and

bitsoff, that return the number of bits

that are on and off in a file. Use the

shorthand bit-manipulation operators.


63

Exercise: On-Off Bits Counting

on off
Example:
G 0100 0111 4 4
o 0110 1111 6 2
Boy.txt o 0110 1111 6 2
d 0110 0100 3 5
Good boy. 0010 0000 1 7
b 0110 0010 3 5
o 0110 1111 6 2
y 0111 1001 5 3
. 0010 1110 4 4
38 34
64

Exercise: On-Off Bits Counting

on off
Example:
G 01000111 4 4
o 01101111 6 2
Boy.txt o 01101111 6 2
d 01100100 3 5
Good boy. 00100000 1 7
b 0110 0010 3 5
o 0110 1111 6 2
There are 38 on-bits yand 34
0111 5 in file
off-bits
1001 3 Boy.txt.
. 0010 1110 4 4
38 34
65

Exercise: On-Off Bits Counting

01101110 01101110 01101110 01101110


mask & 10000000 & 01000000 & 00100000 & 00010000
00000000 01000000 00100000 00000000
On ✓ ✓
Off ✓ ✓
01101110 01101110 01101110 01101110
mask & 00001000 & 00000100 & 00000010 & 00000001
00001000 00000100 00000010 00000000
On ✓ ✓ ✓
Off ✓
66

Exercise: On-Off Bits Counting

▪ int bitson(char c)
returns number of on-bit in c

▪ int bitsoff(char c)
returns number of off-bit in c
67

C Program Design
C Structures, Unions, Bit
Manipulations and Enumerations

▪Bit Fields
68

Why Bit Fields?

sizeof(struct Card) = ?

struct Card {
unsigned face;
unsigned suit;
unsigned color;
};
69

Bit Fields
▪ When storage space is at a premium,
it may be necessary to pack several
objects into a single machine storage
unit.

suit

color face
70

Defining Bit Fields

struct BitCard {
unsigned face : 4;
unsigned suit : 2; sizeof(struct BitCard) = ?
unsigned color: 1;
};

suit

color face
71

Defining Bit Fields

struct BitCard {
unsigned face : 4;
unsigned suit : 2;
unsigned color: 1;
};

▪ Follow unsigned or int member with a


colon (:) and an integer constant
representing the width of the field.
72

Example

// Cards.h

// bitCard structure definition with bit fields


struct bitCard {
unsigned face : 4; // 4 bits; 0-15
unsigned suit : 2; // 2 bits; 0-3
unsigned color : 1; // 1 bit; 0-1
}; // end struct bitCard

typedef struct bitCard Card; // new type name for struct bitCard

void fillDeck( Card * const wDeck ); // prototype


void deal( const Card * const wDeck ); // prototype
73
// Cards.h

// bitCard structure definition with bit fields


struct bitCard {

Example unsigned face : 4; // 4 bits; 0-15


unsigned suit : 2; // 2 bits; 0-3
unsigned color : 1; // 1 bit; 0-1
}; // end struct bitCard

#include <stdio.h> typedef struct bitCard Card; // new type name for struct bitCard
#include "Cards.h" void fillDeck( Card * const wDeck ); // prototype
void fillDeck( Card * const wDeck ) void deal( const Card * const wDeck ); // prototype
{
int i; /* counter */

for ( i = 0; i <= 51; i++ ) {


wDeck[ i ].face = i % 13;
wDeck[ i ].suit = i / 13;
wDeck[ i ].color = i / 26;
}
}

void deal( const Card * const wDeck )


{
int k1; /* subscripts 0-25 */
int k2; /* subscripts 26-51 */

for ( k1 = 0, k2 = k1 + 26; k1 <= 25; k1++, k2++ ) {


printf( "Card:%3d Suit:%2d Color:%2d ",
wDeck[ k1 ].face, wDeck[ k1 ].suit, wDeck[ k1 ].color );
printf( "Card:%3d Suit:%2d Color:%2d\n",
wDeck[ k2 ].face, wDeck[ k2 ].suit, wDeck[ k2 ].color );
}
}
74
// Cards.h

// bitCard structure definition with bit fields


struct bitCard {

Example unsigned face : 4; // 4 bits; 0-15


unsigned suit : 2; // 2 bits; 0-3
unsigned color : 1; // 1 bit; 0-1
}; // end struct bitCard

#include <stdio.h> typedef struct bitCard Card; // new type name for struct bitCard
#include "Cards.h" void fillDeck( Card * const wDeck ); // prototype
void fillDeck( Card * const wDeck ) void deal( const Card * const wDeck ); // prototype
{
int i; /* counter */

//
for (main.c
i = 0; i <= 51; i++ ) {
wDeck[ i ].face = i % 13;
#include <stdio.h>
wDeck[ i ].suit = i / 13;
#include
}
"Cards.h“
wDeck[ i ].color = i / 26;

int main( void )


void deal( const Card * const wDeck )
{
{
int k1; /* subscripts 0-25 */
Card deck[ 52 ]; // create array of Cards
int k2; /* subscripts 26-51 */

for ( k1 = 0, k2 = k1 + 26; k1 <= 25; k1++, k2++ ) {


printf( "Card:%3d Suit:%2d Color:%2d ",
fillDeck( deck );
wDeck[ k1 ].face, wDeck[ k1 ].suit, wDeck[ k1 ].color );
deal( deck );
printf( "Card:%3d Suit:%2d Color:%2d\n",
wDeck[ k2 ].face, wDeck[ k2 ].suit, wDeck[ k2 ].color );
}
}
}
75
// Cards.h

// bitCard structure definition with bit fields


struct bitCard {

Example unsigned face : 4; // 4 bits; 0-15


unsigned suit : 2; // 2 bits; 0-3
unsigned color : 1; // 1 bit; 0-1
}; // end struct bitCard

typedef struct bitCard Card; // new type name for struct bitCard

void fillDeck( Card * const wDeck ); // prototype


void deal( const Card * const wDeck ); // prototype

// main.c
#include <stdio.h>
#include "Cards.h"
#include <stdio.h>
void fillDeck( Card * const wDeck ) #include "Cards.h“
{
int i; /* counter */
int main( void )
for ( i = 0; i <= 51; i++ ) { {
wDeck[ i ].face = i % 13; Card deck[ 52 ]; // create array of Cards
wDeck[ i ].suit = i / 13;
wDeck[ i ].color = i / 26;
} fillDeck( deck );
} deal( deck );
void deal( const Card * const wDeck )
}
{
int k1; /* subscripts 0-25 */
int k2; /* subscripts 26-51 */

for ( k1 = 0, k2 = k1 + 26; k1 <= 25; k1++, k2++ ) {


printf( "Card:%3d Suit:%2d Color:%2d ",
wDeck[ k1 ].face, wDeck[ k1 ].suit, wDeck[ k1 ].color );
printf( "Card:%3d Suit:%2d Color:%2d\n",
wDeck[ k2 ].face, wDeck[ k2 ].suit, wDeck[ k2 ].color );
}
}
76

More on Defining Bit Fields

▪ Unnamed bit field


– Field used as padding in the structure
– Nothing may be stored in the bits
struct UnNameExample {
unsigned a : 13;
unsigned : 3; // unnamed
unsigned b : 4;
};

– Unnamed bit field with zero width aligns next bit


field to a new storage unit boundary
77

Example

struct UnnameExample {
/* field 4 bits wide */
unsigned field1 :4;

/* unnamed 3 bit field


* unnamed fields allow for padding */
unsigned :3;

/* one-bit field
* can only be 0 or -1 in two's complement! */
signed field2 :1;

/* align next field on a storage unit */


unsigned :0;
unsigned field3 :6;
};
78

C Program Design
C Structures, Unions, Bit
Manipulations and Enumerations

▪Enumeration
Constants
79

Enumeration

enum Suits {CLUB, DIMOND, SPADE, HEART};

enum Months {JAN, FEB, MAR, APR, MAY, JUN,


JUL, AUG, SEP, OCT, NOV, DEC};

▪ Set of integer constants represented by


identifiers
▪ Enumeration constants are like symbolic constants
whose values are automatically set
▪ Need unique constant names
▪ Values start at 0 and are incremented by 1
▪ Values can be set explicitly with =
80

Enumeration
enum Suits {CLUB, DIMOND, SPADE, HEART};

enum Months {JAN,


{JAN=1,
FEB,
FEB,
MAR,
MAR,
APR,
APR,
MAY,
MAY,
JUN,
JUN,
JUL, AUG, SEP, OCT, NOV, DEC};

▪ Set of integer constants represented by


identifiers
▪ Enumeration constants are like symbolic
constants whose values are automatically
set
▪ Need unique constant names
▪ Values start at 0 and are incremented by
1
▪ Values can be set explicitly with =
81

Example

#include <stdio.h>

enum months {// enumeration constants represent months of the year


JAN = 1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC };

int main( void )


{
enum months month; // can contain any of the 12 months

const char *monthName[] = { "", "January", "February", "March",


"April", "May", "June", "July", "August", "September", "October",
"November", "December" };

for ( month = JAN; month <= DEC; month++ )


printf( "%2d%11s\n", month, monthName[ month ] );
}
82

Example

#include <stdio.h>

enum months {// enumeration constants represent months of the year


JAN = 1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC };

int main( void )


{
enum months month; // can contain any of the 12 months

const char *monthName[] = { "", "January", "February", "March",


"April", "May", "June", "July", "August", "September", "October",
"November", "December" };

for ( month = JAN; month <= DEC; month++ )


printf( "%2d%11s\n", month, monthName[ month ] );
}
83

More Examples

enum boolean { NO, YES };

enum escapes { BELL = '\a', BACKSPACE = '\b', TAB = '\t',


NEWLINE = '\n', VTAB = '\v', RETURN = '\r' };

enum Action {stop = 1, sit, stand = 2, walk, run}; // sit = stand =2

enum Action action = stop; // initializaiton

printf("%d\n", action + 2); // operation


Action--; // operation

You might also like