Structures

advertisement
Structures
Structures allow you to group related information.
There are many forms of a struct statement:
// form #1 - defines a structType, but not a structure variable
// (i.e., it doesn't allocate memory for a variable.)
struct structType
{
attributeDef1;
attributeDef2;
…
};
// form #2 - defines a structure variable, allocating memory
struct
{
attributeDef1;
attributeDef2;
…
} structureVariable;
// form 1:
defined Employee as a struct type
struct Employee
{
char szSSN[10];
char szFullName[40];
double dHourlyRate;
};
// form 2:
defined a struct variable, allocating memory
struct
{
char szSSN[10];
char szFullName[40];
double dHourlyRate;
} employee;
// form 3: define a struct type (Employee) and a
// struct variable (employee)
struct Employee
{
char szSSN[10];
char szFullName[40];
double dHourlyRate;
// form #3 - defines a strucType and a structure variable, allocating memory
struct structType
{
attributeDef1;
attributeDef2;
…
} structureVariable;
} employee;
// form #4 - uses a previously defined structType to define a
// structure variable, allocating memory
struct structType structureVariable;
} ;
struct Employee employee, employeeMgr;
// form 4: define a struct type (Employee) and two
// struct variables (employee, employeeMgr)
struct Employee
{
char szSSN[10];
char szFullName[40];
double dHourlyRate;
We can also use typedefs to define structures.
typedef struct
{
attributeDef1;
attributeDef2;
…
} typedefStruct;
We can then use it in a declaration.
typedefStruct structureVariable;
Referencing an attribute of a structure variable uses dot notation.
structureVariable.attribute
Assignments also use the dot notation.
typedef struct
{
char szSSN[10];
char szFullName[40];
double dHourlyRate;
} Employee;
Employee employee, employeeMgr;
printf("SSN=%s, rate=%lf\n"
, employee.szSSN, employee.dHourlyRate);
printf("Manager is %s\n", employeeMgr.szFullName);
employee.dHourlyRate = 12.50;
strcpy(employee.szFullName, "Allen Wrench");
We can assign one structure variable into another when they are of the same
type.
sourceStructureVariable = targetStructureVariable;
This copies all of the attributes of the source into the target.
employeeMgr = employee;
When passing a structure variable to a function, C will make a copy of the
value which can be expensive. It is almost always better to pass its address.
calculateRaise (&employee);
Arrays of Structures
To declare an array of structures, specify the array size after the structure
variable.
struct structType structureVariable[arraySize];
typedefStruct structureVariable[arraySize];
void calculateRaise (Employee *pemployee)
{
pEmployee->dHourlyRate = pEmployee->dHourlyRate * 1.01;
}
Employee employeeM[20];
Structures as Attributes
In the attribute definition, use either a struct reference or typedef reference
// struct reference
struct structType
{
attributeDef1;
attributeDef2;
struct anotherStructType attributeStructVariable;
…
} structureVariable;
//typedef reference
struct structType
{
attributeDef1;
attributeDef2;
typedefStruct attributeStructVariable;
…
} structureVariable;
Initialization of Structures
When a structure variable is declared, it can be initialized by listing the values
in order.
If there are few values that need to be initialized, those can be listed using
{.variable1=value1, .variable2=value2, …}
Arrays of structures can be initialized. The attributes can be initialized in order
or you can surround an array item with braces.
As stated previously, a structure can be assigned into a structure of the same
type. It will copy the entire structure.
Slack Bytes (aligning numeric types)
What is the size of W2? iExemptionCnt=4, char = 1, dWithholding = 8; sum is
13
Why does sizeof(W2) give 16?
typedef struct
{
int iExemptionCnt;
char cFillingStatus;
double dWithholdExtra;
} W2;
//
//
//
//
//
Number of exemptions
M - Married, S - Single
X - married but filling
as single
extra amount to withhold
typedef struct
{
char szSSN[10];
char szFullName[40];
double dHourlyRate;
W2 w2;
} Employee;
Employee employee;
To reference dWithholdExtra, reference both structures:
dWithholding = dStandardWithholding
+ employee.w2.dWithholdExtra;
Employee employee =
{ "123456789", "Bill Board"
, 12.50, 1, 'M', 100.00 };
Employee employeeMgr =
{
.szFullName = "I. M. Boss"
, .dHourlyRate = 70.00
, .w2.dWithholdExtra = 300.00
};
Employee employeeM[5] =
{
{ "123456789", "Bill Board", 12.50, 1, 'M', 100.00 }
, { "222222222", "Peg Board", 15.00, 1, 'M', 150.00 }
, { "333333333", "Emory Board", 10.00, 0, 'S', 0.00 }
};
employeeMgr = employee;
employeeM[3] = employeeMgr;
sizeof(W2) gives 16
sizeof(Employee) gives 80
Example for W2:
What is the size of Employee?ssn= 10, name=40, dHourlyRate=8; W2 = ?
Why does sizeof(Employee) give 80?
It is because of slack bytes. It can be easier to read and write 4 byte
numeric values if their addresses are a multiple of 4. 8 byte numeric
values must be aligned to addresses that are a multiple of 8 for many
architectures.
Address
Variable
Size
1000
iExemptionCnt
4
cFillingStatus
1004
1
1008
dWithholding
8
So, there are 3 slack bytes between cFillingStatus and
dWithholding. sizeof(W2) = 4+1+3+8 = 16
Example for Employee:
Address
Variable
Size
szSSN
2000
10
szFullName
2010
40
2056
8
dHourlyRate
2060
16
W2
There are 6 slack bytes after szFullName.
sizeof(Employee) = 10+40+6+8+16 = 80
Download