本文旨在用作关于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位计算机.)
所以我们遇到了一个字段问题,经过几天的调试后,将问题缩小到这个特定的代码位,其中没有发生while循环中的处理:
// heavily redacted code
// numberA and numberB are both of uint16_t
// Important stuff happens in that while loop
while ( numberA + 1 == numberB )
{
// some processing
}
Run Code Online (Sandbox Code Playgroud)
这个运行得很好,直到我们达到了65535的uint16限制.另一堆打印语句后来,我们发现它numberA + 1有一个值65536,同时被numberB包裹回来0.检查失败,没有进行任何处理.
这让我很好奇,所以我整理了一个快速的C程序(用GCC 4.9.2编译)来检查:
#include <stdio.h>
#include <stdint.h>
int main()
{
uint16_t numberA, numberB;
numberA = 65535;
numberB = numberA + 1;
uint32_t numberC, numberD;
numberC = 4294967295;
numberD = numberC + 1;
printf("numberA = %d\n", numberA …Run Code Online (Sandbox Code Playgroud) 考虑以下程序:
// http://ideone.com/4I0dT
#include <limits>
#include <iostream>
int main()
{
int max = std::numeric_limits<int>::max();
unsigned int one = 1;
unsigned int result = max + one;
std::cout << result;
}
Run Code Online (Sandbox Code Playgroud)
和
// http://ideone.com/UBuFZ
#include <limits>
#include <iostream>
int main()
{
unsigned int us = 42;
int neg = -43;
int result = us + neg;
std::cout << result;
}
Run Code Online (Sandbox Code Playgroud)
+运算符如何"知道"返回哪个正确的类型?一般的规则是把所有的参数转换为最广泛的类型,但在这里没有明确的"赢家"之间int和unsigned int.在第一种情况下,unsigned int必须选择作为结果operator+,因为我得到了结果2147483648.在第二种情况下,它必须选择int,因为我得到了结果-1.然而,在一般情况下,我没有看到这是如何可判定的.这是我看到的未定义的行为还是其他什么?
我一直在寻找答案.我要做出一系列的我自己的字符串函数一样my_strcmp(),my_strcat()等等.
是否strcmp()通过两个字符数组的每个索引工作,如果ASCII值在两个字符串的相同索引处较小,则该字符串按字母顺序更大,因此返回0或1或2?我想我要问的是,它是否使用字符的ASCII值来返回这些结果?
任何帮助将不胜感激.
[修订]
好的,所以我想出了这个...它适用于所有情况,除非第二个字符串大于第一个字符串.
有小费吗?
int my_strcmp(char s1[], char s2[])
{
int i = 0;
while ( s1[i] != '\0' )
{
if( s2[i] == '\0' ) { return 1; }
else if( s1[i] < s2[i] ) { return -1; }
else if( s1[i] > s2[i] ) { return 1; }
i++;
}
return 0;
}
int main (int argc, char *argv[])
{
int result = my_strcmp(argv[1], argv[2]);
printf("Value: %d \n", result);
return …Run Code Online (Sandbox Code Playgroud) 在阅读Xilinx的DMA示例代码时,我遇到了这段代码:
value = (value + 1) & 0xFF
Run Code Online (Sandbox Code Playgroud)
其中value是uint8_t.
有什么意义& 0xFF?为什么不简单写value = value + 1?
是否可以创建一个模板化函数来检查原始数据类型是否适合可能不同的原始数据类型的值?我们暂时将范围限制为整数类型.
更确切地说:是否有可能创建一个"一个适合所有"的模板化函数,而不会得到编译器警告(布尔表达式总是真/假,有符号/无符号比较,未使用的变量)并且不禁用编译器警告检查?这些函数还应该在运行时尽可能地限制检查(在编译时应排除所有琐碎的情况).如果可能的话,我宁愿避免使用C++ 11之类的扩展(除非存在"旧"C++的"快速"替代).
注意:"value"在编译时是未知的,只是其类型.
预期行为的示例:
int main(int argc, char** argv) {
for (int i = 1; i < argc; i++) {
const int value = atoi(argv[i]);
std::cout << value << ": ";
std::cout << CanTypeFitValue<int8_t>(value) << " ";
std::cout << CanTypeFitValue<uint8_t>(value) << " ";
std::cout << CanTypeFitValue<int16_t>(value) << " ";
std::cout << CanTypeFitValue<uint16_t>(value) << " ";
std::cout << CanTypeFitValue<int32_t>(value) << " ";
std::cout << CanTypeFitValue<uint32_t>(value) << " ";
std::cout << CanTypeFitValue<int64_t>(value) << " ";
std::cout << CanTypeFitValue<uint64_t>(value) << std::endl;
} …Run Code Online (Sandbox Code Playgroud) 考虑以下示例:
#include <stdio.h>
int main(void)
{
unsigned char a = 15; /* one byte */
unsigned short b = 15; /* two bytes */
unsigned int c = 15; /* four bytes */
long x = -a; /* eight bytes */
printf("%ld\n", x);
x = -b;
printf("%ld\n", x);
x = -c;
printf("%ld\n", x);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译我正在使用GCC 4.4.7(它没有给我任何警告):
gcc -g -std=c99 -pedantic-errors -Wall -W check.c
Run Code Online (Sandbox Code Playgroud)
我的结果是:
-15
-15
4294967281
Run Code Online (Sandbox Code Playgroud)
问题是为什么两者unsigned char和unsigned short值都正确地"传播"到(签名)long,而unsigned int …
我在嵌入式Linux的C++/Qt项目中工作,我们经常"决定"反对我们处理器的局限性,特别是在更新用户界面中的图形时.由于这些限制(特别是我们前一段时间甚至更糟糕的情况),我会尽可能地优化代码,如果优化成本最低的话.我正在做的一个优化是始终对我正在处理的情况使用正确的整数值:qint8,qint16和qint32取决于我需要的值有多大.
但是前段时间我在某个地方读到,在可能的情况下,我不应该尝试使用最小的整数,我应该总是更喜欢使用与处理器容量相关的整数值,也就是说,如果我的处理器是32位的,那么即使不需要这么大的整数,我也应该总是使用qint32.在第一时刻,我无法理解为什么,但这个问题的答案表明,这是因为当处理器必须使用其"默认大小整数"时,处理器的性能会更高.
好吧,我不相信.首先没有提供实际的参考来证实这样的论点:我只是无法理解为什么从32位存储器空间写入和读取比使用32位整数更慢(并且给出的解释不是很容易理解,顺便说一句.其次,当我需要将数据从一侧传输到另一侧时,例如当使用Qt的信号和插槽机制时,我的应用程序上有一些时刻.由于我将数据从一个点传输到另一个点,不应该是较小的数据总能比较大的数据有所改进吗?我的意思是发送两个字符(不是通过引用)的信号不应该更快地完成工作然后发送两个32位整数?
事实上,虽然"处理器解释"建议使用处理器的特性,但其他情况则表明相反.例如,在处理数据库时,这个和这个线程都表明在使用较小版本的整数时有一个优势(即使只是在某些情况下).
所以,毕竟,当上下文允许或不允许时,我是否应该使用小类型的int?或者,当一种方法或另一种方法更有可能给出更好或更差的结果时,是否有一个案例列表?(例如,我在使用数据库时应使用int8和int16,但在所有其他情况下我的处理器的默认类型)
并且作为最后一个问题:Qt通常具有基于int的函数实现.在这种情况下,施法操作是否会通过使用次要整数来消除任何可能的改进?
我已经看到了这本书将以下代码计算机系统:一个程序员的角度来看,2/E.这很好用,并创建所需的输出.输出可以通过有符号和无符号表示的区别来解释.
#include<stdio.h>
int main() {
if (-1 < 0u) {
printf("-1 < 0u\n");
}
else {
printf("-1 >= 0u\n");
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
-1 >= 0u但是,上面的代码产生的代码与上面的代码相同,不是!换一种说法,
#include <stdio.h>
int main() {
unsigned short u = 0u;
short x = -1;
if (x < u)
printf("-1 < 0u\n");
else
printf("-1 >= 0u\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
收益率-1 < 0u.为什么会这样?我无法解释这一点.
请注意,我已经看到像类似的问题这样,但他们不帮助.
PS.正如@Abhineet所说,这种困境可以通过改变short来解决int.但是,怎么能解释这种现象呢?换句话说,-14个字节是0xff ff ff ff2个字节0xff ff.鉴于它们被解释为2s补码 …
c bit-manipulation integer-promotion twos-complement unsigned-integer