假设在C实现上(例如在x86 C编译器上)USHRT_MAX = 65535和INT_MAX = 2147483647.那么,以下陈述是否明确定义?
unsigned short product = USHRT_MAX * USHRT_MAX;
Run Code Online (Sandbox Code Playgroud)
根据C99标准中的以下内容,两个操作数都被提升为int(因为它int可以表示所有可能的值unsigned short),因此,结果没有明确定义,因为会发生溢出(65535 ^ 2 = 4294836225 > 2147483647),这意味着值product不是明确界定:
6.3.1.1-1
如果int可以表示原始类型的所有值,则该值将转换为int; 否则,它将转换为unsigned int.这些被称为整数促销.(48)所有其他类型由整数促销不变.
48)整数提升仅适用于:通常的算术转换,某些参数表达式,一元+, - 和〜运算符的操作数,以及移位运算符的两个操作数的一部分,由它们各自指定小节.
但是,根据以下内容,结果是明确定义的,因为涉及无符号操作数的计算不会溢出:
6.2.5-9
有符号整数类型的非负值范围是相应无符号整数类型的子范围,并且每种类型中相同值的表示是相同的.(31)涉及无符号操作数的计算永远不会溢出,因为结果是无法用结果无符号整数类型表示减去模数,该数字大于可由结果类型表示的最大值.
product上述陈述中的变量是否具有明确定义的值?
编辑:在下列情况下会发生什么?
unsigned short lhs = USHRT_MAX;
unsigned short rhs = USHRT_MAX;
unsigned short product = lhs * rhs;
Run Code Online (Sandbox Code Playgroud)
促销获胜。
第 5.2.4.2.1 节介绍了常量USHRT_MAX等:
下面给出的值应替换为适合在
#if预处理指令中使用的常量表达式。此外,除了CHAR_BIT和 之外MB_LEN_MAX,以下内容应替换为与根据整数提升转换的相应类型对象的表达式具有相同类型的表达式。
因此,乘法是在ints 上进行的,并且不涉及无符号操作数,毫无疑问,没有一致的方法来实现USHRT_MAX涉及无符号操作数 if 的操作USHRT_MAX < INT_MAX。因此你会出现溢出和未定义的行为。
关于补充的问题
编辑:在以下情况下应该发生什么?
Run Code Online (Sandbox Code Playgroud)unsigned short lhs = USHRT_MAX; unsigned short rhs = USHRT_MAX; unsigned short product = lhs * rhs;
那是完全相同的情况。的操作数*受到整数提升的影响,通过对和的值的假设,所有类型的值unsigned short都可以表示为s ,因此乘法在s 上,并且与指定的值会溢出。intUSHRT_MAXINT_MAXint
您需要将至少一个操作数转换为一种未提升为intin oerder 的无符号类型,以便对无符号操作数执行乘法。