首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在使用gcc时,是什么原因导致字符被签名或未签名?

在使用gcc时,是什么原因导致字符被签名或未签名?
EN

Stack Overflow用户
提问于 2017-09-28 07:12:33
回答 6查看 10.3K关注 0票数 51

如果C中的char (使用gcc)被签名或未签名,原因是什么?我知道标准并不是一个比另一个强,我可以从限制中检查CHAR_MINCHAR_MAX,但是我想知道在使用gcc时是什么触发了另一个

如果我阅读libgcc-6中的finds.h,我会发现有一个宏__CHAR_UNSIGNED__,它定义了一个“默认”字符,有符号或无符号,但我不确定这是否是编译器在编译时设置的。

我试图列出GCCs预定义的makros

代码语言:javascript
复制
$ gcc -dM -E -x c /dev/null | grep -i CHAR
#define __UINT_LEAST8_TYPE__ unsigned char
#define __CHAR_BIT__ 8
#define __WCHAR_MAX__ 0x7fffffff
#define __GCC_ATOMIC_CHAR_LOCK_FREE 2
#define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
#define __SCHAR_MAX__ 0x7f
#define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1)
#define __UINT8_TYPE__ unsigned char
#define __INT8_TYPE__ signed char
#define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
#define __CHAR16_TYPE__ short unsigned int
#define __INT_LEAST8_TYPE__ signed char
#define __WCHAR_TYPE__ int
#define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
#define __SIZEOF_WCHAR_T__ 4
#define __INT_FAST8_TYPE__ signed char
#define __CHAR32_TYPE__ unsigned int
#define __UINT_FAST8_TYPE__ unsigned char

但没能找到__CHAR_UNSIGNED__

背景:我在两台不同的机器上编译了一些代码:

桌面PC:

  • Debian GNU/Linux 9.1 (拉伸)
  • gcc版本6.3.0 20170516 (Debian 6.3.0-18)
  • Intel(R) Core(商标) i3-4150
  • libgcc-6-dev: 6.3.0-18
  • char被签名

覆盆子Pi3

  • Raspbian /Linux9.1(拉伸)
  • gcc版本6.3.0 20170516 (Raspbian6.3.0-18+rpi1 1)
  • ARMv7处理器rev 4 (v7l)
  • libgcc-6-dev: 6.3.0-18+rpi
  • char未签名

所以唯一明显的区别是CPU架构..。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2017-09-28 07:19:07

根据C11标准(read n1570),char可以是signedunsigned (因此实际上有两种类型的C)。确切地说,它是特定于实现的。

有些处理器指令集体系结构应用程序二进制接口倾向于signed字符(字节)类型(例如,因为它很好地映射到一些机器代码指令),而另一些则倾向于使用unsigned字符。

gcc甚至有一些几乎不应该使用的-fsigned-char-funsigned-char 选项 (因为更改它会破坏呼叫约定和ABI中的一些角落),除非您重新编译所有东西,包括您的C标准库

您可以在Linux上使用宏(7)<endian.h> (参见endian(3))或来检测您的系统。

在大多数情况下,您应该编写不依赖于这些内容的便携 C代码。您可以找到跨平台库(例如滑翔)来帮助您。

顺便说一句,gcc -dM -E -x c /dev/null还提供了__BYTE_ORDER__等,如果您想要一个无符号的8位字节,您应该使用<stdint.h>及其uint8_t (更便于移植和更易读)。标准limits.h定义了CHAR_MINSCHAR_MINCHAR_MAXSCHAR_MAX (您可以比较它们的等价性以检测signed char的实现),等等.

顺便说一句,您应该关心字符编码,但是现在大多数系统都使用到处都是。像libunistring这样的库是有用的。还请参阅,并记住,实际上,用UTF-8编码的Unicode字符可以跨越几个字节(即char-s)。

票数 53
EN

Stack Overflow用户

发布于 2017-09-28 07:25:04

默认情况取决于平台和本机代码集。例如,使用EBCDIC (通常是大型机)的机器必须使用unsigned char (或有CHAR_BIT > 8),因为C标准要求基本代码集中的字符为正,而EBCDIC则使用数字0为240之类的代码。(C11标准,§6.2.5 Types 2:声明为char类型的对象足够大,足以存储基本执行字符集的任何成员。如果基本执行字符集的一个成员存储在char对象中,则它的值保证为非负的。)

您可以控制GCC在-fsigned-char-funsigned-char选项中使用的符号。这是否是一个好主意是另一个讨论。

票数 42
EN

Stack Overflow用户

发布于 2017-09-28 07:46:28

字符类型charsignedunsigned,这取决于平台和编译器。

根据参考链接:

C和C++标准允许字符类型char是签名的无符号取决于平台和编译器。 大多数系统,包括x86 GNU/Linux和Microsoft,都使用有签名的char, 但是那些基于PowerPC和ARM处理器的处理器通常使用无符号字符。 这可能导致在对char类型具有不同默认值的平台之间移植程序时产生意外的结果。

GCC提供了选项-fsigned-char-funsigned-char来设置默认类型的char

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46463064

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档