liveBook · Manning

Alias

As explained in Modern C

An alias is an alternative name by which an entity, command, parameter, or resource can be referred to.

Two pointers, one object?

Consider a function that saves `*a`, assigns `2 * saved` to `*b`, then returns `*a`. If `a` and `b` point to distinct objects, the returned value is the saved value. If both point to the same object, writing through `b` also changes what `a` sees, so the returned value is twice the saved value. Declaring `a` as `double const*` does not rule out that change through `b`. section 12.3

1   double blub(double const* a, double* b);
2
3   int main(void) {
4     double c = 35;
5     double d = 3.5;
6     printf("blub is %g\n", blub(&c, &d));
7     printf("after blub the sum is %g\n", c + d);
8   }1   double blub(double const* a, double* b) {
2     double myA = *a;
3     *b = 2*myA;
4     return *a;      // May be myA or 2*myA
5   }


!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":0,\"ch\":0},{\"line\":0,\"ch\":1}],[{\"line\":7,\"ch\":5},{\"line\":7,\"ch\":6}],[{\"line\":0,\"ch\":4},{\"line\":0,\"ch\":10}],[{\"line\":3,\"ch\":6},{\"line\":3,\"ch\":12}],[{\"line\":4,\"ch\":6},{\"line\":4,\"ch\":12}],[{\"line\":7,\"ch\":9},{\"line\":7,\"ch\":15}],[{\"line\":8,\"ch\":6},{\"line\":8,\"ch\":12}],[{\"line\":0,\"ch\":16},{\"line\":0,\"ch\":28}],[{\"line\":7,\"ch\":21},{\"line\":7,\"ch\":33}],[{\"line\":0,\"ch\":4},{\"line\":0,\"ch\":10}],[{\"line\":3,\"ch\":6},{\"line\":3,\"ch\":12}],[{\"line\":4,\"ch\":6},{\"line\":4,\"ch\":12}],[{\"line\":7,\"ch\":9},{\"line\":7,\"ch\":15}],[{\"line\":8,\"ch\":6},{\"line\":8,\"ch\":12}],[{\"line\":1,\"ch\":0},{\"line\":1,\"ch\":1}],[{\"line\":8,\"ch\":0},{\"line\":8,\"ch\":1}],[{\"line\":9,\"ch\":11},{\"line\":9,\"ch\":12}],[{\"line\":10,\"ch\":39},{\"line\":10,\"ch\":40}],[{\"line\":2,\"ch\":0},{\"line\":2,\"ch\":1}],[{\"line\":3,\"ch\":17},{\"line\":3,\"ch\":18}],[{\"line\":4,\"ch\":17},{\"line\":4,\"ch\":18}],[{\"line\":9,\"ch\":0},{\"line\":9,\"ch\":1}],[{\"line\":2,\"ch\":4},{\"line\":2,\"ch\":7}],[{\"line\":5,\"ch\":8},{\"line\":5,\"ch\":11}],[{\"line\":6,\"ch\":8},{\"line\":6,\"ch\":11}],[{\"line\":2,\"ch\":8},{\"line\":2,\"ch\":12}],[{\"line\":2,\"ch\":13},{\"line\":2,\"ch\":17}],[{\"line\":3,\"ch\":0},{\"line\":3,\"ch\":1}],[{\"line\":10,\"ch\":0},{\"line\":10,\"ch\":1}],[{\"line\":0,\"ch\":4},{\"line\":0,\"ch\":10}],[{\"line\":3,\"ch\":6},{\"line\":3,\"ch\":12}],[{\"line\":4,\"ch\":6},{\"line\":4,\"ch\":12}],[{\"line\":7,\"ch\":9},{\"line\":7,\"ch\":15}],[{\"line\":8,\"ch\":6},{\"line\":8,\"ch\":12}],[{\"line\":3,\"ch\":18},{\"line\":3,\"ch\":19}],[{\"line\":4,\"ch\":0},{\"line\":4,\"ch\":1}],[{\"line\":11,\"ch\":0},{\"line\":11,\"ch\":1}],[{\"line\":0,\"ch\":4},{\"line\":0,\"ch\":10}],[{\"line\":3,\"ch\":6},{\"line\":3,\"ch\":12}],[{\"line\":4,\"ch\":6},{\"line\":4,\"ch\":12}],[{\"line\":7,\"ch\":9},{\"line\":7,\"ch\":15}],[{\"line\":8,\"ch\":6},{\"line\":8,\"ch\":12}],[{\"line\":5,\"ch\":0},{\"line\":5,\"ch\":1}],[{\"line\":5,\"ch\":6},{\"line\":5,\"ch\":12}],[{\"line\":6,\"ch\":6},{\"line\":6,\"ch\":12}],[{\"line\":6,\"ch\":0},{\"line\":6,\"ch\":1}],[{\"line\":5,\"ch\":6},{\"line\":5,\"ch\":12}],[{\"line\":6,\"ch\":6},{\"line\":6,\"ch\":12}],[{\"line\":7,\"ch\":0},{\"line\":7,\"ch\":1}],[{\"line\":0,\"ch\":0},{\"line\":0,\"ch\":1}],[{\"line\":7,\"ch\":5},{\"line\":7,\"ch\":6}],[{\"line\":0,\"ch\":4},{\"line\":0,\"ch\":10}],[{\"line\":3,\"ch\":6},{\"line\":3,\"ch\":12}],[{\"line\":4,\"ch\":6},{\"line\":4,\"ch\":12}],[{\"line\":7,\"ch\":9},{\"line\":7,\"ch\":15}],[{\"line\":8,\"ch\":6},{\"line\":8,\"ch\":12}],[{\"line\":0,\"ch\":16},{\"line\":0,\"ch\":28}],[{\"line\":7,\"ch\":21},{\"line\":7,\"ch\":33}],[{\"line\":0,\"ch\":4},{\"line\":0,\"ch\":10}],[{\"line\":3,\"ch\":6},{\"line\":3,\"ch\":12}],[{\"line\":4,\"ch\":6},{\"line\":4,\"ch\":12}],[{\"line\":7,\"ch\":9},{\"line\":7,\"ch\":15}],[{\"line\":8,\"ch\":6},{\"line\":8,\"ch\":12}],[{\"line\":1,\"ch\":0},{\"line\":1,\"ch\":1}],[{\"line\":8,\"ch\":0},{\"line\":8,\"ch\":1}],[{\"line\":9,\"ch\":11},{\"line\":9,\"ch\":12}],[{\"line\":10,\"ch\":39},{\"line\":10,\"ch\":40}],[{\"line\":0,\"ch\":4},{\"line\":0,\"ch\":10}],[{\"line\":3,\"ch\":6},{\"line\":3,\"ch\":12}],[{\"line\":4,\"ch\":6},{\"line\":4,\"ch\":12}],[{\"line\":7,\"ch\":9},{\"line\":7,\"ch\":15}],[{\"line\":8,\"ch\":6},{\"line\":8,\"ch\":12}],[{\"line\":2,\"ch\":0},{\"line\":2,\"ch\":1}],[{\"line\":3,\"ch\":17},{\"line\":3,\"ch\":18}],[{\"line\":4,\"ch\":17},{\"line\":4,\"ch\":18}],[{\"line\":9,\"ch\":0},{\"line\":9,\"ch\":1}],[{\"line\":3,\"ch\":0},{\"line\":3,\"ch\":1}],[{\"line\":10,\"ch\":0},{\"line\":10,\"ch\":1}],[{\"line\":3,\"ch\":18},{\"line\":3,\"ch\":19}],[{\"line\":4,\"ch\":0},{\"line\":4,\"ch\":1}],[{\"line\":11,\"ch\":0},{\"line\":11,\"ch\":1}]]"}
!@%STYLE%@!

