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

Reply via email to