CS1336, Structs, Unions and Enums

27
CS1336, Structs, Unions and Enums A lecture for you while I'm gone

description

CS1336, Structs, Unions and Enums. A lecture for you while I'm gone. Outline. Review of Array vs Struct Structs and memroy Union Enumerated values. Structs vs Arrays. What's an array? A bunch of items of the same type one after another in memory. - PowerPoint PPT Presentation

Transcript of CS1336, Structs, Unions and Enums

Page 1: CS1336, Structs, Unions and Enums

CS1336, Structs, Unions and Enums

A lecture for you while I'm gone

Page 2: CS1336, Structs, Unions and Enums

Outline

• Review of Array vs Struct

• Structs and memroy

• Union

• Enumerated values

Page 3: CS1336, Structs, Unions and Enums

Structs vs Arrays

• What's an array?– A bunch of items of the same type one after

another in memory.– Useful for keeping up with lists of similar,

related things– Each item is called an element– We get to each element using its integer

index.– There's little difference between an array and

a pointer to an array (but some difference)

Page 4: CS1336, Structs, Unions and Enums

Structs vs Arrays

• What's a struct– A bunch of items of (potentially) different types one

after another in memory.– Useful for keeping up with related, but potentially

dissimilar things– Items in a struct are called fields – We get to the fields of a struct using their names– Different syntax for a struct and a pointer to a struct:

• For a struct: a.color = red;• For a pointer to a struct: a->color = red;

Page 5: CS1336, Structs, Unions and Enums

Making Structure Instances

• We use the term, instance, to talk about a value of some struct type that's been allocated in memory.– We can make an instance of MyStruct on

the runtime stack with:# Goes away when the variable goes out of scope.struct MyStruct a;

– We can dynamically allocate an instance of MyStruct with:# doesn't go away until we free it.struct MyStruct *a = (struct MyStruct *)malloc( sizeof( struct MyStruct ) );

Page 6: CS1336, Structs, Unions and Enums

Structs and Binary I/O

• An instance of a struct occupies a contiguous region of memory

• We should be able to read an write the whole thing by writing its memory– struct MyStruct a;– fread( &a, sizeof( struct MyStruct ), 1, fp );– fwrite( &a, sizeof( struct MyStruct ), 1, fp );

• Just like with primitive types, the file here will contain binary data reflecting what the structure looks like in memory.

Page 7: CS1336, Structs, Unions and Enums

Structs and Binary I/O

• Binary I/O of entire structs is convenient, but it has some consequences– May be non-portable between different system

architectures because of byte ordering issues.– Depending on the compiler and the system

architecture, a struct instance may contain unused bytes called padding

– This padding wastes space in the file and, since it may depend on the compiler, it reduces portability

Page 8: CS1336, Structs, Unions and Enums

Padding in a Struct

• Most processors are more efficient if or require that you are careful about what kind memory address a value starts at.– For example, many systems expect an int to start at

an even byte boundary.• It would be ok for an int to be stored at addresses 0xffe8,

0xb43c2a or 0x3ccb0• It would not be ok for an int to be stored at address 0xff,

0xb43c2b or 0x9207– We say some systems require a value to be aligned in

memory– Alignment requirements typically only apply to

primitive types that are larger than a byte (int, foat, double, long int, short, etc.)

Page 9: CS1336, Structs, Unions and Enums

Padding in a Struct

• We say a value is naturally aligned if it starts at an address that's a multiple of its size.– For example, a 4-byte int would be naturally aligned if

it started at an address that's a multiple of 4– A 2-byte short would be naturally aligned if it started

on an even numbered address

• A compiler may align values in a struct either because the system requires it or because it will make the code faster.

Page 10: CS1336, Structs, Unions and Enums

Padding in a Struct

• Aligning the elements of a struct may leave spaces between them– Pretend this struct will be compiled on a system that

requires values larger than a byte to be even-byte aligned.

struct MyStruct {char a; /* 1-byte field. */int b; /* 4-byte field. */char c; /* 1-byte field. */short d; /* 2-byte field. */

}– The compiler will have to introduce a byte of padding

between after each char, just to make sure the next field is properly aligned.

Page 11: CS1336, Structs, Unions and Enums

