I am trying to debug someone else's code.
There is a struct with elements of various size including a member defined as
uint16_t attempts
elsewhere this element is accessed thus
int x = handle->attempts;
int in my system is 32 bits
Is it safe to assume that 2 bytes are loaded from the position pointed to in the struct (uint16_t) and implicitly convert to int (4 bytes).
Or is it possible that the 4 bytes pointed to are loaded as an int (in this case an amalgamation of 2 uint16_t members)?
CodePudding user response:
int x = handle->attempts;
is a declaration with an initialization. In this declaration, handle->attempts
is an initializer, per the grammar in C 2018 6.7 1. An initializer is an assignment-expression, per C 2018 6.7.9 1, and so rules for expression evaluation will be used.
The expression handle->attempts
designates the uint16_t
member named attempts
of the structure pointed to by handle
. In other words, it is an lvalue for the member. Per C 2018 6.3.2.1 2, this lvalue is converted to the value stored in the designated object. Thus, the C standard says the bytes representing this object are read and interpreted according to the uint16_t
type.
Then a rule for initialization in C 2018 6.7.9 11 tells us this value is used as the initial value for the object being defined, x
, using the same constraints and conversions as for simple assignment.
C 2018 6.5.16.1 specifies simple assignment. Paragraph 2 says “the value of the right operand is converted to the type of the assignment expression and replaces the value stored in the object designated by the left operand.” Thus, the value we have obtained from the initializer is converted to the type of x
, int
, and that bytes representing that value in the type int
are stored in x
.
CodePudding user response:
Converting an integer value to another integer type is guaranteed to result in the same value as long as the target type can represent the value in question. A 4 byte int
will be able to represent all values of std::uint16_t
.