Normally, a structure type needs to be defined before you use it. But there are times when you need to refer to a structure type before its definition. In that case, use a forward declaration of the type, which is just the type heading followed by a semicolon. For example,
struct Cell;is a forward declaration for type Cell.
Forward declarations have a rather severe limitation. A forward declaration of type Cell allows you to use type Cell* before you define type Cell. But it does not allow you to use type Cell without a * before the definition of type Cell.
A definition of structure type T can refer to type T* without a forward declaration. For example, type definition
struct ListCell { ListCell* next; int item; };indicates that a value of type ListCell has two fields, one of which is a pointer to a ListCell. We will see uses of this when looking at data structures. It will also help to illustrate structure copying, which is next.
A structure is treated like a value that occupies a given number of bytes. For example, suppose that PairOfInts is defined as follows.
struct PairOfInts { int a; int b; };Assuming that an int occupies 4 bytes, a value of type PairOfInts occupies 8 bytes, enough room for two ints. Statements
PairOfInts x, y; x.a = 20; x.b = 40; y = x;create two variables, x and y, of type PairOfInts. The next two statements initialize structure x. The last statement,
y = x;copies the structured value in x into y. You get an exact copy.
Structure copies are done the same way no matter how you indicate the structures. For example,
PairOfInts *p, *q; p = new PairOfInts; q = new PairOfInts; p->a = 20; p->b = 40; *q = *p;copies structure *p into *q.
The copy that you get from an assignment statement with a structure variable is a bit-for-bit copy, also called a shallow copy. To illustrate, let's create a small data structure out of two structures.
ListCell *A, *B;
B = new ListCell;
B->next = NULL;
B->item = 7;
A = new ListCell;
A->next = B;
A->item = 3;
The result looks like this, where each structure is shown with the next value on top and the item on the bottom.
Now let's illustrate copying.
ListCell *C, *D; C = A; D = new ListCell; *D = *A;The result looks like this.
Notice that C (a pointer variable) is an exact copy of A (a pointer variable), pointing to the same place. Pointer variable D has been made to point to a new ListCell, as is shown in the diagram. Assignment
*D = *A;copies the exact contents of *A into *D. The structure that B points to is not copied; only the pointer copied, making the next pointers in *A and *D point to the same place.
A deep copy does not do a bit-by-bit copy. Instead, when it sees a pointer in a structure, it does another structure copy. If statement *D = *A were replaced by a deep copy, we would expect to get the following.
Deep copies of structures that you create are not done automatically. If you want a deep copy you will need to write a function that performs the copy.
Why does the difference between shallow and deep copies matter to you? Generally, statement
X = Y;does a shallow copy. A common misconception is that it does a deep copy. That tends to lead to errors in programs. If you think that statement
*D = *A;does a deep copy, then you also believe that statement
D->next->item = 60;does not have any effect on the value of B->item. But looking at the diagram, you can see that pointer D->next points to the same structure as B, and changing one of them changes both.