Padding in a Struct

• Even-byte padding example, continued.– The struct will end up looking like this (the pad fields aren't really

there, I'm just showing where the compiler will put extra space):struct MyStruct {

char a; /* 1-byte field. */char pad; /* 1 byte of padding. */int b; /* 4-byte field. */char c; /* 1-byte field. */char pad; /* 1 byte of padding. */short d; /* 2-byte field. */

}– Because of the padding, sizeof will report 10 bytes for this struct

even though we only need to store 8 bytes of data.– On a system that required ints to be naturally aligned, this struct

would receive even more padding– For example, my laptop wants the b to be 4-byte aligned.

Page 12: CS1336, Structs, Unions and Enums

Structs and Padding

• We have some influence over how much padding occurs.– We could reorder fields to reduce padding.

struct MyStruct {int b; /* 4-byte field. */char a; /* 1-byte field. */char c; /* 1-byte field. */short d; /* 2-byte field. */

}– Here, no padding would be required on a system that

expected even-byte alignment.

Page 13: CS1336, Structs, Unions and Enums

Alternatives to Binary Struct I/O

• Reading and writing whole structure instances in binary is convenient, but it may waste space because of padding and may inhibit portability

• Still, lots of software systems do this kind of thing when these issues are not important

• We have some alternatives – Read and write each field one after another in some human

readable format• Could use printf/scanf• File would be human readable, which is nice• No extra padding will be required• Format would be very portable• However, a human readable format often requires more storage• Consider, the int 2458154370 is 10 ASCII characters, but the would

require only 4 bytes if written to a binary file.

Page 14: CS1336, Structs, Unions and Enums

Alternatives to Binary Struct I/O

• We have some alternatives, continued – Read and write each field one after another in

binary• Could use fread/fwrite for each field.• No extra padding will be required• Encoding of each field would typically be cheap (in

storage)• We would have to consider portability issues like

byte order for each field

Page 15: CS1336, Structs, Unions and Enums

Inspecting a Struct• We can use the sizeof() operator to find out how much memory a

struct instance requires• We can also do some pointer tricks to find out where each of its

fields start inside the instance (the offset for each field)– Pretend MyStruct is a struct– We can take a null pointer and pretend it's a pointer to a MyStruct

instance:(struct MyStruct *)NULL

– We can talk about a field of this MyStruct instance starting at memory address zero:((struct MyStruct *)NULL)->myField

– We can talk about the address of myField in a structure starting at memory address zero:&(((struct MyStruct *)NULL)->myField)

– If we cast this to an int, we can print out the offset of myField in an instance of MyStruct(int) &((struct MyStruct *)NULL)->myField

Page 16: CS1336, Structs, Unions and Enums

Union

• We have been thinking about how something like a struct instance is organized in memory.

• Now is a good time to think about union– Syntax for union is almost the same as struct:

union Example {int a;char b;double c;

}– However, instead of laying out its fields one after another in

memory, the union organizes them one over another in memory– Every union field starts at the same offset, just the start of the

structure– Memory size of the union is the size of it's largest field.– We can check using the trick we already figured out.(int) &(((union Example *)NULL)->b) == 0

Page 17: CS1336, Structs, Unions and Enums

Why use Union

• Union has a strange behavior and it's not used as much as struct

• It is useful when:– You don't know you will sometimes have to store a

value of one type and sometimes a value of a different type

– but you won't have to store both values at the same time

– You want to save memory by using the same memory to store both.

• Union really just gives us multiple ways of looking at or using the same memory

Page 18: CS1336, Structs, Unions and Enums

A Use for Union• Consider the union:

union Integer { int ival; unsigned char bval[ sizeof( int ) ];};

• Here, the int and character arrays are really different ways to get to the same memory.

• This would make it easy to work with an int stored in ival either as a whole int or a byte at a time. /* Put a value into our integer. */ union Integer i; i.ival = 0xffb0; /* Extract its representation a byte at a time. */ int j; for ( j = 0; j < sizeof( int ); j++ ) printf( "%d ", i.bval[ j ] ); printf( "\n" );

Page 19: CS1336, Structs, Unions and Enums

Union inside Struct• Union is most often used inside a struct• This gives us a way to make a struct that be used to hold similar, but

