本文旨在用作关于C中隐式整数提升的常见问题解答,特别是由通常的算术转换和/或整数提升引起的隐式提升.
示例1)
为什么这会给出一个奇怪的大整数而不是255?
unsigned char x = 0;
unsigned char y = 1;
printf("%u\n", x - y);
Run Code Online (Sandbox Code Playgroud)
例2)
为什么这会给"-1大于0"?
unsigned int a = 1;
signed int b = -2;
if(a + b > 0)
puts("-1 is larger than 0");
Run Code Online (Sandbox Code Playgroud)
示例3)
为什么更改上例中的类型来short解决问题?
unsigned short a = 1;
signed short b = -2;
if(a + b > 0)
puts("-1 is larger than 0"); // will not print
Run Code Online (Sandbox Code Playgroud)
(这些示例适用于16位或短16位的32位或64位计算机.)
我想知道以下代码的使用
int result = 0;
int factor = 1;
for (...) {
result = ...
factor *= 10;
}
return result;
Run Code Online (Sandbox Code Playgroud)
如果循环是随着n时间反复进行的,则将factor其乘以10精确的n时间。但是,factor仅在乘以10总n-1次数后才使用。如果我们假设factor除了在循环的最后一次迭代之外永远不会溢出,而是可能在循环的最后一次迭代中溢出,那么这样的代码是否可以接受?在这种情况下,factor证明溢出后永远不会使用的值。
我正在就是否应接受此类代码进行辩论。可以将乘法放在if语句中,并且在可能溢出时,不对循环的最后一次迭代进行乘法。缺点是它会使代码混乱,并添加了一个不必要的分支,需要在所有先前的循环迭代中进行检查。我还可以减少循环迭代一次,并在循环之后复制一次循环主体,这又使代码复杂化。
有问题的实际代码在一个紧密的内部循环中使用,该循环在实时图形应用程序中消耗大量的总CPU时间。
请看我的测试代码:
#include <stdlib.h>
#include <stdio.h>
#define PRINT_COMPARE_RESULT(a, b) \
if (a > b) { \
printf( #a " > " #b "\n"); \
} \
else if (a < b) { \
printf( #a " < " #b "\n"); \
} \
else { \
printf( #a " = " #b "\n" ); \
}
int main()
{
signed int a = -1;
unsigned int b = 2;
signed short c = -1;
unsigned short d = 2;
PRINT_COMPARE_RESULT(a,b);
PRINT_COMPARE_RESULT(c,d); …Run Code Online (Sandbox Code Playgroud) 我正在阅读关于通常算术转换的C99标准.
如果两个操作数具有相同的类型,则不需要进一步转换.
否则,如果两个操作数都具有有符号整数类型或两者都具有无符号整数类型,则具有较小整数转换等级类型的操作数将转换为具有更高等级的操作数的类型.
否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的秩,则具有有符号整数类型的操作数将转换为具有无符号整数类型的操作数的类型.
否则,如果带有符号整数类型的操作数的类型可以表示具有无符号整数类型的操作数类型的所有值,则具有无符号整数类型的操作数将转换为带有符号整数类型的操作数的类型.
否则,两个操作数都转换为无符号整数类型,对应于带有符号整数类型的操作数的类型.
所以我想说我有以下代码:
#include <stdio.h>
int main()
{
unsigned int a = 10;
signed int b = -5;
printf("%d\n", a + b); /* 5 */
printf("%u\n", a + b); /* 5 */
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我认为粗体段落适用(因为unsigned int并且signed int具有相同的等级.为什么不转换为b unsigned?或者它可能转换为无符号但是有些东西我不明白?
感谢您的时间 :-)
签名/未签名的不匹配一定是坏的吗?
这是我的计划:
int main(int argc, char *argv[]) {
unsigned int i;
for (i = 1; i < argc; i++) { // signed/unsigned mismatch here
}
}
Run Code Online (Sandbox Code Playgroud)
argc签了,i不是.这是一个问题吗?
注意:建议的重复项处理的是unsigned intand signed int,而不是unsigned char和signed char。建议的重复问题涉及 C11。这个问题只与C89有关。这个问题可以重新讨论吗?
我的代码:
#include <stdio.h>
int main()
{
signed char c;
unsigned char d;
c = (signed char) -2;
d = (unsigned char) c;
printf("%d %d\n", c, d);
d = (unsigned char) 254;
c = (signed char) d;
printf("%d %d\n", c, d);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
$ clang -Wall -Wextra -pedantic -std=c89 foo.c && ./a.out
-2 254
-2 254
Run Code Online (Sandbox Code Playgroud)
对于上面显示的两种转换,输出是否保证-2 254在符合标准的 C89 编译器中?或者输出取决于实施?
如果我使用错误的格式说明符,如下所示:
unsigned int i = -1;
printf("%d\n", i);
Run Code Online (Sandbox Code Playgroud)
它被调用未定义的行为,因为%u格式说明符unsigned.
C11标准§7.21.6.1(P9):
如果转换规范无效,则行为未定义.282)如果任何参数不是相应转换规范的正确类型,则行为未定义.
但是,如果我这样写:
unsigned int i = -1;
printf("%d\n", (int)i); // unsigned to signed
Run Code Online (Sandbox Code Playgroud)
它也是未定义的行为吗?
我在c中有以下代码:
unsigned int a = 60; /* 60 = 0011 1100 */
int c = 0;
c = ~a; /*-61 = 1100 0011 */
printf("c = ~a = %d\n", c );
c = a << 2; /* 240 = 1111 0000 */
printf("c = a << 2 = %d\n", c );
Run Code Online (Sandbox Code Playgroud)
第一个输出是-61而第二个输出是240.为什么第一个printf会计算1100的两个补码,而第二个只是将1111 0000转换为十进制的等值?