int
,double
,char
, etc.- Pointers
- A contiguous sequence of objects of the same type
- A compound type is a datatype that we define in our code as containing other primitive or compound data types
- A compound object made up of member subobjects
- The members and their types are defined by a struct or a class
- The simplest compound type in C and C++ is the struct
- Elements in a struct are laid out in memory in the order listed
struct Triangle
{
double a, b, c; // Edges
};
- This struct contains a triangle's edge lengths
- It declares a new type
Triangle
but does not define any variables of that type - A common convention is to capitalize the names of structs
struct Triangle
{
double a, b, c; // Edges
char name[ 100 ];
int id;
};
- A struct can contain different types
- This struct contains three doubles for the edges, a 100-character C-string and an int
struct Triangle
{
double a, b, c; // Edges
};
int main( )
{
Triangle t;
}
The values of a
, b
, and c
are undefined
Members can be intialized with dot notation or with a list
struct Triangle
{
double a, b, c; // Edges
};
int main( )
{
Triangle t;
t.a = 3;
t.b = 4;
t.c = 5;
}
struct Triangle
{
double a, b, c; // Edges
};
int main( )
{
Triangle t = { 3, 4, 5 };
}
struct Triangle
{
double a, b, c; // Edges
};
int main( )
{
Triangle t = { 3, 4, 5 };
Triangle t2 = t1;
}
Passing structs by value is inefficient, as it means you are copying the entire struct onto the stack.
It's better to either:
struct Triangle
{
double a, b, c; // Edges
};
double TriangleArea( Triangle *t )
{
double s = ( t->a + t->b + t->c ) / 2;
double area = sqrt( s*( s - t->a )*( s - t->b )*( s - t->c ) );
return area;
}
int main( )
{
Triangle t = { 3, 4, 5 };
cout << "area = " << TriangleArea( &t ) << endl;
}
The following pointer dereference notations are identical
(*t).a
t->a
However, the following notation does not work
*t.a
This does not work, because the dot takes precedence over the dereference, so the a
component is being taken before t
is referenced
struct Triangle
{
double a, b, c; // Edges
};
double TriangleArea( Triangle &t )
{
double s = ( t.a + t.b + t.c ) / 2;
double area = sqrt( s*( s - t.a )*( s - t.b )*( s - t.c ) );
return area;
}
int main( )
{
Triangle t = { 3, 4, 5 };
cout << "area = " << TriangleArea( t ) << endl;
}
- const means do not modify in this scope
const int MaxSize = 10;
int main( )
{
MaxSize = 7; // Error: MaxSize
// is read-only
char str[ MaxSize ] = "hello"; // OK
}
The value of the pointer and the value of the object to which the pointer points can be made constant
const T *p; // "T" (the pointed-to object)
// cannot be changed
T *const p; // "p" (the pointer) cannot be
// changed
const T *const p; // neither can be changed
T
is the type, such as int
, and p
is the pointer, such as a variable name
The following parameters are identical
int strlen( char const *s )
{
s += 1; //OK
*s = 'j'; //error
//...
}
int strlen( const char *s )
{
s += 1; //OK
*s = 'j'; //error
//...
}
An error is thrown, because the value of the object to which the pointer points is constant, and cannot be modified.
The value of the pointer, however, is not constant, and is open to modification.
int strlen( char *const s )
{
s += 1; //error
*s = 'j'; //OK
//...
}
An error is thrown, because the value of the pointer is constant, and cannot be modified.
The value of the object to which the pointer points, however, is not constant, and is open to modification.
int strlen( const char *const s )
{
s += 1; //error
*s = 'j'; //error
//...
}
Both the pointer and the object are constant in this situation, so changes to either will result in an error.
int a[ 3 ] = { 1, 2, 3 };
int *p = a;
int &a_ref = a[ 0 ];
struct x
{
int i;
char c;
}
Types are composable. Once you have declared a type struct x, that type can be used to define a pointer to struct x, an array of struct x, or even a struct that contains a struct x.
struct | array |
---|---|
struct Triangle { /*...*/ }; |
double edges[ 3 ]; |
Stores group of data | Stores group of data |
Heterogeneous - Different types | Homogeneous - All the same type |
Access by name | Access by index |
Default pass-by-value | Default pass-by-pointer |
Creates a custom type | Does not create a new type |