SYNOPSIS: unary-operator: . identifier
DESCRIPTION: - It is not an lvalue. - This means sizeof() and _Lengthof() cannot be applied to them.- This prevents ambiguity with a designator in an initializer-list within a nested braced-initializer.
- The type of a .identifier is always an incomplete type.
- This prevents circular dependencies involving sizeof() or _Lengthof().
- Shadowing rules apply.
- This prevents ambiguity.
EXAMPLES:
- Valid examples (libc):
int
strncmp(const char s1[.n],
const char s2[.n],
size_t n);
int
cacheflush(void addr[.nbytes],
int nbytes,
int cache);
long
mbind(void addr[.len],
unsigned long len,
int mode,
const unsigned long nodemask[(.maxnode + ULONG_WIDTH ‐ 1)
/ ULONG_WIDTH],
unsigned long maxnode, unsigned int flags);
void *
bsearch(const void key[.size],
const void base[.size * .nmemb],
size_t nmemb,
size_t size,
int (*compar)(const void [.size], const void [.size]));
- Valid examples (my own):
void
ustr2str(char dst[restrict .len + 1],
const char src[restrict .len],
size_t len);
char *
stpecpy(char dst[.end - .dst + 1],
char *restrict src,
char end[1]);
- Valid examples (from this thread):
-
struct s { int a; };
void f(int a, int b[((struct s) { .a = 1 }).a]);
Explanation:
- Because of shadowing rules, .a=1 refers to the struct member.
- Also, if .a referred to the parameter, it would be an rvalue, so
it wouldn't be valid to assign to it.
- (...).a refers to the struct member too, since otherwise an rvalue is
not expected there.
-
void foo(struct bar { int x; char c[.x] } a, int x);
Explanation:
- Because of shadowing rules, [.x] refers to the struct member.
-
struct bar { int y; };
void foo(char p[((struct bar){ .y = .x }).y], int x);
Explanation:
- .x unambiguously refers to the parameter.
- Undefined behavior:
-
struct bar { int y; };
void foo(char p[((struct bar){ .y = .y }).y], int y);
Explanation:
- Because of shadowing rules, =.y refers to the struct member.
- .y=.y means initialize the member with itself (uninitialized use).
- (...).y refers to the struct member, since otherwise an rvalue is not
expected there.
- Constraint violations:
-
void foo(char (*a)[sizeof *.b], char (*b)[sizeof *.a]);
Explanation:
- sizeof(*.b): Cannot get size of incomplete type.
- sizeof(*.a): Cannot get size of incomplete type.
-
void f(size_t s, int a[sizeof(1) = 1]);
Explanation:
- Cannot assign to rvalue.
-
void f(size_t s, int a[.s = 1]);
Explanation:
- Cannot assign to rvalue.
-
void f(size_t s, int a[sizeof(.s)]);
Explanation:
- sizeof(.s): Cannot get size of incomplete type.
Does this idea make sense to you?
Cheers,
Alex
--
<http://www.alejandro-colomar.es/>
OpenPGP_signature
Description: OpenPGP digital signature
