Last updated: July 1, 2021
 
red bullet point Home
red bullet point Grant
red bullet point Objective
red bullet point Strategy
red bullet point Timeline
red bullet point Project Team
red bullet point Technician
red bullet point Hardware
red bullet point Software
red bullet point Account
red bullet point Teaching Material
red bullet point Course / Lab
red bullet point Research
red bullet point Resource
red bullet point FAQ
red bullet point Vacancy
 
arrow HPCCC Website
 
Total Visitors since
28 Aug 2003: 424783
 
Valid XHTML 1.0!
 
Valid CSS!
Click here to download the PDF version

Chapter 10: Structures, Unions and Bit Manipulations
====================================================

Introduction
------------
* structure are collections of related variables under one name.
* structure may contain variables of many different data types - in
contrast to arrays that
contain only elements of the same data type.
* similar to record to be stored in files.
* pointers and structures facilitate the formation of more complex
data
structures such as linked lists, queues, stacks, and trees.

Definitions
-----------
* e.g.
struct card
{
char *face;
char *suit;
};
* "struct" - structure definition
* "card" - structure tag, not structure type
* the structure type is "struct card"
* "face" and "suit" - structure members: can be variable of basic data
types, arrays, pointers and other structures
* ";" is important to end the definition of structure
* a structure cannot contain an instance of itself, but a pointer can
be included
* structure variables:
struct card a, deck[52], *cPtr;
* or incorporated into the "struct card":
struct card
{
char *face;
char *suit;
} a, desk[52], *cPtr;

Initializing Structures
-----------------------
* using initializer lists as with arrays
* e.g.
struct card a = {"Three", "Hearts"};
* member "face" to "Three", member "suit" to "Hearts"

Accessing Members
-----------------
* structure member operator: "." - access via structure variable name
* e.g.
printf("%s", a.suit);
* structure pointer operator: "->" - access via structure pointer
* e.g.
printf("%s", cPtr->suit);
* equivalent to
printf("%s", (*cPtr).suit);
* e.g.
#include <stdio.h>

struct card
{
char *face;
char *suit;
}

main()
{
struct card a;
struct card *aPtr;

a.face = "Ace";
a.suit = "Spades";
aPtr = &a;
printf("%s%s%s\n%s%s%s\n%s%s%s\n",
a.face, " of ", a.suit,
aPtr->face, " of ", aPtr->suit,
(*aPtr).face, " of ", (*aPtr).suit);
}

Typedef
-------
* creating alias for defined data type
* e.g.
typedef struct card Card;
* "Card" is alias for type "struct card", so it is structure type, not
structure
tag
* e.g.
typedef struct
{
char *face;
char *suit;
} Card;
* structure variable:
Card a, deck[52], *cPtr;
* e.g.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

struct card
{
char *face;
char *suit;
};

typedef struct card Card;

void fillDeck(Card *, char *[], char *[]);
void shuffle(Card *);
void deal(Card *);

main()
{
Card deck[52];
char *face[] = {"A", "2", "3", "4", "5", "6", "7", "8", "9",
"10", "J", "Q", "K"};
char *suit[] = {"Hearts", "Diamonds", "Clubs", "Spades"};

srand(time(NULL));

fillDeck(deck, face, suit);
shuffle(deck);
deal(deck);
}

void fillDeck(Card *wDeck, char *wFace[], char *wSuit[])
{
int i;

for (i=0;i<52;i++)
{
wDeck[i].face = wFace[i%13];
wDeck[i].suit = wSuit[i/13];
}
}

void shuffle(Card *wDeck)
{
int i,j;
Card temp;

for (i=0;i<52;i++)
{
j = rand() % 52;
temp = wDeck[i];
wDeck[i] = wDeck[j];
wDeck[j] = temp;
}
}

void deal(Card *wDeck)
{
int i;

for (i=0;i<52;i++)
{
printf("%5s of %-8s%c", wDeck[i].face, wDeck[i].suit,
(i+1)%2?'\t':'\n');
}
}


Unions
------
* members share the same storage space
* for different situations in a program, some variables may not be
relevant, but other are
* a union shares the space instead of wasting storage on variables
that are not being used
* members can be of any type
* the number of bytes used to store a union must be at least enough to
hold the largest member
* only one member can be referenced at a time
* e.g.
union number
{
int x;
float y;
}

