csci 243 the mechanics of programming c: …tvf/csci243/notes/05-c-structs.pdfcsci 243 the mechanics...
Post on 27-Jun-2020
7 Views
Preview:
TRANSCRIPT
CSCI 243The Mechanics of Programming
Timothy Fossum (tvf@cs.rit.edu)
TVF / RIT 20195
C: Structures
TVF / RIT 20195 CS243: Structures
Aggregate Data Types
• Arrays• Homogeneous collections of elements
• Declare by specifying desired number of elements
• Accessed by position (index)
• Structures• Heterogeneous collections of elements
• Declare by listing the members in desired storage order
• Accessed by member name
TVF / RIT 20195 CS243: Structures
Structures
• Declaration syntax:
• tag – optional “name” for this structure
• Needed if you ever want to refer to this type later
• data_members – fields within structure
• Look like variable declarations
• Need one or more
• vars – optional variable declarations
struct [ tag ] { data_members} [ vars ];
TVF / RIT 20195 CS243: Structures
Structures
• Data members: essentially, variable prototypes• Any type that is fully known to the compiler
• Any legal variable name
• → no self-containing structures
• → no mutually-containing structures
• Member selection: . operator
• Initializable, assignable
TVF / RIT 20195 CS243: Structures
Struct Example – daytime.c (1/4)////// a simple program to illustrate basic structure declaration,/// initialization, and use////// it also illustrates (in passing) the dangers of using/// uninitialized local variables in functions///#include <stdio.h>
////// basic day + time structure///struct daytime {
int day;int month;int year;int hour;int minute;int second;
};
TVF / RIT 20195 CS243: Structures
Struct Example – daytime.c (2/4)////// print_date(date) print the supplied date/time information/// in yyyy/mm/dd hh:mm:ss format///void print_date( struct daytime date ) {
printf( "Day/time: %4d/%02d/%02d %02d:%02d:%02d\n",date.year, date.month, date.day,date.hour, date.minute, date.second );
}
TVF / RIT 20195 CS243: Structures
Struct Example – daytime.c (3/4)int main( void ) {
// declare a few initialized dates – the initializations// are done in the order the struct variables appearstruct daytime day1 = { 4, 7, 1779, 12, 00, 00 };struct daytime day2 = { 10, 9, 2013, 11, 54, 21 };
// another one, using “designated initializers” struct daytime day3 = { .hour = 15, .month = 8, .day = 26,
.year = 2013, .second = 0, .minute = 0 };
// declare a few uninitialized datesstruct daytime day4, day5, day6;
// print the first set of dates
puts( "Initialized dates:" );print_date( day1 );print_date( day2 );print_date( day3 );
TVF / RIT 20195 CS243: Structures
// just for fun, print the uninitialized datesputs( "\nUninitialized dates, before assignments:" );print_date( day4 );print_date( day5 );print_date( day6 );
// initialize (or assign) contents of the latter three dates // using “compound literals”
day4 = (struct daytime) { 13, 4, 2001, 3, 12, 17 };
// using compound literals and designated initializersday5 = (struct daytime) { .month = 11, .day = 8, .hour = 14,
.year = 2002, .second = 0, .minute = 0 };
// using structure assignment – this happens fieldbyfieldday6 = day1;
// print the new contents of these datesputs( "\n'Uninitialized' dates, after assignments:" );print_date( day4 ); print_date( day5 ); print_date( day6 );
return( 0 );}
Struct Example – daytime.c (4/4)
TVF / RIT 20195 CS243: Structures
Struct Example – Using daytime.c (1/2)
% gcc Wall std=c99 c daytime.c% gcc Wall std=c99 o daytime daytime.o
% ./daytimeInitialized dates:Day/time: 1779/07/04 12:00:00Day/time: 2013/09/10 11:54:21Day/time: 2013/08/26 15:00:00
Uninitialized dates, before assignments:Day/time: 134514688/1217433612/1075290180 134520820:01:134513405Day/time: 134520820/1048576/1217432604 134514721:1:1218948714Day/time: 1217224064/1218948571/1217433612 00:134514697:1217433612
'Uninitialized' dates, after assignments:Day/time: 2001/04/13 03:12:17Day/time: 2002/11/08 14:00:00Day/time: 1779/07/04 12:00:00
TVF / RIT 20195 CS243: Structures
Struct Example – Using daytime.c (2/2)
% ./daytimeInitialized dates:Day/time: 1779/07/04 12:00:00Day/time: 2013/09/10 11:54:21Day/time: 2013/08/26 15:00:00
Uninitialized dates, before assignments:Day/time: 134514688/1216970764/1075409076 134520820:01:134513405Day/time: 134520820/1048576/1216969756 134514721:1:1218485866Day/time: 1216761216/1218485723/1216970764 00:134514697:1216970764
'Uninitialized' dates, after assignments:Day/time: 2001/04/13 03:12:17Day/time: 2002/11/08 14:00:00Day/time: 1779/07/04 12:00:00
TVF / RIT 20195 CS243: Structures
Digression: C Standard Versions
• Case in point: gcc “-std=” options:• No standard specified: whatever the compiler does by default
• ansi: "ANSI C" -- typically, C89, the first ANSI C standard
• c89: same as "ANSI C"; a.k.a. "c90"
• gnu89: C89 with GNU extensions; a.k.a. "gnu90"
• c99: 1999 C standard
• gnu99: C99 with GNU extensions
• c11: 2011 C standard
• gnu11: C11 with GNU extensions
• Each has slightly different features
The nice thing about standards is that you have so many to choose from. – Andrew S. Tanenbaum
TVF / RIT 20195 CS243: Structures
Struct Example – months.c (1/3)//// a simple program that illustrates the declaration,// initialization, and use of a structure containing// data of more than one type//#include <stdio.h>
//// an example of a mixedcontent struct//// the 'name' field is 10 characters long because the longest// month name (September) is 9 characters, and we need to leave// room for the trailing NUL character//struct monthinfo {
int ndays; // number of days in the monthchar name[10]; // month name
};
TVF / RIT 20195 CS243: Structures
// an example of initializing an array of structures//struct monthinfo year1[12] = {
{ 31, "January" }, { 28, "February" }, { 31, "March" },{ 30, "April" }, { 31, "May" }, { 30, "June" },{ 31, "July" }, { 31, "August" }, { 30, "September" },{ 31, "October" }, { 30, "November" }, { 31, "December" }
};
//// another example, this time using [] designators// to initialize the array elements//struct monthinfo year2[12] = {
[1] = { 28, "February" }, [3] = { 30, "April" },[5] = { 30, "June" }, [10] = { 30, "November" },[8] = { 30, "September" }, [7] = { 31, "August" },[11] = { 31, "December" }, [0] = { 31, "January" },[6] = { 31, "July" }, [2] = { 31, "March" },[4] = { 31, "May" }, [9] = { 31, "October" }
};
Struct Example – months.c (2/3)
TVF / RIT 20195 CS243: Structures
//// print_year(year) print the contents of a year array//void print_year( struct monthinfo year[] ) {
for( int i = 0; i < 12; ++i ) {printf( "Month %2d: %2d days, name '%s'\n",
i, year[i].ndays, year[i].name );}
}
int main( void ) {
puts( "First year contains:" );print_year( year1 );
puts( "\nSecond year contains:" );print_year( year2 );
return( 0 );}
Struct Example – months.c (3/3)
TVF / RIT 20195 CS243: Structures
Struct Example – Using months.c
% gcc Wall std=c99 c months.c% gcc Wall std=c99 o months months.o
% ./monthsFirst year contains:Month 0: 31 days, name 'January'Month 1: 28 days, name 'February'Month 2: 31 days, name 'March'Month 3: 30 days, name 'April'Month 4: 31 days, name 'May'Month 5: 30 days, name 'June'Month 6: 31 days, name 'July'Month 7: 31 days, name 'August'Month 8: 30 days, name 'September'Month 9: 31 days, name 'October'Month 10: 30 days, name 'November'Month 11: 31 days, name 'December'
Second year contains:Month 0: 31 days, name 'January'Month 1: 28 days, name 'February'Month 2: 31 days, name 'March'Month 3: 30 days, name 'April'Month 4: 31 days, name 'May'Month 5: 30 days, name 'June'Month 6: 31 days, name 'July'Month 7: 31 days, name 'August'Month 8: 30 days, name 'September'Month 9: 31 days, name 'October'Month 10: 30 days, name 'November'Month 11: 31 days, name 'December'
TVF / RIT 20195 CS243: Structures
Digression: sizeof Operator
• Compile-time constant• Not evaluated at runtime!
• Like a #defined constant
• sizeof(x) – number of bytes occupied by “x”
• Can apply to types• # of bytes an instance of this type will occupy
• Can apply to variables• # of bytes this variable occupies
TVF / RIT 20195 CS243: Structures
Sizeof Example – chararrsize.c
/// file: chararraysize.c/// description: illustrate C 'string', a char array, and its size/// author: alp@cs.rit.edu/// gcc -std=c99 -Wall -Wextra -pedantic chararrsize.c -o chararrsize
#include <stdio.h>
int main(void) { char message[] = "ab";
printf("sizeof(char) = %ld\n", sizeof(char)); printf("sizeof(message) = %ld\n", sizeof(message)); return 0;}
% gcc -std=c99 -Wall -Wextra -pedantic chararrsize.c -o chararrsize% ./chararrsizesizeof(char) = 1sizeof(message) = 3
TVF / RIT 20195 CS243: Structures
Sizeof Example – sizes.c (1/2)
////// a simple program to illustrate the use of sizeof()///
#include <stdio.h>#include <string.h>
int main( void ) {int x;int y[10];char a[15];
printf( "sizeof(int) is %ld\n", sizeof(int) );printf( "sizeof(long) is %ld\n", sizeof(long) );
printf( "sizeof(x) is %ld\n", sizeof(x) );printf( "sizeof(y) is %ld\n", sizeof(y) );printf( "sizeof(y[0]) is %ld\n", sizeof(y[0]) );
TVF / RIT 20195 CS243: Structures
Sizeof Example – sizes.c (2/2)
strcpy( a, "Hello" );
// applied to a string - note the difference// between sizeof(string) and strlen(string)
printf( "sizeof(a) is %ld\n", sizeof(a) );printf( "length of a is %ld\n", strlen(a) );
return( 0 );}
% gcc -Wall -std=c99 -c -o sizes.o sizes.c% gcc -Wall -std=c99 -o sizes sizes.o% ./sizessizeof(int) is 4sizeof(long) is 8sizeof(x) is 4sizeof(y) is 40sizeof(y[0]) is 4sizeof(a) is 15length of a is 5
TVF / RIT 20195 CS243: Structures
Structure Layout in Memory
• Consider this structure:
• How much memory does it use?
struct stuff { char c1; int i1; char c2; int i2; char c3; double d1;};
TVF / RIT 20195 CS243: Structures
Struct Example – layout.c (1/3)////// a simple program that illustrates the layout of /// a structure with data members of varying types////// to compile: gcc -Wall -std=c99 -o layout layout.c//#include <stdio.h>
////// an example of a mixed-content struct///struct stuff { char c1; int i1; char c2; int i2; char c3; double d1;};
TVF / RIT 20195 CS243: Structures
Struct Example – layout.c (2/3)////// create a global instance///struct stuff data = { 'a', 42, 'b', 1776, 'c', 4.125};
int main( void ) {
// print the sizes of the individual fields
printf( "sizeof(c1)\t%ld\n", sizeof(data.c1) ); printf( "sizeof(i1)\t%ld\n", sizeof(data.i1) ); printf( "sizeof(c2)\t%ld\n", sizeof(data.c2) ); printf( "sizeof(i2)\t%ld\n", sizeof(data.i2) ); printf( "sizeof(c3)\t%ld\n", sizeof(data.c3) ); printf( "sizeof(d1)\t%ld\n", sizeof(data.d1) );
TVF / RIT 20195 CS243: Structures
Struct Example – layout.c (3/3)
// sum up the sizes
printf( "\nsum:\t%ld\n", sizeof(data.c1) + sizeof(data.i1) + sizeof(data.c2) + sizeof(data.i2) + sizeof(data.c3) + sizeof(data.d1) );
// now, print the size of the entire structure
printf( "\nsizeof(data)\t%ld\n", sizeof(data) );
return( 0 );}
TVF / RIT 20195 CS243: Structures
Struct Example – Using layout.c
• Results:
• But 19 is not equal to 32. Why?
% gcc -Wall -std=c99 -c layout.c% gcc -Wall -std=c99 -o layout layout.o
% ./layoutsizeof(c1) 1sizeof(i1) 4sizeof(c2) 1sizeof(i2) 4sizeof(c3) 1sizeof(d1) 8
sum: 19
sizeof(data) 32
TVF / RIT 20195 CS243: Structures
Structure Layout in Memory
• Some architectures require alignment of data items• MIPS, SPARC, M680x0 require it
• x86, x86_64, others don’t require alignment (but the compiler might still align items)
• Alignment is done to speed up data transfers
• Common rules:• char aligned on byte boundary
• int aligned on four-byte boundary
• double aligned on eight-byte boundary
• Compilers know this and insert “padding” bytes…
• …even if the hardware doesn’t require it
TVF / RIT 20195 CS243: Structures
Padding
• Our structure and its layout
struct stuff { char c1; // offset 0, size 1 int i1; // offset 4, size 4 char c2; // offset 8, size 1 int i2; // offset 12, size 4 char c3; // offset 16, size 1 double d1; // offset 24, size 8};
TVF / RIT 20195 CS243: Structures
Padding
• More memory-friendly layout:
• No padding → 19 bytes• 40.6% reduction in space usage
• Some compilers may add padding at end• Add one byte → 20 bytes total → 32.5% reduction
• Add 5 bytes → 24 bytes total → 25% reduction
struct stuff { double d1; int i1; int i2; char c1; char c2; char c3;};
top related