我试过执行以下程序:
#include <stdio.h>
int main() {
signed char a = -5;
unsigned char b = -5;
int c = -5;
unsigned int d = -5;
if (a == b)
printf("\r\n char is SAME!!!");
else
printf("\r\n char is DIFF!!!");
if (c == d)
printf("\r\n int is SAME!!!");
else
printf("\r\n int is DIFF!!!");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
对于这个程序,我得到输出:
char是DIFF !!! int是相同的!
为什么我们两者都有不同的输出?
输出应该如下?
char是相同的!int是相同的!
一个键盘连接.
我经常使用在C++中使用字节时使用char的库.另一种方法是将"Byte"定义为unsigned char,但这不是他们决定使用的标准.我经常将C#中的字节传递给C++ dll并将它们转换为char以与库一起工作.
当向其他简单类型转换为字符或字符时,可能会出现一些副作用.具体来说,什么时候你已经处理了这个破碎的代码,你是怎么发现它是因为char签名?
幸运的是我没有在我的代码中碰到这个,在学校的嵌入式系统类中使用了一个char签名的转换技巧.我希望更好地理解这个问题,因为我觉得它与我正在做的工作有关.
我最近读到了之间的区别
char
unsigned char
Run Code Online (Sandbox Code Playgroud)
和
signed char
Run Code Online (Sandbox Code Playgroud)
是特定于平台的.
我不能完全理解这个问题?这是否意味着位序列可以从一个平台到另一个平台变化,即平台1,标志是第一位,平台2标志可能在末尾?你会怎么对这个代码?
基本上我的问题来自于看到这一行:
typedef unsigned char byte;
Run Code Online (Sandbox Code Playgroud)
我不明白标牌的相关性?
有没有一种简单的方法来确定浮点数的符号?
我进行了实验并想出了这个:
#include <iostream>
int main(int argc, char** argv)
{
union
{
float f;
char c[4];
};
f = -0.0f;
std::cout << (c[3] & 0x10000000) << "\n";
std::cin.ignore();
std::cin.get();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
其中(c [3]&0x10000000)为负数给出的值> 0但我认为这要求我做出以下假设:
如果任何这些假设错误或者我错过了任何假设,请纠正我.
通常,价值观是积极的.例如,TCP/UDP序列号始终为正值.两者int并unsigned int有足够大的存储即使是最大的sequence number,所以我可以使用这些类型.当已知值为正值时,还有许多其他示例.
unsigned当常规signed类型的容量足够(并且通常绰绰有余)时,是否有任何理由使用类型?
我个人倾向于使用常规类型,因为:
int可能比uint或更具可读性unsigned intUINT等.使用unsignedI型的原因可以想象:
浮点值是不精确的,这就是为什么我们应该很少在比较中使用严格的数字相等.例如,在Java中打印false(如ideone.com上所示):
System.out.println(.1 + .2 == .3);
// false
Run Code Online (Sandbox Code Playgroud)
通常,比较浮点计算结果的正确方法是查看某些预期值的绝对差值是否小于某个容许的epsilon.
System.out.println(Math.abs(.1 + .2 - .3) < .00000000000001);
// true
Run Code Online (Sandbox Code Playgroud)
问题是某些操作是否可以产生确切的结果.我们知道,任何非有限浮点值x(即要么NaN或无穷大),x - x是ALWAYS NaN.
但如果x是有限的,这是否有保证?
x * -1 == -xx - x == 0(特别是我对Java行为最感兴趣,但也欢迎其他语言的讨论.)
对于它的价值,我认为(我可能在这里错了)答案是肯定的!我认为这归结为是否对于任何有限的IEEE-754浮点值,其加法逆是总是可计算的.由于例如float并且double只有一个专用位用于符号,这似乎是这种情况,因为它只需要翻转符号位来找到加法逆(即有效数应保持不变).
language-agnostic floating-point precision ieee-754 signedness
我在我的代码中有以下定义
#define PRODUCTNAME "SomeName"
Run Code Online (Sandbox Code Playgroud)
我想用函数发送它com_reply(unsigned char* msg, uint16_t lenght).
现在我得到一个警告,我的论点在签名方面有所不同.我知道问题是什么以及为什么com_reply使用unsigned char*而不是char*,我只是想知道:
如何定义我的字符串,unsigned char*以便我可以在整个程序中使用它而不会在整个地方收到警告.
编辑:
严格来说,我在这里有多个定义,主要原因是有一个BANNER定义由其他几个定义组成,如下所示:
#define PRODUCTNAME "SomeName"
#define PRODUCTDATE "2013-03-30"
#define BANNER PRODUCTNAME " (" PRODUCTDATE ")"
Run Code Online (Sandbox Code Playgroud)
我应该创建const变量并在程序启动时连接它们而不是在这里使用定义吗?
注意:这个问题是关于位移运算符<<和>> 的第二个操作数的符号.完全没有第一个操作数.
CERT INT34-C,部分:不要移位负数位...
并不是说它需要理由,但他们证明这是不确定的行为.
我本以为这条规则很有意义,因为如果你想换另一条路,那么使用适当的移位算子移动另一个方向的正位数.
因此,如果在C中,移位负位数是不必要的和未定义的,为什么<<或>>的第二个操作数甚至允许被签名?
MISRA-C:2004,例如(无论你怎么想MISRA喜欢或不喜欢)在6.10.2节中,作为解释结果的类型仅取决于第一个操作数的副作用,说"第二个操作数可以是任何有符号或无符号整数类型".[强调我的]
为什么邀请人们在位移中使用带符号的第二个操作数?为什么允许呢?有没有编译器警告过它?
Clojure的位移操作似乎都返回64位long结果,即使对于32位int参数也是如此.这不是一个实质性的问题bit-shift-left:
user=> (format "%08x" (unchecked-int (bit-shift-left (unchecked-int 0x12345678) 4)))
"23456780"
user=> (format "%08x" (unchecked-int (bit-shift-left (unchecked-int 0xf2345678) 4)))
"23456780"
Run Code Online (Sandbox Code Playgroud)
但是,这成为负数无符号右移的问题:
user=> (format "%08x" (unchecked-int (unsigned-bit-shift-right (unchecked-int 0xf2345678) 4)))
"ff234567"
Run Code Online (Sandbox Code Playgroud)
当然,正确的答案是0f234567.
在Clojure中实现32位无符号右移的最有效方法是什么?
由于在C中定义了转换和操作的方式,因此使用有符号或无符号变量似乎很少:
uint8_t u; int8_t i;
u = -3; i = -3;
u *= 2; i *= 2;
u += 15; i += 15;
u >>= 2; i >>= 2;
printf("%u",u); // -> 2
printf("%u",i); // -> 2
Run Code Online (Sandbox Code Playgroud)
那么,是否有一套规则可以告诉变量的符号在哪些条件下确实有所不同?