Логическая операция применяется к значению типа int (C) или bool (C++), в которое будет неявно сконвертировано x. Поведение вполне ожидаемо и полностью соответствует обоим стандартам.
Да что вы говорите? Могли бы и проверить, прежде чем писать.
Приведение double/char/int/long/ptr к bool типу - это в точности сравнение с нулём.
Если 0 - false, не 0 - true. То же самое и с самим bool, кстати.
Да, прошу прощения. В случае C Вы правы:
Стандарты языков C99, C11 в 5-м абзаце параграфа "6.5.3.3 Unary arithmetic operators" писал(а):
The result of the logical negation operator ! is 0 if the value of its operand compares
unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int.
The expression !E is equivalent to (0==E).
В случае C++, по-моему, нет (подчеркнуты различия для разных стандартов языка):
Стандарт языка C++03 в 8-м абзаце параграфа "5.3.1 Unary operators [expr.unary.op]" писал(а):
The operand of the logical negation operator ! is implicitly converted to bool (clause 4); its value is true if the converted operand is false and false otherwise. The type of the result is bool.
Стандарт языка C++11 в 8-м абзаце параграфа "5.3.1 Unary operators [expr.unary.op]" писал(а):
The operand of the logical negation operator ! is contextually converted to bool (clause 4); its value is true if the converted operand is false and false otherwise. The type of the result is bool.
А в разделе 4 значится следующее:
Стандарт языка C++03 в 1-м абзаце параграфа "4.12 Boolean conversions [conv.bool]" писал(а):
An rvalue of arithmetic, enumeration, pointer, or pointer to member type can be converted to an rvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true.
Стандарт языка C++11 в 1-м абзаце параграфа "4.12 Boolean conversions [conv.bool]" писал(а):
A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true. A prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false.