All 3 questions pretty much boil down to the same special rule: a pointer to struct may alias with a pointer to one of the types that is also a member of that struct. Meaning that restrict might improve performance a tiny bit, as the compiler no longer needs to assume that a pointer to int might modify some int member of the struct.
Example:
typedef struct
{
int a;
double b;
} struct_t;
void func (struct_t* s, int* i)
{
s->a++;
*i = 123;
printf("%d\n", s->a);
}
On clang 20.1 x86 -O3 I get this code generation:
func:
inc dword ptr [rdi]
mov dword ptr [rsi], 123
mov esi, dword ptr [rdi]
lea rdi, [rip + .L.str]
xor eax, eax
jmp printf@PLT
As in, a is incremented by 1 in-place, then later after *i has been modified, it reloads a from memory esi, dword ptr [rdi]. Because it can't assume that writing to *i didn't change a.
After changing to struct_t* restrict s:
func:
mov eax, dword ptr [rdi]
inc eax
mov dword ptr [rdi], eax
mov dword ptr [rsi], 123
lea rdi, [rip + .L.str]
mov esi, eax
xor eax, eax
jmp printf@PLT
This isn't obviously much faster, but now the inc is carried out on a register instead of a read-modify-write in RAM. The compiler doesn't have to assume that the 123 write affected a. It stores the new value of a back in RAM before writing 123 to i. And then later uses the new value of a still kept in a register to pass to printf mov esi, eax, without reloading it from RAM.