Initializing Union
------------------
* only with a value of the first union member
* e.g.
union number value = {10};

Accessing Members
-----------------
* same as structure
* e.g.
union number value;

value.x = 100;
printf("%d", value.x);

value.y = 100.0;
printf("%f", value.y);

Bitwise Operators
-----------------
* bit is the basic representation in computer
* can be either "0" or "1"
* "unsigned" are normally used

* left shift (<<)
e.g.
int y,x = 20; /* 20(10) = 00010100(2) */
y = x << 3; /* 160(10) = 10100000(2) */
* left shift can be used a "quick" multiplication of 2^n

* right shift (>>)
e.g.
int y,x = 20; /* 20(10) = 00010100(2) */
y = x >> 3; /* 2(10) = 00000010(2) */
* right shift can be used a "quick" (integer) division of 2^n

* bitwise AND (&)
Operands Result
0 0 0
0 1 0
1 0 0
1 1 1
* AND can be used as mask: to hide some bits in a value while
selecting other bits
* e.g.
#include <stdio.h>
void displayBits(unsigned value);

main()
{
unsigned x;

printf("Enter an unsigned integer: ");
scanf("%u", &x);
displayBits(x);
}

void displayBits(unsigned value)
{
unsigned c, displayMask = 1 << 15;

printf("%7u = ", value);
for (c=1;c<=16;c++)
{
putchar(value & displayMask ? '1' : '0');
value <<= 1;
if (c%8 == 0)
putchar(' ');
}

putchar('\n');
}

* bitwise OR (|)
Operands Result
0 0 0
0 1 1
1 0 1
1 1 1
* OR can be used to set specific bits to 1 in an operand

* NOT or complement(~)
Operands Result
0 1
1 0
* NOT can be used as taking the one's complement of the operand

* bitwise Exclusive OR (^)
Operands Result
0 0 0
0 1 1
1 0 1
1 1 0
* exclusive OR can be used as a encode and decode process since for
any bit-stream T,
T ^ K ^ K = T, where K is the key
* so E = T ^ K can be considered as the encoded bit-stream of T by key
K
* the decoder can recover the origin bit-stream T by
E ^ K = T
* this is basically the same process of encoder
e.g.
void encoder(char T[], char K[], char E[])
{
int i;

for (i=0;i<2;i++)
{
E[i] = T[i] ^ K[i];
}
}
* however, the encoded bit-stream, E, may not be represented by ASCII
* we can remedy the situation by padding zero in the beginning of each
of four bits and add 33 (the first character code of ASCII)
* e.g.
void padding(char E[], char PE[])
{
unsigned char lowmask = 15;
unsigned char highmask = 15 << 4;
int i;

for (i=0;i<2;i++)
{
PE[i*2] = (E[i] & lowmask) + 33;
PE[i*2+1] = ((E[i] & highmask) >> 4) + 33;
}

PE[i*2] = '\0';
}
* the encoding program is
* e.g.
#include <stdio.h>
void encoder(char T[], char K[], char E[]);
void padding(char E[], char PE[]);

main()
{
char Text[3], Key[3], EncodedText[3], OutText[5];

printf("Input the message: ");
scanf("%s",Text);
printf("Input the key: ");
scanf("%s",Key);

encoder(Text, Key, EncodedText);
padding(EncodedText, OutText);

printf("The secret message is: %s\n",OutText);
}
* each bitwise operator (except the bitwise complement operator) has a
corresponding assignment operator:
&=, |=, ^=, <<=, >>=


Enumeration Constants
---------------------
* An enumeration, introduced by the keyword "enum", is a set of
integer constants represented by identifiers.
* The values in an "enum" start with 0, unless specified otherwise,
and are incremented by 1.
* E.g.
enum months {JAN, FEB, MAR, APR, MAY, JUN, JUL,
AUG, SEP, OCT, NOV, DEC};
creates a new type, "enum months", in which the identifiers are set
automatically to the integer 0 to 11.
* To number the months 1 to 12, use
enum months {JAN = 1, FEB, MAR, APR, MAY, JUN, JUL,
AUG, SEP, OCT, NOV, DEC};
* E.g.
#include <stdio.h>

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

main()
{
enum months month;
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]);

return 0;
}


Exercise
========
1. Try to write the decoding program.
2. Try to decode "0&,&" by the key "00"







©2002-2024 Hong Kong Baptist University. All Rights Reserved.