Concepts / Pointers and References to Structures

Pointers and References to Structures

A struct member can be accessed through the struct's name, a reference to the struct, or a pointer to the struct.

  • Programming
Interactive lab

Try it: Names and Objects

How Python variables are names bound to objects: assignment never copies, mutating a list is seen through every name that points at it, and ints are replaced rather than changed.

How it works

  1. name = object binds a name; b = a makes b point at the same object.
  2. Mutating a list (append, +=) changes the one shared object.
  3. a = a + [x] and y = y + 1 create NEW objects and re-point one name.
  4. Passing a list to a function passes the reference, so the function can change it.

Default run (7 steps): Two names, one list. Every name is a label that points at an object. … Printed: [1, 2, 3] / True

Simplified: Six fixed scripts on a tiny heap; you choose the values. Object numbers are illustrative, not real id() values.

Educational simulation

Loading the simulation…

Predicting Which Operator to Use

Suppose a function receives a Vector in three different forms: as a plain value, as a reference, and as a pointer. Each form gives the function a different kind of handle on the same struct. The function needs to read the member sz from each handle. The question is simple to state: given that you hold a Vector in one of these forms, how do you get at its sz member?

What do you think happens?

Of the three reads v.sz, rv.sz, and pv->sz, which one goes through a pointer, and which operator does it use?

  • v.sz, because the plain struct name is the pointer

  • rv.sz, because a reference is a kind of pointer

  • pv->sz, which uses the arrow operator

  • All three use pointers

Reveal answer
Answer:

pv->sz is the access that goes through a pointer, and it uses the arrow operator. v.sz and rv.sz both use the dot operator.

The first two reads use the dot because v is the struct itself and rv is a reference, which is another name for the same object. The third read uses the arrow because pv holds the location of a Vector rather than the Vector. Only the operator changes; the member name sz is written the same way after it.

Three Handles on the Same Member

A struct member can be accessed in three ways, depending on what you hold. You can access it through the struct's name, which means you have the struct object itself. You can access it through a reference to the struct, which is another name for the same object. Or you can access it through a pointer to the struct, which holds the location of the object rather than the object itself.

Definition

A reference to a struct is another name for the same object, so a member reached through a reference is the same member of the same object that the struct's name reaches. A pointer to a struct holds the location of the object rather than the object itself, so reaching a member through a pointer requires following that location first.

All three routes lead to the same member. The difference lies in how you reach the object, not in what the member is. The member sz is one int inside a Vector, and it is the same sz whether you arrive through the name, the reference, or the pointer.

vthe struct's nameVector objectthe struct itselfrva reference, another namefor the objectszthe same member in everycasepva pointer, holds a locationnames directlyis another name forleads to via stored locationmember
How the struct name, the reference, and the pointer all lead to the same sz member of one Vector object. The name and the reference reach the object directly, while the pointer reaches it by way of a stored location.

Tracing a Function That Takes Three Forms

The clearest way to see the three routes is to watch one function read sz through each of them. The example below is an illustrative reconstruction in the same shape as the trace this lesson uses. It takes a Vector by value, by reference, and by pointer, and it reads sz from each parameter into a separate int variable.

cpp
Notes on the code
  • The parameter v is a plain value, so v.sz uses the dot operator.
  • The parameter rv is a reference, which is another name for the caller's object, so rv.sz also uses the dot.
  • The parameter pv holds the location of a Vector, so pv->sz uses the arrow.
Worked example

Deciding Which Read Uses Which Operator

For each of the three reads in read_three, decide which operator is written and explain why that operator is valid for that handle.

  1. 1
    Read v.sz

    v is the Vector itself, held as a plain value. The struct name gives direct access to the object, so the dot operator is used.

  2. 2
    Read rv.sz

    rv is a reference, which is another name for the same object. Because it refers to the object directly, rv.sz is written with the dot, just like v.sz.

  3. 3
    Read pv->sz

    pv holds the location of a Vector rather than the Vector. The arrow operator follows that location to the object and then reaches sz, so pv->sz is written with the arrow.

  4. 4
    Compare the results

    The three int variables receive the value of the same member. The punctuation differs only because the handles differ.

Result

v.sz and rv.sz use the dot operator; pv->sz uses the arrow operator. All three read the same sz member of the Vector.

