Chapter 16 - Structures
Download
Report
Transcript Chapter 16 - Structures
Chapter 16 Pointers and Structures
Pointers
What is the difference sptr and ssptr?
char* sptr[ ] = { "One", "Two", "Three" };
char** xsptr = sptr;
sptr
"One\0"
xsptr
"Two\0"
"Three\0"
BYU CS/ECEn 124
Structures
2
Concepts to Learn…
enum
Structures
typedef’s
structs in structs
Array of structs
struct Pointers
Union
Bit Fields
Dynamic Memory Allocation
Linked List
BYU CS/ECEn 124
Structures
3
enum
enum
Closely related to the #define preprocessor.
Define a list of aliases which represent integer
numbers.
The advantage of enum over #define is that it has
scope.
Two types:
Only visible within the block it was declared.
Named: enum greekType { ALPHA, BETA, GAMMA };
Unnamed: enum { HOMER, MARGE, BART, LISA };
Values start at zero, unless specified.
BYU CS/ECEn 124
Structures
4
enum
enum Examples
enum numbers { zero, one, two, three };
enum animals { cat=1, dog, cow=9, sheep, };
enum plants { grass, roses, cabbages, oaktree };
enum diseases { heart, skin, brain, circulatory };
enum quarks { charmed, strange, truth, beauty };
enum treasures { rubies, sapphires, gold, silver };
BYU CS/ECEn 124
Structures
5
Structures
Structures
A structure is a collection of variables, possibly of
different types, grouped together under a single
name (tag).
Structures help organize complicated data.
A structure must be defined prior to a structure
variable being declared.
Structure definitions include a tag, member
elements, and a variable definition.
The variable definition is optional.
BYU CS/ECEn 124
Structures
6
Structures
Structures
Structure definitions inform the compiler what the
structure will look like.
struct flightType
{
char flightNum[7];
int altitude;
int longitude;
int latitude;
int heading;
double airSpeed;
};
/* max 6 characters */
/* in meters */
/* in tenths of degrees */
/* in tenths of degrees */
/* in tenths of degrees */
/* in km/hr */
Structure definition does not allocate memory.
BYU CS/ECEn 124
Structures
7
Structures
Structures
To allocate memory for a struct, we declare a variable
using the new structure definition type.
struct flightType plane;
Structure members are laid
out in the order specified
by the definition.
Memory is now allocated,
and can be accessed as
individual members of this
variable with the “dot”
operator:
plane.altitude = 10000;
plane.heading = 800;
BYU CS/ECEn 124
plane.flightNum[0]
plane.flightNum[1]
plane.flightNum[2]
plane.flightNum[3]
plane.flightNum[4]
plane.flightNum[5]
plane.flightNum[6]
plane.altitude
plane.longitude
plane.latitude
plane.heading
plane.airspeed
Structures
0x0000(SP)
0x0002(SP)
0x0004(SP)
0x0006(SP)
0x0008(SP)
0x000a(SP)
0x000c(SP)
0x000e(SP)
0x0010(SP)
0x0012(SP)
0x0014(SP)
0x0016(SP)
8
Structures
Structure Example
#include <stdio.h>
#include <string.h>
Does not allocate
memory
struct person
{
char name[80];
int ssn;
};
struct person barney, fred;
Allocates two memory
structs
int main()
{
strcpy(barney.name, "Rubble, Barney");
barney.ssn = 555234561;
strcpy(fred.name, "Flintstone, Fred");
fred.ssn = 123451234;
printf(“\n%s %d", fred.name, fred.ssn);
printf(“\n%s %d", barney.name, barney.ssn);
}
BYU CS/ECEn 124
Structures
9
typedef’s
Typedef’s
Using Naturally Named Data Types
typedef’s
Why typedef?
You use variables with logical names.
Why not use data types with logical names?
Is an “int” 8-bits, 16-bits, 32-bits?
What’s a “long”?
Better question: why memorize it?
Most integer data types are platform dependent!!!
typedef’s make your code more portable.
Syntax:
typedef <type> <name>;
BYU CS/ECEn 124
Structures
11
typedef’s
How To Use typedef’s
1) Create a logical data type scheme.
A signed 8-bit number could be "s8"
An unsigned 16-bit number could be "u16"
2) Create a “typedef.h” file for each microcontroller
platform you use.
3) #include "typedef.h" in each of your files.
4) Use your new data type names.
typedef unsigned int u16;
typedef unsigned char u8;
u16 number;
BYU CS/ECEn 124
Structures
12
typedef’s
typedef.h Example
typedef
typedef
typedef
typedef
typedef
typedef
unsigned char u8;
signed char s8;
unsigned short u16;
signed short s16;
unsigned long u32;
signed long s32;
Replace:
unsigned char variable;
with:
u8 variable;
BYU CS/ECEn 124
Structures
13
typedef’s
typedef’s
Typedef declarations provide no additional
functionality.
Makes code more readable by giving applicationspecific names to variable types.
typedef int Color;
typedef struct flightType Flight;
Color pixels[500];
Flight plane1, plane2;
BYU CS/ECEn 124
Structures
14
structs in structs
Structures in Structures
One field of a struct can be another structure
struct addressStruct
{
char street[80];
char city[32];
int zipCode;
};
struct person
{
char initials[4];
int ssn;
int height;
int weight;
struct addressStruct address;
} tom;
person
initials
ssn
height
weight
address
street
city
int main()
{
tom.ssn = 555123456;
tom.weight = 150;
tom.address.zipCode = 84062;
…
BYU CS/ECEn 124
zipCode
Structures
15
Array of structs
Arrays of Structures
Can declare an array of structs:
typedef struct flightType
{
char flightNum[7];
int altitude;
int longitude;
int latitude;
int heading;
double airSpeed;
} Flight planes[100];
/* max 6 characters */
/* in meters */
/* in tenths of degrees */
/* in tenths of degrees */
/* in tenths of degrees */
/* in km/hr */
Each array element is a structure.
To access a member of a particular element in
the array you can use the “.” dot operator:
planes[34].altitude = 10000;
BYU CS/ECEn 124
Structures
16
struct Pointers
Pointers and Structures
Pointers can point at structures
struct person
{
char name[80];
int ssn;
} barney, *rubble;
How Much Memory?
int main()
Not Common
{
rubble = &barney;
strcpy((*rubble).name, “Rubble, Barney”);
(*rubble).ssn = 555234561;
printf(“%s %d\n”, (*rubble).name, (*rubble).ssn);
}
More Common
strcpy(rubble->name, “Rubble, Barney”);
rubble->ssn = 555234561;
printf(“%s %d\n”, rubble->name, rubble->ssn);
BYU CS/ECEn 124
Structures
17
struct Pointers
Pointers and Structures
Since pointers can point to structures, then it’s
easy to make links between structures.
struct person
{
char initials[2];
int ssn;
int height;
struct person *father;
struct person *mother;
};
tom
father
bill
/* Declare variables and initialize them at the same time */
struct person tom = { "tj", 555235512, 74, NULL, NULL };
struct person bill = { "wj", 351003232, 75, NULL, NULL };
struct person susan = { "sd", 980332153, 70, NULL, NULL };
int main()
{
/* Set tom's parents pointers */
tom.father = &bill;
tom.mother = &susan;
printf(“\nTom's mother's height is: %d in", tom.mother->height);
}
BYU CS/ECEn 124
Structures
mother
susan
tom is a struct and mother is a
field in that struct, thus
tom.mother is correct.
mother is a pointer to a struct
and thus mother->height is
correct.
Combine them for
tom.mother->height
18
Dynamic Memory Allocation
Memory Usage + Heaps
Variable memory is allocated in
three areas:
Global data section
Run-time stack
Dynamically allocated - heap
Global variables are allocated in
the global data section and are
accessible after declaration.
Local variables are allocated
during execution on the stack.
Dynamically allocated variables
are items created during runtime and are allocated on the
heap.
malloc() – allocates memory
free() – frees memory
BYU CS/ECEn 124
0x0000
0x0100
Global Data Section
Heap
SP
0x0600
Run-time stack
0x8000
PC
Program
(Flash)
0xffff
Structures
SFR’s
Interrupt Vectors
19
Dynamic Memory Allocation
Dynamic Memory Allocation
The sizeof() function determines how much
space is necessary for allocation.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *dynArray;
double *ddynArray;
/* Allocate space for 16 ints */
dynArray = (int *)malloc( 16 * sizeof(int) );
dynArray[6] = 65;
dynArray[12] = 2;
/* Allocate space for 20 doubles */
ddynArray = (double *)malloc( 20 * sizeof(double) );
}
BYU CS/ECEn 124
Structures
20
Dynamic Memory Allocation
Dynamic Memory Allocation
Dynamic memory allocation using malloc() is
used for many kinds of programs.
When data size is unknown or variable.
When building abstract structures like trees and linked
lists.
A NULL pointer returned from malloc() means it
failed and you are likely out of memory.
Dynamic allocation can be a source of bugs in C
code.
Memory leak - allocating memory and forgetting to free
it during program execution.
BYU CS/ECEn 124
Structures
21
Dynamic Memory Allocation
Dynamic Memory Allocation
Once allocated, the memory belongs to your
program until it terminates or is free()’d.
#include <stdio.h>
#include <stdlib.h>
main()
{
int *dynArray;
/* Allocate space for 16 ints */
dynArray = (int *)malloc( 16 * sizeof(int) );
dynArray[6] = 65;
dynArray[12] = 2;
doSomething( dynArray );
free( dynArray );
}
BYU CS/ECEn 124
Structures
22
Dynamic Memory Allocation
Pointers, Structures, & malloc()
Common to let malloc() create space for structures
struct person
{
char initials[2];
int ssn;
int height;
struct person *father;
struct person *mother;
} *tom, *bill, *susan;
int main()
{
tom = (struct person *)malloc( sizeof( struct person ) );
bill = (struct person *)malloc( sizeof( struct person ) );
susan = (struct person *)malloc( sizeof( struct person ) );
strncpy(tom->initials, "tj“, 2);
tom->ssn = 555235512;
tom->father = bill;
tom->mother = susan;
susan->height = 68;
/* Since tom is now a pointer, tom->mother->height is correct. */
printf(“\nTom's mother's height is: %d", tom->mother->height);
}
BYU CS/ECEn 124
Structures
23
union
union
A union is a value that may have any of
several representations or formats; or a
data structure that consists of a variable
which may hold such a value.
Unions are defined like structures
(structs), except that each data member
begins at the same location in memory.
The union object occupies as much space
as the largest member.
BYU CS/ECEn 124
Structures
24
union
union Example
#include <stdio.h>
union
{
char c;
int i;
} x;
int main()
{
int i;
char* c = &x.c;
x.i = 0x12345678;
printf("\ni = %08x\n", x.i);
for (i=0; i<4; i++) printf(" %02x", c[i]);
}
BYU CS/ECEn 124
Structures
25
union
union Example
union
{
char c;
int i;
float f;
double d;
} x;
x.c
x.i
x.f
x.d
=
=
=
=
char* c = &x.c;
int* i = &x.i;
float* f = &x.f;
double* d = &x.d;
printf("\nc
printf("\ni
printf("\nf
printf("\nd
'z';
5180;
3.14;
3.141592653589793;
BYU CS/ECEn 124
Structures
=
=
=
=
%p",
%p",
%p",
%p",
c);
i);
f);
d);
26
Bit Fields
Bit Fields
Allow specification of some very small objects of a given
number of bits in length.
Allow specification of fields within some externally
produced data files.
Can only be declared inside a structure or a union.
No guarantee of the ordering of fields within machine
words, so programs will be non-portable and compilerdependent.
Be careful using them. It can require a surprising
amount of run-time code to manipulate these things and
you can end up using more space than they save.
Bit fields do not have addresses—you can't have
pointers to them or arrays of them.
BYU CS/ECEn 124
Structures
27
Bit Fields
Bit Fields Example
#pragma pack(push,1)
typedef struct
{
unsigned short sec: 5;
unsigned short min: 6;
unsigned short hour: 5;
} FATTime;
#pragma pack(pop)
// BYTE align in memory (no padding)
#pragma pack(push,1)
typedef struct
{
unsigned short day: 5;
unsigned short month: 4;
unsigned short year: 7;
} FATDate;
#pragma pack(pop)
// BYTE align in memory (no padding)
BYU CS/ECEn 124
//
//
//
//
(total 16 bits--a unsigned short)
low-order 5 bits are the seconds
next 6 bits are the minutes
high-order 5 bits are the hour
// End of strict alignment
//
//
//
//
(total 16 bits--a unsigned short)
low-order 5 bits are the day
next 4 bits are the month
high-order 7 bits are the year
// End of strict alignment
Structures
28
Bit Fields
Bit Fields Example
typedef struct
{
FATTime time;
FATDate date;
} DirEntry;
void setTimeDate(DirEntry* dir)
{
time_t a;
struct tm *b;
time(&a);
b = localtime(&a);
dir->date.year = b->tm_year + 1900 - 1980;
dir->date.month = b->tm_mon;
dir->date.day = b->tm_wday;
dir->time.hour = b->tm_hour;
dir->time.min = b->tm_min;
dir->time.sec = b->tm_sec;
return;
} // end setDirTimeDate
BYU CS/ECEn 124
Structures
29
Linked List
Linked List Data Structure
A linked list is an collection of nodes, each of
which contains data and is connected using
pointers.
Each node points to the next node in the list.
The first node in the list is called the head.
The last node in the list is called the tail.
list
BYU CS/ECEn 124
50
75
Structures
99
NULL
30
Linked List
Simple Linked List Example
typedef struct element
{
int value;
struct element* next;
} Element;
Element *list;
list
Element* newElement(int v)
{
Element* tmp;
tmp = (Element*)malloc( sizeof(Element) );
tmp->value = v;
tmp->next = NULL;
return tmp;
}
50
75
99
NULL
int main()
{
/* Create linked list */
list = newElement(50);
list->next = newElement(75);
list->next->next = newElement(99);
}
BYU CS/ECEn 124
Structures
31
Linked List
Linked Lists vs Arrays
Advantages of a linked list
Dynamic size.
Easy to add additional nodes.
Easy to add or remove nodes from the middle of the
list by adding or redirecting links.
Advantages of an array
Can easily and quickly access arbitrary elements.
In a linked list in order to access the 5th element of the list you
must start at the head and follow the links through four other
nodes.
BYU CS/ECEn 124
Structures
32
Linked List
Linked List Creation
There are three steps required to create a linked
list
Allocate space for predefined structure.
Fill in the structure fields.
Link the structure into the list using pointers.
struct element* newElement(int v)
{
struct element* tmp;
tmp = (struct element*)malloc( sizeof(struct element) );
tmp->value = v;
tmp->next = NULL;
return tmp;
}
BYU CS/ECEn 124
Structures
33
Linked List
Pre-pending Items to a Linked List
/* Prepend an item to start of oldList, returning ptr to new list */
struct element* prepend(struct element* item, struct element* oldList)
{
item->next = oldList;
return item;
}
int main()
{
struct element* tmp;
list = newElement(45);
/* Prepend item to list */
tmp = newElement(30);
list = prepend(tmp, list);
/* Can prepend in one statement */
list = prepend(newElement(10), list);
printList(list);
}
list
BYU CS/ECEn 124
10
30
Structures
45
NULL
34
Linked List
Appending Items to a Linked List
/* Append an item to the end of oldList, returning ptr to list */
struct element* append(struct element* item, struct element* oldList)
{
struct element* tmp;
if (oldList == NULL) return item; /* oldList is empty */
tmp = oldList;
while (tmp->next != NULL) tmp = tmp->next;
tmp->next = item;
return oldList;
/* Search for end of list */
}
int main()
{
/* Append some items to end of list */
list = append(newElement(200), list);
list = append(newElement(201), list);
list = append(newElement(202), list);
printList(list);
}
list
BYU CS/ECEn 124
200
201
Structures
202
NULL
35
Linked List
Inserting Items into a Linked List
Search to find the proper location
link the new record into it’s proper place.
multiple cases to consider
list is empty
item belongs at front of existing list
item belongs somewhere in middle of existing list
item belongs at end of existing list
BYU CS/ECEn 124
Structures
36
Linked List
Inserting Items into a Linked List
struct element* insert(struct element* item, struct element* oldList)
{
struct element* tmp;
/* oldList is empty */
if (oldList == NULL) return item;
/* The new item goes first (pre-pend) */
if (item->value < oldList->value)
{ item->next = oldList;
return item;
}
/* Search for proper location */
tmp = oldList;
while ((tmp->next != NULL) && (tmp->next->value < item->value))
tmp = tmp->next;
item->next = tmp->next;
tmp->next = item;
return oldList;
}
BYU CS/ECEn 124
Structures
37
Linked List
Inserting Items into a Linked List
struct element* insert(struct element* item, struct element* oldList)
int main()
{
/* Insert some items into list */
list = insert(newElement(65), list);
list = insert(newElement(2), list);
list = insert(newElement(97), list);
list = insert(newElement(3), list);
list = insert(newElement(300), list);
printList(list);
}
list
2
BYU CS/ECEn 124
3
65
Structures
97
300
NULL
38
Linked List
Freeing Items in a Linked List
Elements in a linked list need to be “freed” or you
will have a memory leak.
When “freeing” items in a linked list, be careful
not to “saw off the limb you’re standing on”.
int main()
{
/* Create a linked list */
list = newElement(50);
list->next = newElement(75);
list->next->next = newElement(99);
free(list->next->next);
free(list->next);
free(list);
}
BYU CS/ECEn 124
Structures
39
Linked List
Printing Items in a Linked List
Use a temporary pointer to walk down the list
print values as you go
end up with a newline
void printList(struct element *ptr)
{
struct element *tmp;
tmp = ptr;
while (tmp != NULL)
{
printf(“ %d”, tmp->value);
tmp = tmp->next;
}
printf("\n");
}
BYU CS/ECEn 124
void printList(struct element *ptr)
{
if (ptr == NULL) printf("\n");
else
{
printf(" %d", ptr->value);
printList(ptr->next);
}
}
Structures
40
Example 2
Example 2
Thermostat temperature entry:
typedef unsigned int u16;
typedef unsigned char u8;
enum { SUN, MON, TUE, WED, THUR, FRI, SAT };
typedef struct Setting_struct
{ struct Setting_struct* link;
union
{ u16 time;
// day:hour/minute
struct
{ u8 day:3;
// day of week (0-6)
u8 hour:5;
// hour (0-23)
u8 minute;
// minute (0-59)
} times;
} date;
u8 high;
u8 low;
} Setting;
BYU CS/ECEn 124
Structures
link
date
high
low
NULL
41
Example 2
Create New Node
// create a new entry
Setting* newSetting(u8 day, u8 hour, u8 minute, u8 high, u8
low)
{
// malloc a new node
Setting* temp = (Setting*)malloc(sizeof(Setting));
// store entries
temp->date.times.day = day;
temp->date.times.hour = hour;
temp->date.times.minute = minute;
temp->high = high;
temp->low = low;
// null link
temp->link = NULL;
return temp;
} // end newSetting
BYU CS/ECEn 124
Structures
42
Example 2
main
enum { SUN=0, MON, TUE, WED, THUR, FRI, SAT };
int main()
{
Setting *list = NULL;
// Create linked list
list = newSetting(MON, 6, 30, 22<<1, 20<<1);
list->link = newSetting(WED, 20, 30, 17<<1, 15<<1);
list->link->link = newSetting(FRI, 8, 30, 22<<1, 20<<1);
list->link->link->link = newSetting(SAT, 18, 30, 20<<1, 18<<1);
}
0256
BYU CS/ECEn 124
025e
0266
026e
0000
1e31
1ea3
1e45
1e96
2c
22
2c
28
28
1e
28
24
Structures
43
Example 2
Insert Setting
Setting* insertSetting(Setting* setting, Setting* oldList)
{
Setting* temp;
if (oldList == NULL) return setting;
// oldList is empty
// The new item goes first (pre-pend)
if (setting->date.time < oldList->date.time)
{ setting->link = oldList;
return setting;
}
// Search for proper location
temp = oldList;
while (temp->link != NULL)
{ if (temp->date.time == setting->date.time)
{ // replace
temp->high = setting->high;
temp->low = setting->low;
free(setting);
return oldList;
}
if (temp->link->date.time > setting->date.time) break;
temp = temp->link;
// next
}
setting->link = temp->link;
// insert
temp->link = setting;
return oldList;
} // end insertSetting
BYU CS/ECEn 124
Structures
44
Example 2
Print Setting
char* days[] = { "Sun", "Mon", "Tue",
"Wed", "Thu", "Fri", "Sat" };
void printList(Setting* ptr)
{
Setting* temp;
temp = ptr;
while (temp != NULL)
{
printf("\n%s %02d:%02d %4.1f-%4.1f",
days[temp->date.times.day],
temp->date.times.hour,
temp->date.times.minute,
(float)temp->high / 2.0,
(float)temp->low / 2.0 );
temp = temp->link;
}
printf("\n");
} // end printList
BYU CS/ECEn 124
Structures
45
Example 2
Final Test
void main(void)
{
Setting *list = NULL;
eZ430X_init(CALDCO_1MHZ);
lcd_init();
lcd_backlight(ON);
// init board
// init LCD
// Create linked list
list = newSetting(MON, 6, 30, 22<<1, 20<<1);
list->link = newSetting(WED, 20, 30, 17<<1, 15<<1);
list->link->link = newSetting(FRI, 8, 30, 22<<1, 20<<1);
list->link->link->link = newSetting(SAT, 18, 30, 20<<1, 18<<1);
// Insert some items into list
list = insertSetting(newSetting(MON,
list = insertSetting(newSetting(SUN,
list = insertSetting(newSetting(TUE,
list = insertSetting(newSetting(MON,
list = insertSetting(newSetting(SAT,
}
6, 30, 24<<1, 18<<1), list);
6, 30, 22<<1, 20<<1), list);
6, 30, 22<<1, 20<<1), list);
6, 30, 20<<1, 10<<1), list);
20, 30, 22<<1, 20<<1), list);
printList(list);
return;
BYU CS/ECEn 124
Structures
46
BYU CS/ECEn 124
Structures
47