简体   繁体   English

C:gcc隐式将signed char转换为unsigned char,反之亦然?

[英]C: gcc implicitly converts signed char to unsigned char and vice versa?

I'm trying to learn C at got stuck with datatype-sizes at the moment. 我正在努力学习C,因为目前我已经陷入了数据类型。

Have a look at this code snippet: 看看这段代码:

#include <stdio.h>
#include <limits.h>

int main() {
    char a = 255;
    char b = -128;
    a = -128;
    b = 255;
    printf("size: %lu\n", sizeof(char));
    printf("min: %d\n", CHAR_MIN);
    printf("max: %d\n", CHAR_MAX);
}

The printf-output is: printf输出是:

size: 1
min: -128
max: 127

How is that possible? 怎么可能? The size of char is 1 Byte and the default char seems to be signed (-128...127). char的大小是1 Byte,默认的char似乎是签名的(-128 ... 127)。 So how can I assign a value > 127 without getting an overflow warning (which I get when I try to assign -128 or 256)? 那么如何在不发出溢出警告的情况下分配值> 127(我在尝试分配-128或256时得到)? Is gcc automatically converting to unsigned char? gcc会自动转换为unsigned char吗? And then, when I assign a negative value, does it convert back? 然后,当我指定负值时,它会转换回来吗? Why does it do so? 它为什么这样做? I mean, all this implicitness wouldn't make it easier to understand. 我的意思是,所有这些隐含性都不会让它更容易理解。

EDIT: 编辑:

Okay, it's not converting anything: 好吧,它没有转换任何东西:

char a = 255;
char b = 128;
printf("%d\n", a);    /* -1 */
printf("%d\n", b);    /* -128 */

So it starts counting from the bottom up. 所以它从下往上开始计算。 But why doesn't the compiler give me a warning? 但为什么编译器没有给我一个警告? And why does it so, when I try to assign 256? 为什么会这样,当我尝试分配256?

See 6.3.1.3/3 in the C99 Standard 参见C99标准中的 6.3.1.3/3

... the new type is signed and the value cannot be represented in it; ...新类型已签名且值无法在其中表示; either the result is implementation-defined or an implementation-defined signal is raised. 结果是实现定义的,或者引发实现定义的信号。

So, if you don't get a signal (if your program doesn't stop) read the documentation for your compiler to understand what it does. 因此,如果您没有收到信号(如果您的程序没有停止),请阅读编译器的文档以了解它的作用。