Compare the call with distinct addresses to the function body. Then consider a call passing the same address for both parameters: the assignment through `b` changes the value read through `a`. section 12.3

Aliasing means accessing the same object through different pointers. It matters both to the program’s result and to optimization: if a call might change an object through another pointer, the compiler cannot simply assume its earlier value still holds. section 12.3

TAKEAWAY — Treat possible aliases as part of a pointer interface’s contract.

  • Except for character types, only pointers of the same base type may alias. In the contrasting `size_t const*` and `double*` example, the write through the latter cannot change the object read through the former; defeating that assumption produces undefined behavior. section 12.3
  • Avoid taking a local variable’s address when it is unnecessary. The `&` operator is unavailable for a `register` variable, preventing that variable from aliasing; this approach is not useful for arrays. section 12.3 section 13.2.2
  • Use `restrict` only when callers can meet its access requirements. It helps specify aliasing properties of function parameters, but those requirements may not be checked at compile time. section 15.2 section 15.4
1   void* memcpy(void*restrict s1, void const*restrict s2,  size_t n);
2   void* memmove(void* s1, const void* s2, size_t n);


!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":0,\"ch\":0},{\"line\":0,\"ch\":1}],[{\"line\":1,\"ch\":25},{\"line\":1,\"ch\":26}],[{\"line\":0,\"ch\":4},{\"line\":0,\"ch\":8}],[{\"line\":1,\"ch\":4},{\"line\":1,\"ch\":8}],[{\"line\":0,\"ch\":10},{\"line\":0,\"ch\":16}],[{\"line\":0,\"ch\":4},{\"line\":0,\"ch\":8}],[{\"line\":1,\"ch\":4},{\"line\":1,\"ch\":8}],[{\"line\":0,\"ch\":22},{\"line\":0,\"ch\":30}],[{\"line\":0,\"ch\":35},{\"line\":0,\"ch\":45}],[{\"line\":0,\"ch\":22},{\"line\":0,\"ch\":30}],[{\"line\":0,\"ch\":60},{\"line\":0,\"ch\":66}],[{\"line\":1,\"ch\":44},{\"line\":1,\"ch\":50}],[{\"line\":0,\"ch\":56},{\"line\":0,\"ch\":57}],[{\"line\":1,\"ch\":0},{\"line\":1,\"ch\":1}],[{\"line\":0,\"ch\":4},{\"line\":0,\"ch\":8}],[{\"line\":1,\"ch\":4},{\"line\":1,\"ch\":8}],[{\"line\":1,\"ch\":10},{\"line\":1,\"ch\":17}],[{\"line\":0,\"ch\":4},{\"line\":0,\"ch\":8}],[{\"line\":1,\"ch\":4},{\"line\":1,\"ch\":8}],[{\"line\":1,\"ch\":28},{\"line\":1,\"ch\":38}],[{\"line\":0,\"ch\":60},{\"line\":0,\"ch\":66}],[{\"line\":1,\"ch\":44},{\"line\":1,\"ch\":50}]]"}
!@%STYLE%@!

The declarations contrast `memcpy`, whose source and destination objects must not overlap, with `memmove`, which permits equal pointers or overlapping objects. section 15.2

Character pointers need particular care: their aliasing exception makes exclusivity important in string-processing interfaces. Passing the same format string as both the `printf` format and its `%s` argument is identified here as a `restrict` violation with undefined behavior, even if an execution appears to print the expected result. Establish correctness before seeking a speedup, and measure any performance claim. section 15.2 section 15.4

How Modern C covers it

How deep it goes
Works through same-object and distinct-object pointer calls, then develops base-type and restrict rules without detailing optimizer internals.
Examples
Contrasts pointer-parameter functions, register locals, memcpy versus memmove, and a printf restrict violation.
What it assumes
Assumes familiarity with C pointers, addresses, and function calls while defining aliasing through a concrete pointer example.
What you can do after
Diagnose/debug with it when a pointer write may change another read, or when a restrict-qualified call may violate its contract.
How it connects
Connects aliasing to pointer types, character types, register storage, restrict qualifiers, and optimization.

Also explained in

Compare how 6 books explain alias →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Modern C. The section links point to the parts of the book it draws on.