Notice that the function reads sz but does not change it. Each of these reads only copies a value into an int. Whether the caller's original struct is affected by the function depends on how the parameter was passed. The v parameter is a plain value, so the function works with its own copy of the struct, while rv and pv give the function access to the caller's object.

Choosing Between Dot and Arrow

The two operators correspond to the two kinds of handle. The dot operator is used when you access members through a struct's name or through a reference. The arrow operator is used when you access members through a pointer to a struct. The member name is written after the operator in both forms. Only the operator changes, and the operator tells you what kind of handle you are holding.

v.szstruct namepv->szpointerrv.szreference
Each access expression in the trace, grouped by the operator it uses. The dot reaches members from a name or reference, and the arrow reaches them from a pointer.

The arrow is a shorthand. Writing pv->sz means the same thing as first dereferencing the pointer to reach the object and then using the dot on it. The parenthesized form makes the dereference step visible, and it is the same member in both cases.

cpp
Notes on the code
  • The arrow hides the dereference step inside the operator.
  • The parentheses are required in the long form so that the dereference happens before the member is selected.

Reference Versus Pointer Side by Side

A reference and a pointer can both be used to reach the same struct's members, so it is easy to confuse them. The table below separates what each one is, how each one is accessed, and what each one can do.

FeatureReferencePointer
What it isAnother name for the same struct objectHolds the location of the struct object
How a member is reachedDot operator, as in rv.szArrow operator, as in pv->sz
Can it be changed to refer to something elseNo, once bound it stays the same objectYes, a pointer can be reassigned to point elsewhere
Needs following a location firstNoYes, the arrow follows the stored location

How a reference and a pointer differ when both reach the same struct's members

pvpointer holding a locationVector objectthe struct at that locationszmember read by pv->szpoints tomember
A pointer pv holds the location of a Vector. The arrow follows that location to the object, and then selects the member sz inside it.

Mistakes When Picking an Operator

  • Common mistake

    Using the dot on a pointer

    What it looks like

    pv.sz when pv is a pointer to a Vector

    Why it fails

    The dot operator is used for access through a name or a reference. A pointer holds a location, not the struct, so the dot does not reach the member through it.

    Do this instead

    Write pv->sz, because the arrow is the operator for access through a pointer to a struct.

  • Common mistake

    Using the arrow on a struct name or reference

    What it looks like

    v->sz when v is a Vector, or rv->sz when rv is a reference

    Why it fails

    The arrow is used for access through a pointer. v and rv are the struct and its alias, not a pointer to it, so the arrow does not match the handle held.

    Do this instead

    Write v.sz and rv.sz with the dot.

  • Common mistake

    Assuming all three reads are different members

    What it looks like

    Believing v.sz, rv.sz, and pv->sz each read a different field

    Why it fails

    All three routes lead to the same member. Only the way of reaching the object differs.

    Do this instead

    Read the expressions as three handles on one sz member, and pick the operator that matches the handle.

  • Common mistake

    Forgetting that the member name is written the same way after either operator

Trace Another Function

EASY

A function takes a Vector by reference as rv and a Vector by pointer as pv. It writes int a = rv.sz; and int b = pv->sz;. Without running the code, state which operator each line uses, and explain whether a and b read the same member. Then say what changes in your answer if the parameter is changed from a pointer to a plain value written as v, with the line int c = v.sz;.

Hints
  • Ask first what each handle holds: the object itself, another name for it, or a location.
  • Only the operator is different between rv.sz and pv->sz. The member name sz is the same.
  • A plain value v also holds the struct itself, so its member is reached with the dot.

Key Takeaways

  • A struct member can be reached through the struct's name, through a reference to the struct, or through a pointer to the struct, and all three routes lead to the same member.
  • The dot operator is used with a struct's name or a reference, as in v.sz and rv.sz, while the arrow operator is used with a pointer to a struct, as in pv->sz.
  • A reference is another name for the same object, while a pointer holds the location of the object, so reaching a member through a pointer requires following that location.
  • Pick the operator by asking what handle you hold: the struct or its reference takes the dot, and a pointer takes the arrow.
  • The arrow is shorthand for dereferencing the pointer and then using the dot, so pv->sz and (*pv).sz name the same member.

Related concepts

More concepts starting with P