문제

In C, signed integers like -1 are supposedly supposed to be declared with the keyword signed, like so:

signed int i = -1;

However, I tried this:

signed int i = -2;
unsigned int i = -2;
int i = -2;

and all 3 cases print out -2 with printf("%d", i);. Why?

도움이 되었습니까?

해결책

Since you confirmed you are printing using:

printf("%d", i);

this is undefined behavior in the unsigned case. This is covered in the draft C99 standard section 7.19.6.1 The fprintf function which also covers printf for format specifiers, it says in paragraph 9:

If a conversion specification is invalid, the behavior is undefined.248)[...]

The standard defined in section 3.4.3 undefined behavior as:

behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements

and further notes:

Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

Finally, we can see that int is the same as signed int. We can see this by going to section 6.7.2 Type specifiers, in paragraph 2 it groups int as follows:

int, signed, or signed int

and later on says in paragraph 5 says:

Each of the comma-separated sets designates the same type, except that for bit-field[...]

다른 팁

The way an integer variable is printed, is subjected to the format string that you pass to printf:

  • If you use %d, then you'll be printing it as a signed integer.
  • If you use %u, then you'll be printing it as an unsigned integer.

printf has no way of knowing what you pass to it. C compiler does the default type promotions on passing the arguments, and then the function itself reinterprets the values in accordance with the format specifiers that you pass, because it has no other information regarding the type of the value that you passed.

When you pass an unsigned int to printf in a position of %d, it is undefined behavior. Your program is incorrect, and it could print anything.

It happens that on hardware that represent negative numbers in two's complement representation you get the same number that you started with. However, this is not a universal rule.

unsigned int i = -2; // i actually holds 4294967294
printf("%d", i); // printf casts i back to an int which is -2 hence the same output

You've got 2 things going on:

  1. Signed and unsigned are different ways of interpreting the same 64 (or 32, or whatever) bits.
  2. Printf is a variadic function which accepts parameters of different types

You passed a signed value (-2) to an unsigned variable, and then asked printf to interpret it as signed.

Remember that "signed" and unsigned have to do with how arithmetic is done on the numbers. the printf family accepts internally casts whatever you pass in based on the format designators. (this is the nature of variadic functions that accept more than one type of parameter. They cannot use traditional type safety mechanisms)

This is all very well, but not all things will work the same.

Addition and subtraction work the same on most architectures (as long as you're not on some oddball architecture that doesn't use 2's complement for representing negative numbers Multiplication and division may also work the same. Inequality comparisons are the hardest thing to know how they will work, and I have been bit a number of times doing a comparison between signed and unsigned that I thought would be ok, be cause they were in the small signed number range.

Thats what "undefined" means. Behaviour is left to the compiler and hardware implementers and cannot be relied to be the same between architectures or even over time on the same architecture.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top