首页 / 知识
关于在C中签名为无符号转换:在C中签名为无符号-始终安全吗?
2023-04-14 14:50:00

Signed to unsigned conversion in C - is it always safe?假设我有以下C代码。
这里正在进行什么隐式转换,并且此代码对于 简短答案
您的 长答案 根据C99标准:
在您的情况下,我们有一个未签名的int(
现在我们需要参考上面的(2)。通过添加
奖励:算术转换半WTF
您可以使用此链接在线尝试:https://repl.it/repls/QuickWhimsicalBytes 奖励:算术转换的副作用
通过将无符号值初始化为
由于上述转换规则,因此无论系统的带符号号码表示如何,都保证可以移植。有关更多信息,请参见此SO问题:使用-1将所有位设置为true是否安全? 从有符号到无符号的转换不一定只是复制或重新解释有符号值的表示。引用C标准(C99 6.3.1.3):
对于如今近乎普遍的二进制补码表示,规则确实对应于重新解释位。但是对于其他表示形式(符号和大小或1的补码),C实现仍必须安排相同的结果,这意味着转换不能仅复制这些位。例如,(unsigned)-1 == UINT_MAX,与表示形式无关。 通常,将C中的转换定义为对值而不是表示形式进行操作。 要回答原始问题:
i的值将转换为unsigned int,得出 (与无符号溢出不同,有符号溢出会调用未定义的行为。环绕是很常见的,但C标准不能保证这种环绕-编译器的优化可能会对进行不必要假设的代码造成严重破坏。) 参考圣经:
从有符号转换为无符号时,有两种可能性。最初为正的数字保持(或解释为)相同的值。原来是负数的数字现在将被解释为更大的正数。 当添加一个无符号变量和一个带符号变量(或任何二进制操作)时,两者都将隐式转换为无符号,这将导致巨大的结果。 因此,从结果上可能是巨大的和错误的意义上讲,这是安全的,但绝不会崩溃。 如先前的回答,您可以在有符号和无符号之间来回转换,而不会出现问题。有符号整数的边界大小写为-1(0xFFFFFFFF)。尝试对其进行加法和减法,您会发现您可以回退并使其正确。 但是,如果您要来回转换,我强烈建议您命名变量,以便清楚地知道它们是什么类型,例如:
太容易被更重要的问题分散注意力,并且忘记了如果没有提示就将变量命名为哪种类型,这太容易了。您不想强制转换为无符号,然后将其用作数组索引。
我将被转换为无符号整数。
在明确定义的意义上说是安全的(请参阅https://stackoverflow.com/a/50632/5083516)。 规则通常用难以理解的标准来编写,但是本质上无论有符号整数使用哪种表示形式,无符号整数都将包含数字的2的补码表示形式。 加,减和乘将在这些数字上正常工作,从而导致另一个无符号整数包含表示"实际结果"的二进制补码。 除法和转换为较大的无符号整数类型将具有定义明确的结果,但这些结果将不是"真实结果"的2的补码表示。
虽然标准定义了从有符号到无符号的转换,但是反向实现是由实现定义的,gcc和msvc都定义了转换,这样当将无符号整数中存储的2的补码转换回有符号整数时,您将获得"真实结果" 。我希望您只会在不使用2的补码作为有符号整数的晦涩系统上找到其他行为。
https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html#Integers-implementation 可怕的答案 Ozgur Ozcitak
这是完全错误的。 马特斯·弗雷德里克森
这也是错误的。由于无符号类型中的填充位,如果无符号整数具有相同的精度,则可以将它们提升为整数。 SMH
错误。也许会,也许不会。
错误。如果它导致溢出或保留值,则为未定义行为。 匿名
错误。取决于int相对于unsigned int的精度。 泰勒·普莱斯
错误。尝试存储有符号整数范围之外的值会导致未定义的行为。 现在我终于可以回答这个问题了。 如果int的精度等于unsigned int,则u将被提升为有符号int,您将从表达式(u + i)中获得值-4444。现在,如果u和i具有其他值,则可能会出现溢出和未定义的行为,但是使用这些确切的数字,您将得到-4444 [1]。该值的类型为int。但是您正在尝试将该值存储到一个无符号的int中,以便将其转换为一个无符号的int,结果最终将具有(UINT_MAX + 1)-4444。 如果unsigned int的精度大于int的精度,则有符号的int将被提升为一个无符号的int,其值将为(UINT_MAX + 1)-5678,并将其添加到另一个无符号的int 1234中。其他值,这些表达式使表达式落在{0..UINT_MAX}范围之外,将添加或减去值(UINT_MAX + 1),直到结果DOES落在{0..UINT_MAX)范围内,并且不会发生未定义的行为。 什么是精度? 整数具有填充位,符号位和值位。无符号整数显然没有符号位。进一步保证了无符号字符没有填充位。整数具有的值位数是其精度。 [陷阱] 如果存在填充位,则不能单独使用macrosizeof宏来确定整数的精度。并且字节的大小不必是C99定义的八位位组(八位)。 [1]溢出可能发生在两个点之一。加法之前(升级期间)中的任何一个-当您的unsigned int太大而无法容纳在int内部时。即使无符号int在int范围内,加法后也可能发生溢出,加法后结果仍然可能溢出。 无关紧要的是,我是一名正在寻找工作的研究生;) |
最新内容
相关内容
linux地址转换命令是?
linux地址转换命令是?,地址,系统,代码,密码,网络,信息,服务,电脑,设备,报告,配置LINUX的IP命令1、(1)Ifconfig命令 第一种使用ifconfig命令配置linux挂载的命令名为?
linux挂载的命令名为?,系统,设备,数据,网络,信息,命令,工作,检测,情况,电脑,虚拟机下linux如何使用mount挂载cdrom?1、找到光盘的完整路径名。linux命令时间转换?
linux命令时间转换?,时间,系统,命令,信息,国家,大陆,概念,终端,时区,时分,Linux系统的服务器时间要怎么进行修改输入这条命令系统时间会设置为linux终端命令符号?
linux终端命令符号?,系统,终端,设备,流向,概念,命令,符号,用户,表示,代表,Linux中的常用符号解释1、通配符:“*”、“?”和DOS下一样,当我们不知linux命令时间戳转换?
linux命令时间戳转换?,时间,系统,地址,信息,工作,代码,标准,工具,形态,命令,linux时间戳命令1、可以使用touch命令修改Linux系统中一个文件的mlinux转换行列命令?
linux转换行列命令?,工作,地址,信息,网络,系统,命令,标准,电脑,环境,目录,linux指令转换为cmd指令首先打开电脑,点击电脑桌面左下角的搜索框,输linux地址转换命令?
linux地址转换命令?,地址,系统,代码,信息,设备,网络,服务,密码,状态,报告,linux怎么修改localaddress地址1、首先,打开Linux终端系统,随后在系统转换格式命令linux?
转换格式命令linux?,系统,情况,地址,命令,设备,工作,基础,发行,工具,数据,Linux命令大全Linux命令大全以下是一些常用的 Linux 命令:ls:列出当前linux转换图形命令?
linux转换图形命令?,系统,工作,密码,工具,地址,命令,地方,环境,软件,信息,Linux命令行与图形界面切换方法系统默认启动到图形界面。登录后输入linux时间转换命令?
linux时间转换命令?,时间,系统,国家,大陆,命令,信息,标准,电脑,时区,终端,linux修改时区时间命令1、目录方法1:使用命令行打开终端应用程序。查linux按符号查找命令?
linux按符号查找命令?,系统,命令,字符串,灵活,工具,文件,文件名,选项,参数,模式,求助Linux下带特殊字符的字符串查找方法!linux在文件中怎么查linux命令模式转换?
linux命令模式转换?,工作,系统,数据,标准,命令,地址,信息,模式,设备,密码,linux系统常用操作命令1、linux常用命令有pwd命令、cd命令、ls命令