double
variable divided by an integer may yield unexpected results due to implicit type conversion.(type)variable
c
double one = 3.24;
if ((int)one / 3 == 1) {
printf(“true”);
} else {
printf(“false”);
}
typedef
typedef
keyword extends the C type system by declaring new types for the compiler to recognize and use.typedef [old type] [new type];
c
typedef unsigned char bitfield;
New types can be used anywhere built-in types are used.
Example:
typedef unsigned char bitfield;
bitfield myFunction(bitfield x, int y) {
bitfield z;
float a;
return ((bitfield)1);
}
The compiler treats the new type exactly as the old type (the new name acts simply as an alias for the original type).
A structure is an organized unit of data that is treated as a single entity (variable).
Can be defined like any other variable and has an implicit “type”.
Syntax:
struct {
[definition]
} [variable(s)];
where definition
is the layout of the structure, and variable(s)
are variables of the struct type.
struct {
char name[128]; // Make and model
int mileage; // The current mileage
} gremlin, cayman, cessna180, montauk;
The period "." is used to reference the fields of the struct.
strcpy(cayman.name, “My favorite car”); // strcpy will be covered later
cayman.mileage = 1240;
Allow associating integer values with names.
Syntax:
enum {
<ID1> = <value>,
<ID2> = <value>,
...
} variable;
Example:
enum {
SUNDAY = 0,
MONDAY = 1,
TUESDAY = 2,
WEDNESDAY = 3,
THURSDAY = 4,
FRIDAY = 5,
SATURDAY = 6
} daysOfWeek;
The <value>
part of the declaration is optional. If omitted, the compiler assigns integers to the values starting from 0.
Example:
enum {
SUNDAY,
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY
} daysOfWeek;
You can use the names in any place that you would use an integer.
int x = MONDAY;
int y = TUESDAY * FRIDAY;
if (day == SATURDAY) { ... }
int func(int x);
... func(TUESDAY);
struct {
enum {
AUTOMOTIVE = 0, // Automobile or equivalent
AERONAUTICAL = 1, // Airplane, rotorcraft, ..
MARINE = 2 // Boat or similar
} type;
char name[128]; // Make and model
int milage; // The current milage
} gremlin, cayman, cessna180, montauk;
// Example
cayman.type = AUTOMOTIVE;
if (cayman.type == AUTOMOTIVE) {
printf(“This is a car\n”);
}
struct {
enum {
AUTOMOTIVE = 0, // Automobile or equivalent
AERONAUTICAL = 1, // Airplane, rotorcraft, ..
MARINE = 2 // Boat or similar
} type;
char name[128]; // Make and model
int milage; // The current milage
struct {
int cylinders; // The number of cylinders
int horsepower; // The total horsepower
int hours_smoh; // Hours since last major overhaul
} engine; // Engine Specification/history
} gremlin, cayman, cessna180, montauk;
// Example
cayman.engine.cylinders = 6;
cayman.milage = 1240;
A union is a way to overlay different data structures over the same memory region.
It allows selectively interpreting the data in place.
Syntax:
union {
[definition]
} [variable(s)];
Example:
union {
char vin[17]; // Vehicle ID (car)
char tail_number[8]; // Tail number (airplane)
char hull_id[12]; // Hull ID (boat)
} vehicle_id; // The vehicle identifier
union {
char vin[17]; // Vehicle ID (car)
char tail_number[8]; // Tail number (airplane)
char hull_id[12]; // Hull ID (boat)
} vehicle_id; // The vehicle identifier
// Example
strcpy(vehicle_id.vin, “123456”); // strcpy will be covered later
printf(”%s\n”, vehicle_id.vin); // prints “123456”
vehicle_id.tail_number = “F-BOZQ”;
printf(”%s\n”, vehicle_id.vin); // prints “F-BOZQ”
printf(“Size:%lu\n”, sizeof(vehicle_id)); // prints “17”
Example of a complex structure using enum
, nested struct
, and union
.
struct {
enum {
AUTOMOTIVE = 0, // Automobile or equivalent
AERONAUTICAL = 1, // Airplane, rotorcraft, ..
MARINE = 2 // Boat or similar
} type;
char name[128]; // Make and model
int milage; // The current milage
struct {
int cylinders; // The number of cylinders
int horsepower; // The total horsepower
int hours_smoh; // Hours since last major overhaul
} engine; // Engine Specification/history
union {
char vin[17]; // Vehicle ID (car)
char tail_number[8]; // Tail number (airplane)
char hull_id[12]; // Hull ID (boat)
} vehicle_id; // The vehicle identifier
} gremlin, cayman, cessna180, montauk;
Using typedef
to define vehicle information.
typedef enum {
AUTOMOTIVE = 0, // Automobile or equivalent
AERONAUTICAL = 1, // Airplane, rotorcraft, ..
MARINE = 2 // Boat or similar
} VEHICLE_TYPE;
typedef struct {
int cylinders; // The number of cylinders
int horsepower; // The total horsepower
int hours_smoh; // Hours since last major overhaul
} ENGINE_INFO; // Engine specification/history
typedef union {
char vin[17]; // Vehicle ID (car)
char tail_number[8]; // Tail number (airplane)
char hull_id[12]; // Hull ID (boat)
} VEHICLE_IDENT; // The vehicle identifier
// Vehicle structure
typedef struct {
char name[128]; // Make and model
int milage; // The current milage
VEHICLE_TYPE type; // The type of vehicle
ENGINE_INFO engine; // Engine specification/history
VEHICLE_IDENT vehicle_id; // The vehicle identification
} VEHICLE;
// Now define the variables
VEHICLE gremlin, cayman, cessna180, montauk;
When handling a pointer to a struct, the fields are accessed with the ->
operator instead of the .
operator.
VEHICLE cayman;
VEHICLE *vehicle = &cayman;
strcpy(vehicle->name, “2013 Porsche Cayman S”);
vehicle->engine.cylinders = 6;
Consists of two symbols ?
and :
used as follows: expr1 ? expr2 : expr3
Read as "if expr1 then expr2 else expr3".
expr1
is evaluated first; if its value isn’t zero, the result is the evaluation of expr2
; else the result is the evaluation of expr3
.
Common usage in printf
.
int i = 1, j = 2, k;
k = i > j ? i : j;
k = (i >= 0 ? i : 0) + j;
if (i > j)
printf(“%d\n”, i);
else
printf(“%d\n”, i); //or printf(“%d\n”, i > j ? i : j);
Example of multiline print string and "?" expressions.
VEHICLE *vehicle = &cayman;
printf( "*** Vehicle Information **\n"
"Name : %s\n"
"Milage : %u\n"
"Vehicle type : %s\n"
"Cylinders : %u\n"
"Horsepower : %u hp\n"
"SMOH : %u hours\n"
"VIN : %s\n",
vehicle->name,
vehicle->milage,
(vehicle->type == AUTOMOTIVE) ? "car" : (vehicle->type == AERONAUTICAL) ? "airplane" : "boat",
vehicle->engine.cylinders,
vehicle->engine.horsepower,
vehicle->engine.hours_smoh,
(vehicle->type == AUTOMOTIVE) ? vehicle->vehicle_id.vin : (vehicle->type == AERONAUTICAL) ? vehicle->vehicle_id.tail_number
: vehicle->vehicle_id.hull_id );
#define MEM_OFFSET(a, b) ((unsigned long)&b)-((unsigned long)&a)
to print out the values of the fields.cayman
struct.You can assign the value of a struct from a struct of the same type; this copies the entire contents.
Example:
#include <stdio.h>
struct Point {
float x, y;
};
int main(int argc, char **argv) {
struct Point p1 = {0.0, 2.0};
struct Point p2 = {4.0, 6.0};
printf("p1: {%f,%f} p2: {%f,%f}\n", p1.x, p1.y, p2.x, p2.y);
p2 = p1;
printf("p1: {%f,%f} p2: {%f,%f}\n", p1.x, p1.y, p2.x, p2.y);
return 0;
}
You can return structs from functions.
Example (Complex Number):
```c
// a complex number is a + bi
typedef struct complex_st {
double real; // real component (i.e., a)
double imag; // imaginary component (i.e., b)
} Complex, *ComplexPtr;
Complex AddComplex(Complex x, Complex y) {
Complex retval;
retval.real = x.real + y.real;
retval.imag = x.imag + y.imag;
return retval; // returns a copy of retval
}
Complex MultiplyComplex(Complex x, Complex y) {
Complex retval;
retval.real = (x.real * y.real) - (x.imag * y.imag);
retval.imag = (x.imag * y.real) - (x.real * y.imag);
return retval;
}
```
Create numeric (integer) values that have a very specific width (in bits).
C supports this by identifying the bit width in declarations of integer fields.
Example:
struct vehicle_props {
uint32_t registered : 1;
uint32_t color_code : 8;
uint32_t doors : 3;
uint32_t year : 16;
} props;
props.registered = 1;
props.color_code = 14;
props.doors = 2;
props.doors = 9; // Legal, but out of range
props.year = 2013;
printf(“Size of props: %lu\n”, sizeof(props)); // Prints “4”