gcc documents the behaviour ( in http://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html#Integers-implementation ) as gcc将行为记录在http://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html#Integers-implementation

  • The result of, or the signal raised by, converting an integer to a signed integer type when the value cannot be represented in an object of that type (C90 6.2.1.2, C99 6.3.1.3). 当该值无法在该类型的对象中表示时,将整数转换为有符号整数类型的结果或信号(C90 6.2.1.2,C99 6.3.1.3)。

For conversion to a type of width N, the value is reduced modulo 2^N to be within range of the type; 为了转换为宽度N的类型,该值以2 ^ N的模数减少到该类型的范围内; no signal is raised. 没有信号被提出。

how can I assign a value > 127 如何指定值> 127

The result of converting an out-of-range integer value to a signed integer type is either an implementation-defined result or an implementation-defined signal (6.3.1.3/3). 将超出范围的整数值转换为有符号整数类型的结果是实现定义的结果或实现定义的信号(6.3.1.3/3)。 So your code is legal C, it just doesn't have the same behavior on all implementations. 所以你的代码是合法的C,它在所有实现上都没有相同的行为。

without getting an overflow warning 没有溢出警告

It's entirely up to GCC to decide whether to warn or not about valid code. 由GCC决定是否警告有效代码完全取决于GCC。 I'm not quite sure what its rules are, but I get a warning for initializing a signed char with 256 , but not with 255 . 我不太确定它的规则是什么,但我得到一个警告,用256初始化一个带signed char ,但不是255 I guess that's because a warning for code like char a = 0xFF would normally not be wanted by the programmer, even when char is signed. 我想这是因为程序员通常不会想要像char a = 0xFF这样的代码的警告,即使char已签名。 There is a portability issue, in that the same code on another compiler might raise a signal or result in the value 0 or 23 . 存在可移植性问题,因为另一个编译器上的相同代码可能会引发信号或导致值023

-pedantic enables a warning for this (thanks, pmg), which makes sense since -pedantic is intended to help write portable code. -pedantic启用此警告(感谢,pmg),这是有道理的,因为-pedantic旨在帮助编写可移植代码。 Or arguably doesn't make sense, since as R.. points out it's beyond the scope of merely putting the compiler into standard-conformance mode. 或者可以说没有意义,因为R ..指出它超出了仅仅将编译器置于标准一致性模式的范围。 However, the man page for gcc says that -pedantic enables diagnostics required by the standard. 但是,gcc的手册页说-pedantic可以启用标准所需的诊断。 This one isn't, but the man page also says: 这个不是,但是手册页也说:

Some users try to use -pedantic to check programs for strict ISO C conformance. 一些用户尝试使用-pedantic来检查程序是否符合严格的ISO C标准。 They soon find that it does not do quite what they want: it finds some non-ISO practices, but not all---only those for which ISO C requires a diagnostic, and some others for which diagnostics have been added. 他们很快发现它并没有完全符合他们的要求:它发现了一些非ISO实践,但并非全部 - 只有ISO C需要诊断的那些,以及其他一些已经添加了诊断的实践。

This leaves me wondering what a "non-ISO practice" is, and suspecting that char a = 255 is one of the ones for which a diagnostic has been specifically added. 这让我想知道什么是“非ISO实践”,并且怀疑char a = 255是专门添加诊断的那个之一。 Certainly "non-ISO" means more than just things for which the standard demands a diagnostic, but gcc obviously is not going so far as to diagnose all non-strictly-conforming code of this kind. 当然,“非ISO”不仅仅意味着标准需要诊断的东西,但gcc显然还没有诊断出所有非严格一致的代码。

I also get a warning for initializing an int with ((long long)UINT_MAX) + 1 , but not with UINT_MAX . 我也收到一个警告,用((long long)UINT_MAX) + 1初始化一个int ,但不是UINT_MAX Looks as if by default gcc consistently gives you the first power of 2 for free, but after that it thinks you've made a mistake. 看起来好像默认情况下gcc一直给你免费的第一个2的幂,但在那之后它认为你犯了一个错误。

Use -Wconversion to get a warning about all of those initializations, including char a = 255 . 使用-Wconversion获取有关所有这些初始化的警告,包括char a = 255 Beware that will give you a boatload of other warnings that you may or may not want. 请注意,这会给你一大堆你可能想要或不想要的其他警告。

all this implicitness wouldn't make it easier to understand 所有这些隐含性都不会让它更容易理解

You'll have to take that up with Dennis Ritchie. 你必须要与Dennis Ritchie合作。 C is weakly-typed as far as arithmetic types are concerned. 就算术类型而言,C是弱类型的。 They all implicitly convert to each other, with various levels of bad behavior when the value is out of range depending on the types involved. 当值超出范围时,它们都隐含地相互转换,具有各种级别的不良行为,具体取决于所涉及的类型。 Again, -Wconversion warns about the dangerous ones. 同样, -Wconversion警告危险的。

There are other design decisions in C that mean the weakness is quite important to avoid unwieldy code. C中还有其他设计决策意味着弱点对于避免笨重的代码非常重要。 For example, the fact that arithmetic is always done in at least an int means that char a = 1, b = 2; a = a + b 例如,算术总是在至少一个int完成的事实意味着char a = 1, b = 2; a = a + b char a = 1, b = 2; a = a + b involves an implicit conversion from int to char when the result of the addition is assigned to a . 当将加法结果赋给a时, char a = 1, b = 2; a = a + b涉及从intchar的隐式转换。 If you use -Wconversion , or if C didn't have the implicit conversion at all, you'd have to write a = (char)(a+b) , which wouldn't be too popular. 如果你使用-Wconversion ,或者C根本没有隐式转换,你必须写a = (char)(a+b) ,这不会太受欢迎。 For that matter, char a = 1 and even char a = 'a' are both implicit conversions from int to char , since C has no literals of type char . 就此而言, char a = 1和even char a = 'a'都是从intchar隐式转换,因为C没有char类型的文字。 So if it wasn't for all those implicit conversions either various other parts of the language would have to be different, or else you'd have to absolutely litter your code with casts. 因此,如果不是所有那些隐式转换,或者语言的其他各个部分都必须是不同的,否则你必须绝对不会使用强制转换来丢弃你的代码。 Some programmers want strong typing, which is fair enough, but you don't get it in C. 有些程序员想要强打字,这很公平,但你不能用C语言。

Simple solution : 简单方案

see signed char can have value from -128 to 127 okey so now when you are assigning 129 to any char value it will take 127(this is valid) + 2(this additional) = -127 看看signed char的值可以从-128到127 okey所以现在当你为任何char值赋值129时它将需要127(这是有效的)+ 2(这个附加的)= -127
(give char a=129 & print it value comes -127) (给char = 129并打印它值-127)

look char register can have value like.. ...126,127,-128,-127,-126...-1,0,1,2.... 看看char寄存器可以有... ... 126,127,-128,-127,-126 ......- 1,0,1,2 ....

which ever you will assign final value will come by this calculation ...!! 你将分配最终价值将来自这个计算... !!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM