S
Shao Miller
A proposal for an amendment of C99's section 6.5.3.2 follows:
--- AMENDMENT ---
6.5.3.2 Address and indirection operators
Constraints
1 <NO AMENDMENT PROPOSED>
2 The operand of the unary * operator shall have pointer type. <NO
AMENDMENT PROPOSED>
3 Except when the unary * operator and its operand are not evaluated,
the operand of the unary * operator shall not be a null pointer
constant expression, or such an expression cast to any pointer type.
4 Except when the unary * operator and its operand are together the
operand to the unary & operator, the operand of the unary * operator
shall not be a pointer type pointing to an incomplete type.
Semantics
5 <AMENDED FROM POINT 3 TO 5. NO OTHER AMENDMENT PROPOSED>
6 <AMENDED FROM POINT 4 TO 6> The unary * operator denotes
indirection. If the operand points to a function, the result is a
function designator; if it points to an object, the result is an
lvalue designating the object. If the operand has type ``pointer to
type'', the result has type ``type''. If the operand is an invalid
value, the behavior of the unary * operator is undefined.87)
Forward references: storage-class specifiers (6.7.1), structure and
union specifiers
(6.7.2.1). <NO AMENDMENT PROPOSED>
.... ... ... <NO AMENDMENTS PROPOSED BEFORE FOOTNOTE 87>
87) Thus, &*E is equivalent to E (even if E is a null pointer), and
&(E1[E2]) to ((E1)+(E2)). It is always true that if E is a function
designator or an lvalue that is a valid operand of the unary &
operator, *&E is a function designator or an lvalue equal to E. If *P
is an lvalue and T is the name of an object pointer type, *(T)P is an
lvalue that has a type compatible with that to which T points.
Among the invalid values for dereferencing a pointer by the unary *
operator are a null pointer, an address inappropriately aligned for
the type of object pointed to, and the address of an object after the
end of its lifetime.
--- INTENDED AUDIENCE ---
The intended audience for this proposal are:
- The ISO/IEC JTC1/SC22/WG14 international standardization working
group for the programming language C
- C implementors (developers of C implementations with conformance to
the standard in mind)
- C programmers
--- RATIONALE ---
The previous text in the C99 international standard allowed for
certain language constructs to lead to undefined behaviour which a C
implementation might choose to define. This amendment encourages
implementators and programmers to avoid allowance of and usage of
these constructs, respectively, to help to maximize the portability of
a C program across different implementations.
These language constructs claimed above as leading to undefined
behaviour are perhaps rarely explored or used historically, so there
should be little impact to implementations beyond two additional
constraint violations to diagnose.
--- IMPLICATIONS FOR C IMPLEMENTORS ---
The amendment's constraint 3 requires a diagnostic message given code
like:
int main(void) {
int i = *(int *)0;
return 0;
}
because it is known at translation-time (pre-evaluation) that this is
an attempt to access an object pointed to by a null pointer, which is
erroneous.
The amendment still allows for:
#include <stddef.h>
size_t sz = sizeof *(int *)0;
and:
int *ip = &*(int *)0;
The amendment's constraint 4 requires a diagnostic message given code
like:
void func(void *vp) {
return *vp;
}
and:
int main(void) {
int i = 5;
int *ip = &i;
*(void *)ip;
return 0;
}
and:
#include <stddef.h>
struct s;
struct s *sp = NULL;
size_t sz = sizeof *(struct s *)ip;
because:
- it is intended to disallow the unary-expression of the unary *
operator and its operand to constitute a void expression merely
because the operand has type ``pointer to void'' (satisfying
constraint 2 and pre-amendment semantic point 4, sentence 3).
- it is intended to disallow the unary-expression of the unary *
operator and its operand to produce a result which has an incomplete
type.
The amendment still allows for:
int main(void) {
int i = 5;
void *vp = &i;
int *ip = &*vp;
return 0;
}
and:
#include <stddef.h>
struct s;
struct s *sp = NULL;
int main(void) {
void *vp = &*sp;
return 0;
}
where it is intended to allow the semantics to be followed so that the
value of a pointer to an incomplete type can be assigned to another
pointer, by not evaluating either the unary & or unary * operator.
The amendment's semantic point 6 removes the mention of an assignment
and should have no implications.
--- IMPLICATIONS FOR C PROGRAMMERS ---
Any code applying the unary * operator to a null pointer constant, or
cast thereof, outside of as an operand to sizeof or unary & will cause
a diagnostic message as a constraint violation.
Any code applying the unary * operator to a pointer to an incomplete
type outside of as an operand to unary & will cause a diagnostic
message as a constraint violation.
Any code that assumes there must be an invalid value assigned to some
pointer in order for the behaviour to be undefined for applying the
unary * operator to any operand is erroneous code, by this amendment.
--- CONSTRUCTIVE FEEDBACK ---
If you please! Thank you!
- Shao Miller
--- AMENDMENT ---
6.5.3.2 Address and indirection operators
Constraints
1 <NO AMENDMENT PROPOSED>
2 The operand of the unary * operator shall have pointer type. <NO
AMENDMENT PROPOSED>
3 Except when the unary * operator and its operand are not evaluated,
the operand of the unary * operator shall not be a null pointer
constant expression, or such an expression cast to any pointer type.
4 Except when the unary * operator and its operand are together the
operand to the unary & operator, the operand of the unary * operator
shall not be a pointer type pointing to an incomplete type.
Semantics
5 <AMENDED FROM POINT 3 TO 5. NO OTHER AMENDMENT PROPOSED>
6 <AMENDED FROM POINT 4 TO 6> The unary * operator denotes
indirection. If the operand points to a function, the result is a
function designator; if it points to an object, the result is an
lvalue designating the object. If the operand has type ``pointer to
type'', the result has type ``type''. If the operand is an invalid
value, the behavior of the unary * operator is undefined.87)
Forward references: storage-class specifiers (6.7.1), structure and
union specifiers
(6.7.2.1). <NO AMENDMENT PROPOSED>
.... ... ... <NO AMENDMENTS PROPOSED BEFORE FOOTNOTE 87>
87) Thus, &*E is equivalent to E (even if E is a null pointer), and
&(E1[E2]) to ((E1)+(E2)). It is always true that if E is a function
designator or an lvalue that is a valid operand of the unary &
operator, *&E is a function designator or an lvalue equal to E. If *P
is an lvalue and T is the name of an object pointer type, *(T)P is an
lvalue that has a type compatible with that to which T points.
Among the invalid values for dereferencing a pointer by the unary *
operator are a null pointer, an address inappropriately aligned for
the type of object pointed to, and the address of an object after the
end of its lifetime.
--- INTENDED AUDIENCE ---
The intended audience for this proposal are:
- The ISO/IEC JTC1/SC22/WG14 international standardization working
group for the programming language C
- C implementors (developers of C implementations with conformance to
the standard in mind)
- C programmers
--- RATIONALE ---
The previous text in the C99 international standard allowed for
certain language constructs to lead to undefined behaviour which a C
implementation might choose to define. This amendment encourages
implementators and programmers to avoid allowance of and usage of
these constructs, respectively, to help to maximize the portability of
a C program across different implementations.
These language constructs claimed above as leading to undefined
behaviour are perhaps rarely explored or used historically, so there
should be little impact to implementations beyond two additional
constraint violations to diagnose.
--- IMPLICATIONS FOR C IMPLEMENTORS ---
The amendment's constraint 3 requires a diagnostic message given code
like:
int main(void) {
int i = *(int *)0;
return 0;
}
because it is known at translation-time (pre-evaluation) that this is
an attempt to access an object pointed to by a null pointer, which is
erroneous.
The amendment still allows for:
#include <stddef.h>
size_t sz = sizeof *(int *)0;
and:
int *ip = &*(int *)0;
The amendment's constraint 4 requires a diagnostic message given code
like:
void func(void *vp) {
return *vp;
}
and:
int main(void) {
int i = 5;
int *ip = &i;
*(void *)ip;
return 0;
}
and:
#include <stddef.h>
struct s;
struct s *sp = NULL;
size_t sz = sizeof *(struct s *)ip;
because:
- it is intended to disallow the unary-expression of the unary *
operator and its operand to constitute a void expression merely
because the operand has type ``pointer to void'' (satisfying
constraint 2 and pre-amendment semantic point 4, sentence 3).
- it is intended to disallow the unary-expression of the unary *
operator and its operand to produce a result which has an incomplete
type.
The amendment still allows for:
int main(void) {
int i = 5;
void *vp = &i;
int *ip = &*vp;
return 0;
}
and:
#include <stddef.h>
struct s;
struct s *sp = NULL;
int main(void) {
void *vp = &*sp;
return 0;
}
where it is intended to allow the semantics to be followed so that the
value of a pointer to an incomplete type can be assigned to another
pointer, by not evaluating either the unary & or unary * operator.
The amendment's semantic point 6 removes the mention of an assignment
and should have no implications.
--- IMPLICATIONS FOR C PROGRAMMERS ---
Any code applying the unary * operator to a null pointer constant, or
cast thereof, outside of as an operand to sizeof or unary & will cause
a diagnostic message as a constraint violation.
Any code applying the unary * operator to a pointer to an incomplete
type outside of as an operand to unary & will cause a diagnostic
message as a constraint violation.
Any code that assumes there must be an invalid value assigned to some
pointer in order for the behaviour to be undefined for applying the
unary * operator to any operand is erroneous code, by this amendment.
--- CONSTRUCTIVE FEEDBACK ---
If you please! Thank you!
- Shao Miller