different things• The following struct can be used to store either an int, a float and a double

or an int, a float and a short string.

struct MyVariantStruct { /* First two fields are always there. */ int a; float b; /* Variant part of the struct, can contain a double

or a short string. */ union VPart {

double c;char d[ 10 ];

} vpart;};

Page 20: CS1336, Structs, Unions and Enums

Union in a Struct• Syntax for this example is a little difficult• Inside the structure, we are defining a new union type called VPart.• At the end of the VPart definition, we add a new field of type VPart to the

struct, the field is called vpart• We can get to the fields of a MyVariantStruct instance just like you would

expect:

MyVariantStruct bob;bob.a = 20;bob.b = -283.6;/* Get to the union in bob and use its double field */bob.vpart.c = 3.1415;/* Get to the union in bob and use its character array field. This will overwrite what we just stored

in c. */strcpy( bob.vpart.d, "Hello!" );

• Consider, what would the size of MyVariantStruct be?

Page 21: CS1336, Structs, Unions and Enums

Anonymous Unions

• Union inside a struct is so common, we can use an abbreviated syntax for it.

• We can leave out the type name and the field name for the union inside our struct.struct MyVariantStruct { /* First two fields are always there. */ int a; float b; /* This is called an anonymous union */ union {

double c;char d[ 10 ];

};};

Page 22: CS1336, Structs, Unions and Enums

Anonymous Unions

• Now, we can use shorter syntax to get to the variant part of the structureMyVariantStruct bob;bob.a = 20;bob.b = -283.6;/* Write to the double field in bob's union */bob.c = 3.1415;/* Write to the character field in bob's union */strcpy( bob.d, "Hello!" );

Page 23: CS1336, Structs, Unions and Enums

Enumerated Types• You probably saw this in CS1, but it's on my list of stuff to teach.• An enumerated type is a way to make your own type containing a

specific set of values that you pick• An enumerated type is a lot like an int, and is even represented as

numbers in the compiled code• Example:

/* Define a new type called Color, with 7 colors as its only legal values. */enum Color { RED, ORANGE, YELLOW, GREEN,

BLUE, INDIGO, VIOLET };

/* Show off how we can use this type. */Color favorite = GREEN;if ( favorite != RED ) printf( "You have the wrong favorite color\n" );

• Values in an enumeration are usually given in all capitals, since they are like constants

• Values in an enumeration automatically promote to int

Page 24: CS1336, Structs, Unions and Enums

Enumerated Types

• Enum is represented as a number– By default, the first value in the definition (RED on the

previous slide) gets represented by zero.– Subsequent values in the enumeration are

represented by the next integer– So, YELLOW is represented by 2 and VIOLET is

represented by 6– You will see this number if you try to print a variable of

some enum type:printf( "%d\n", favorite );

– You can assign directly from an int (requires a type cast in C++)enum Color favorite = (enum Color) 3;

Page 25: CS1336, Structs, Unions and Enums

Fun with Enum

• You can pick the numbers used to represent values in your enumerated typeenum Color { RED = 1, ORANGE = 3, VIOLET = 6, BLUE, GREEN = 0, PURPLE };

• Here, BLUE will be represented by 7 since enum values are get the value one after their predecessor.

• Notice that PURPLE and RED will both be represented by 1. This will make them indistinguishable. Here, they are just two names for the same value.

Page 26: CS1336, Structs, Unions and Enums

Uses for Enum

• It's unfortunate that enumerated values print as numbers rather than their names.

• Likewise, the user can't type the name of an enumerated value as program input

• The way you should think of enum is as a mechanism for making your program more readable and for using a more specific type than int where possible

• Using an enumerated type where you can may make it easier for someone else to understand your program

• An enumerated type as a function parameter makes it easier to make sure you have called the function with a meaningful value

Page 27: CS1336, Structs, Unions and Enums

Examples of Enum Use• Enum can be particularly appropriate for values that will govern a

switch statement:

enum Direction { NORTH, SOUTH, EAST, WEST };…void move( Direction d ) { switch ( d ) {

case NORTH: /* Do something useful. */ break;case SOUTH: /* Do something else. */ break;...

}}