On Thu, Jan 29, 2026 at 07:03:54PM +0100, Alejandro Colomar via Gcc wrote:
> I'm trying to understand why those two attributes exist.
>
> const
> Calls to functions whose
> return value is not affected
> by changes to the observable state of the program
> and that
> have no observable effects on such state
> other than to return a value
> may lend themselves to optimizations such as common
> subexpression elimination.
>
> pure
> Calls to functions that
> have no observable effects on the state of the program
> other than to return a value
> may lend themselves to optimizations such as common
> subexpression elimination.
>
> The difference seems to be only that pure functions can read memory
> through pointers. However, that is already obvious information from the
No, it can read anything in memory. That includes what pointer arguments
point to, but a lot more, anything reachable from the global state at the
point of the call, directly or indirectly.
int v;
int *p;
[[gnu::const]] int foo (int);
[[gnu::pure]] int bar (int);
int
baz (int)
{
int a = foo (42) + foo (42);
int b = 1;
int c = 1;
v++;
p = &b;
a += foo (42);
b++;
a += foo (42);
a += bar (42) + bar (42);
v++;
a += bar (42);
b++;
a += bar (42);
c++;
a += bar (42);
return a;
}
foo is const, so it can't read memory, so one can call foo just once and
multiply its result by 4.
While v++; (change to a global variable) or b++ (change to an automatic
variable that escaped) can change return value of bar, while c++; can't
(it has not escaped). So, one can do
a += bar (42) * 2;
v++;
a += bar (42);
a += bar (42) * 2;
c++;
return a;
but can't call bar fewer times than 3.
Jakub