Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
Post History
It is undefined according to my reading of the standard (I am referring to the latest public draft). int x; (void)x; In the second line, (void)x is a full expression, but x by itself is alread...
Answer
#4: Post edited
It is undefined according to my reading of the standard (I am referring to the latest public draft https://web.archive.org/web/20181230041359if_/http://www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf).- int x;
- (void)x;
- In the second line, `(void)x` is a full expression, but `x` by itself is already an expression. For the expression `x` the following holds:
- > 6.5.1 - 2: An identifier is a primary expression, provided it has been declared as designating an object (in which case it is an lvalue) or a function (in which case it is a function designator).
- Thus, `x` being an identifer that is declared to designate an `int` object implies that `x` is a primary expression and an lvalue.
- > 6.3.2.1 - 2: Except when it is the operand of the sizeof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue); this is called lvalue conversion. [...]
- As the lvalue `x` is the operand of a cast operator (which is not in the above exception list) and as it is also no array type it is converted into the value stored in the object designated by `x`.
- > 6.3.2.1 - 2: [...] If the lvalue designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.
As `x` has automatic storage duration, has never its address taken and is uninitialized, **the behavior is undefined**. (The point about the `register` storage class is to allow optimizations on certain processors, see the explanation of "NaT" in https://devblogs.microsoft.com/oldnewthing/20150727-00/?p=90821.)- Note that it does not matter that `x` is part of a larger expression `(void)x`. But, just to extend on that aspect:
- > 6.5 - 1: An expression is a sequence of operators and operands that specifies computation of a value, or that designates an object or a function, or that generates side effects, or that performs a combination
- thereof. The value computations of the operands of an operator are sequenced before the value computation of the result of the operator.
- Important is the sequencing aspect here: The value of the operand `x` is computed before the result of the `(void)` operator is computed. The full expression will - in the end - have type `void`.
- > 6.3.2.2 - 1: The (nonexistent) value of a void expression (an expression that has type void) shall not be used in any way, and implicit or explicit conversions (except to void) shall not be applied to such an expression. [...]
- But this only says that you are not allowed to make further use of that `void` "result" of the expression `(void)x`.
- > 6.3.2.2 - 1: [...] If an expression of any other type is evaluated as a void expression, its value or designator is discarded. (A void expression is evaluated for its side effects.)
- Note that this does *not* say that the whole expression is discarded: Only its value (which is the result of the expression being evaluated) is discarded. The clause is there to make it clear that a void expressions *is* evaluated. The sentence in parentheses gives the reason why it is evaluated, namely because it may have side effects. The sentence does not say that it is *only* evaluated if it has side effects.
- Therefore, it is also not possible to argue that the "undefinedness" stated above becomes irrelevant because the whole expression would be discarded: The expression just won't be discarded, only its result.
- It is undefined according to my reading of the standard (I am referring to the [latest public draft](https://web.archive.org/web/20181230041359if_/http://www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf)).
- int x;
- (void)x;
- In the second line, `(void)x` is a full expression, but `x` by itself is already an expression. For the expression `x` the following holds:
- > 6.5.1 - 2: An identifier is a primary expression, provided it has been declared as designating an object (in which case it is an lvalue) or a function (in which case it is a function designator).
- Thus, `x` being an identifer that is declared to designate an `int` object implies that `x` is a primary expression and an lvalue.
- > 6.3.2.1 - 2: Except when it is the operand of the sizeof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue); this is called lvalue conversion. [...]
- As the lvalue `x` is the operand of a cast operator (which is not in the above exception list) and as it is also no array type it is converted into the value stored in the object designated by `x`.
- > 6.3.2.1 - 2: [...] If the lvalue designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.
- As `x` has automatic storage duration, has never its address taken and is uninitialized, **the behavior is undefined**. (The point about the `register` storage class is to allow optimizations on certain processors. See the description of the "NaT" register state in [this article about the Itanium processor](https://devblogs.microsoft.com/oldnewthing/20150727-00/?p=90821).)
- Note that it does not matter that `x` is part of a larger expression `(void)x`. But, just to extend on that aspect:
- > 6.5 - 1: An expression is a sequence of operators and operands that specifies computation of a value, or that designates an object or a function, or that generates side effects, or that performs a combination
- thereof. The value computations of the operands of an operator are sequenced before the value computation of the result of the operator.
- Important is the sequencing aspect here: The value of the operand `x` is computed before the result of the `(void)` operator is computed. The full expression will - in the end - have type `void`.
- > 6.3.2.2 - 1: The (nonexistent) value of a void expression (an expression that has type void) shall not be used in any way, and implicit or explicit conversions (except to void) shall not be applied to such an expression. [...]
- But this only says that you are not allowed to make further use of that `void` "result" of the expression `(void)x`.
- > 6.3.2.2 - 1: [...] If an expression of any other type is evaluated as a void expression, its value or designator is discarded. (A void expression is evaluated for its side effects.)
- Note that this does *not* say that the whole expression is discarded: Only its value (which is the result of the expression being evaluated) is discarded. The clause is there to make it clear that a void expressions *is* evaluated. The sentence in parentheses gives the reason why it is evaluated, namely because it may have side effects. The sentence does not say that it is *only* evaluated if it has side effects.
- Therefore, it is also not possible to argue that the "undefinedness" stated above becomes irrelevant because the whole expression would be discarded: The expression just won't be discarded, only its result.
#3: Post edited
- It is undefined according to my reading of the standard (I am referring to the latest public draft https://web.archive.org/web/20181230041359if_/http://www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf).
- int x;
- (void)x;
- In the second line, `(void)x` is a full expression, but `x` by itself is already an expression. For the expression `x` the following holds:
- > 6.5.1 - 2: An identifier is a primary expression, provided it has been declared as designating an object (in which case it is an lvalue) or a function (in which case it is a function designator).
- Thus, `x` being an identifer that is declared to designate an `int` object implies that `x` is a primary expression and an lvalue.
- > 6.3.2.1 - 2: Except when it is the operand of the sizeof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue); this is called lvalue conversion. [...]
- As the lvalue `x` is the operand of a cast operator (which is not in the above exception list) and as it is also no array type it is converted into the value stored in the object designated by `x`.
- > 6.3.2.1 - 2: [...] If the lvalue designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.
As `x` has automatic storage duration, has never its address taken and is uninitialized, **the behavior is undefined**.- Note that it does not matter that `x` is part of a larger expression `(void)x`. But, just to extend on that aspect:
- > 6.5 - 1: An expression is a sequence of operators and operands that specifies computation of a value, or that designates an object or a function, or that generates side effects, or that performs a combination
- thereof. The value computations of the operands of an operator are sequenced before the value computation of the result of the operator.
- Important is the sequencing aspect here: The value of the operand `x` is computed before the result of the `(void)` operator is computed. The full expression will - in the end - have type `void`.
- > 6.3.2.2 - 1: The (nonexistent) value of a void expression (an expression that has type void) shall not be used in any way, and implicit or explicit conversions (except to void) shall not be applied to such an expression. [...]
- But this only says that you are not allowed to make further use of that `void` "result" of the expression `(void)x`.
- > 6.3.2.2 - 1: [...] If an expression of any other type is evaluated as a void expression, its value or designator is discarded. (A void expression is evaluated for its side effects.)
- Note that this does *not* say that the whole expression is discarded: Only its value (which is the result of the expression being evaluated) is discarded. The clause is there to make it clear that a void expressions *is* evaluated. The sentence in parentheses gives the reason why it is evaluated, namely because it may have side effects. The sentence does not say that it is *only* evaluated if it has side effects.
- Therefore, it is also not possible to argue that the "undefinedness" stated above becomes irrelevant because the whole expression would be discarded: The expression just won't be discarded, only its result.
- It is undefined according to my reading of the standard (I am referring to the latest public draft https://web.archive.org/web/20181230041359if_/http://www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf).
- int x;
- (void)x;
- In the second line, `(void)x` is a full expression, but `x` by itself is already an expression. For the expression `x` the following holds:
- > 6.5.1 - 2: An identifier is a primary expression, provided it has been declared as designating an object (in which case it is an lvalue) or a function (in which case it is a function designator).
- Thus, `x` being an identifer that is declared to designate an `int` object implies that `x` is a primary expression and an lvalue.
- > 6.3.2.1 - 2: Except when it is the operand of the sizeof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue); this is called lvalue conversion. [...]
- As the lvalue `x` is the operand of a cast operator (which is not in the above exception list) and as it is also no array type it is converted into the value stored in the object designated by `x`.
- > 6.3.2.1 - 2: [...] If the lvalue designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.
- As `x` has automatic storage duration, has never its address taken and is uninitialized, **the behavior is undefined**. (The point about the `register` storage class is to allow optimizations on certain processors, see the explanation of "NaT" in https://devblogs.microsoft.com/oldnewthing/20150727-00/?p=90821.)
- Note that it does not matter that `x` is part of a larger expression `(void)x`. But, just to extend on that aspect:
- > 6.5 - 1: An expression is a sequence of operators and operands that specifies computation of a value, or that designates an object or a function, or that generates side effects, or that performs a combination
- thereof. The value computations of the operands of an operator are sequenced before the value computation of the result of the operator.
- Important is the sequencing aspect here: The value of the operand `x` is computed before the result of the `(void)` operator is computed. The full expression will - in the end - have type `void`.
- > 6.3.2.2 - 1: The (nonexistent) value of a void expression (an expression that has type void) shall not be used in any way, and implicit or explicit conversions (except to void) shall not be applied to such an expression. [...]
- But this only says that you are not allowed to make further use of that `void` "result" of the expression `(void)x`.
- > 6.3.2.2 - 1: [...] If an expression of any other type is evaluated as a void expression, its value or designator is discarded. (A void expression is evaluated for its side effects.)
- Note that this does *not* say that the whole expression is discarded: Only its value (which is the result of the expression being evaluated) is discarded. The clause is there to make it clear that a void expressions *is* evaluated. The sentence in parentheses gives the reason why it is evaluated, namely because it may have side effects. The sentence does not say that it is *only* evaluated if it has side effects.
- Therefore, it is also not possible to argue that the "undefinedness" stated above becomes irrelevant because the whole expression would be discarded: The expression just won't be discarded, only its result.
#2: Post edited
- It is undefined according to my reading of the standard (I am referring to the latest public draft https://web.archive.org/web/20181230041359if_/http://www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf).
- int x;
- (void)x;
- In the second line, `(void)x` is a full expression, but `x` by itself is already an expression. For the expression `x` the following holds:
- > 6.5.1 - 2: An identifier is a primary expression, provided it has been declared as designating an object (in which case it is an lvalue) or a function (in which case it is a function designator).
- Thus, `x` being an identifer that is declared to designate an `int` object implies that `x` is a primary expression and an lvalue.
- > 6.3.2.1 - 2: Except when it is the operand of the sizeof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue); this is called lvalue conversion. [...]
- As the lvalue `x` is the operand of a cast operator (which is not in the above exception list) and as it is also no array type it is converted into the value stored in the object designated by `x`.
- > 6.3.2.1 - 2: [...] If the lvalue designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.
- As `x` has automatic storage duration, has never its address taken and is uninitialized, **the behavior is undefined**.
- Note that it does not matter that `x` is part of a larger expression `(void)x`. But, just to extend on that aspect:
- > 6.5 - 1: An expression is a sequence of operators and operands that specifies computation of a value, or that designates an object or a function, or that generates side effects, or that performs a combination
- thereof. The value computations of the operands of an operator are sequenced before the value computation of the result of the operator.
- Important is the sequencing aspect here: The value of the operand `x` is computed before the result of the `(void)` operator is computed. The full expression will - in the end - have type `void`.
- > 6.3.2.2 - 1: The (nonexistent) value of a void expression (an expression that has type void) shall not be used in any way, and implicit or explicit conversions (except to void) shall not be applied to such an expression. [...]
- But this only says that you are not allowed to make further use of that `void` "result" of the expression `(void)x`.
- > 6.3.2.2 - 1: [...] If an expression of any other type is evaluated as a void expression, its value or designator is discarded. (A void expression is evaluated for its side effects.)
- Note that this does *not* say that the whole expression is discarded: Only its value (which is the result of the expression being evaluated) is discarded. The clause is there to make it clear that a void expressions *is* evaluated. The sentence in parentheses gives the reason why it is evaluated, namely because it may have side effects. The sentence does not say that it is *only* evaluated if it has side effects.
Therefore, it is also not possible to argue that the "undefinedness" stated above becomes irrelevant because the compiler will discard the whole expression.
- It is undefined according to my reading of the standard (I am referring to the latest public draft https://web.archive.org/web/20181230041359if_/http://www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf).
- int x;
- (void)x;
- In the second line, `(void)x` is a full expression, but `x` by itself is already an expression. For the expression `x` the following holds:
- > 6.5.1 - 2: An identifier is a primary expression, provided it has been declared as designating an object (in which case it is an lvalue) or a function (in which case it is a function designator).
- Thus, `x` being an identifer that is declared to designate an `int` object implies that `x` is a primary expression and an lvalue.
- > 6.3.2.1 - 2: Except when it is the operand of the sizeof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue); this is called lvalue conversion. [...]
- As the lvalue `x` is the operand of a cast operator (which is not in the above exception list) and as it is also no array type it is converted into the value stored in the object designated by `x`.
- > 6.3.2.1 - 2: [...] If the lvalue designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.
- As `x` has automatic storage duration, has never its address taken and is uninitialized, **the behavior is undefined**.
- Note that it does not matter that `x` is part of a larger expression `(void)x`. But, just to extend on that aspect:
- > 6.5 - 1: An expression is a sequence of operators and operands that specifies computation of a value, or that designates an object or a function, or that generates side effects, or that performs a combination
- thereof. The value computations of the operands of an operator are sequenced before the value computation of the result of the operator.
- Important is the sequencing aspect here: The value of the operand `x` is computed before the result of the `(void)` operator is computed. The full expression will - in the end - have type `void`.
- > 6.3.2.2 - 1: The (nonexistent) value of a void expression (an expression that has type void) shall not be used in any way, and implicit or explicit conversions (except to void) shall not be applied to such an expression. [...]
- But this only says that you are not allowed to make further use of that `void` "result" of the expression `(void)x`.
- > 6.3.2.2 - 1: [...] If an expression of any other type is evaluated as a void expression, its value or designator is discarded. (A void expression is evaluated for its side effects.)
- Note that this does *not* say that the whole expression is discarded: Only its value (which is the result of the expression being evaluated) is discarded. The clause is there to make it clear that a void expressions *is* evaluated. The sentence in parentheses gives the reason why it is evaluated, namely because it may have side effects. The sentence does not say that it is *only* evaluated if it has side effects.
- Therefore, it is also not possible to argue that the "undefinedness" stated above becomes irrelevant because the whole expression would be discarded: The expression just won't be discarded, only its result.
#1: Initial revision
It is undefined according to my reading of the standard (I am referring to the latest public draft https://web.archive.org/web/20181230041359if_/http://www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf). int x; (void)x; In the second line, `(void)x` is a full expression, but `x` by itself is already an expression. For the expression `x` the following holds: > 6.5.1 - 2: An identifier is a primary expression, provided it has been declared as designating an object (in which case it is an lvalue) or a function (in which case it is a function designator). Thus, `x` being an identifer that is declared to designate an `int` object implies that `x` is a primary expression and an lvalue. > 6.3.2.1 - 2: Except when it is the operand of the sizeof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue); this is called lvalue conversion. [...] As the lvalue `x` is the operand of a cast operator (which is not in the above exception list) and as it is also no array type it is converted into the value stored in the object designated by `x`. > 6.3.2.1 - 2: [...] If the lvalue designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined. As `x` has automatic storage duration, has never its address taken and is uninitialized, **the behavior is undefined**. Note that it does not matter that `x` is part of a larger expression `(void)x`. But, just to extend on that aspect: > 6.5 - 1: An expression is a sequence of operators and operands that specifies computation of a value, or that designates an object or a function, or that generates side effects, or that performs a combination thereof. The value computations of the operands of an operator are sequenced before the value computation of the result of the operator. Important is the sequencing aspect here: The value of the operand `x` is computed before the result of the `(void)` operator is computed. The full expression will - in the end - have type `void`. > 6.3.2.2 - 1: The (nonexistent) value of a void expression (an expression that has type void) shall not be used in any way, and implicit or explicit conversions (except to void) shall not be applied to such an expression. [...] But this only says that you are not allowed to make further use of that `void` "result" of the expression `(void)x`. > 6.3.2.2 - 1: [...] If an expression of any other type is evaluated as a void expression, its value or designator is discarded. (A void expression is evaluated for its side effects.) Note that this does *not* say that the whole expression is discarded: Only its value (which is the result of the expression being evaluated) is discarded. The clause is there to make it clear that a void expressions *is* evaluated. The sentence in parentheses gives the reason why it is evaluated, namely because it may have side effects. The sentence does not say that it is *only* evaluated if it has side effects. Therefore, it is also not possible to argue that the "undefinedness" stated above becomes irrelevant because the compiler will discard the whole expression.