C -printf 铸造
C -printf casting
我想玩一下有符号短整型变量的溢出。我将变量 a1 声明为 short,然后我给出较大的正值,零是 'considered' 正数,因此有符号整数的最大值(短,整数,长或 long long) 必须是 exp2(8*sizeof(variable)-1)-1,不是吗?
#include<stdio.h>
#include <math.h>
int main()
{
int short a1=2;
a1=exp2(8*sizeof(a1)-1)-1;
printf("The last value that DOES NOT overflow in a integer as \'signed short\' (%i bytes) is %hi.\nIf I define this variable equal to this value I get the value in the variable %hi.\n",(unsigned char) sizeof(a1), (short) exp2(8*sizeof(a1)-1)-1, a1);/*key word short from "(short) exp2(8*sizeof(a1)-1)-1"*/
a1=exp2(8*sizeof(a1)-1);/*warning-overflow: "warning: overflow in implicit constant conversion [-Woverflow]"*/
printf("The 1st value that overflows in a integer as \'signed short\' (%i bytes) is %i.\nIf I define this variable equal to this value instead I get the value in the variable %i.\n",(unsigned char) sizeof(a1), (int) exp2(8*sizeof(a1)-1), a1);/*key word int from "(int) exp2(8*sizeof(a1)-1)"*/
return;
}
所以我得到了一个溢出警告,正如我想要的那样,这就是这段代码的目标:
warning: overflow in implicit constant conversion [-Woverflow]
然后./a.out,输出为
The last value that DOES NOT overflow in a integer as 'signed short'
(2 bytes) is 32766.
If I define this variable equal to this value I get the value in the variable 32767.
The 1st value that overflows in a integer as 'signed short' (2 bytes) is 32768.
If I define this variable equal to this value instead I get the value in the variable 32767.
第二个 printf 工作正常,不是吗?但是我认为第一个应该对变量 a1 (a1=exp2(8*sizeof(a1)-1)-1;) 的 printf 和 (short) exp2(8*sizeof(a1)- 1)-1。
我重写的更清楚:
#include<stdio.h>
#include <math.h>
#include <limits.h>
int main()
{
int short a1=exp2(CHAR_BIT*sizeof(a1)-1)-1;
printf("It should be %hi = %hi.\n",(short) exp2(CHAR_BIT*sizeof(a1)-1)-1, a1);
return;
}
输出为
It should be 32766 = 32767.
当我认为应该是:"It should be 32767 = 32767."
请帮我理解一下
@chux
已解决
#include<stdio.h>
#include <math.h>
#include <limits.h>
#include <float.h>
int main()
{
int short a1=exp2(CHAR_BIT*sizeof(a1)-1)-1;
printf("It should be %hi = %hi.\n",(short) (round(exp2(CHAR_BIT*sizeof(a1)-1))-1), a1);
return;
}
我必须指出这里的括号很重要,没有它们,我的意思是 (short) round(exp2(CHAR_BIT*sizeof(a1)-1))-1
,你会得到另一个值。
double
到 int
截断。
未发布的非标准函数 exp2()
当然是 double exp2(double x)
并且没有很好地实现。
当将小 int
转换为 double
时,就像将参数传递给 exp2(8*sizeof(a1)-1
一样,转换是准确的。
当获取结果并转换为 short
时,如 short a1=exp2()
, 就是问题所在。假设 exp2(15)
的结果略有错误,是 32767.99999999 而不是希望的 32768.0。然后转换为 int
是 "truncation toward 0".
通常解决方案是在截断前舍入。
// add vvvvvv v
(short) round(exp2(CHAR_BIT*sizeof(a1)-1)) - 1
尝试使用以下方法进行调试,以足够精确地查看 return 值。
#include <float.h>
int short a1;
printf("%.*f\n", DBL_DECIMAL_DIG - 1, (double) exp2(CHAR_BIT*sizeof(a1)-1));
我想玩一下有符号短整型变量的溢出。我将变量 a1 声明为 short,然后我给出较大的正值,零是 'considered' 正数,因此有符号整数的最大值(短,整数,长或 long long) 必须是 exp2(8*sizeof(variable)-1)-1,不是吗?
#include<stdio.h>
#include <math.h>
int main()
{
int short a1=2;
a1=exp2(8*sizeof(a1)-1)-1;
printf("The last value that DOES NOT overflow in a integer as \'signed short\' (%i bytes) is %hi.\nIf I define this variable equal to this value I get the value in the variable %hi.\n",(unsigned char) sizeof(a1), (short) exp2(8*sizeof(a1)-1)-1, a1);/*key word short from "(short) exp2(8*sizeof(a1)-1)-1"*/
a1=exp2(8*sizeof(a1)-1);/*warning-overflow: "warning: overflow in implicit constant conversion [-Woverflow]"*/
printf("The 1st value that overflows in a integer as \'signed short\' (%i bytes) is %i.\nIf I define this variable equal to this value instead I get the value in the variable %i.\n",(unsigned char) sizeof(a1), (int) exp2(8*sizeof(a1)-1), a1);/*key word int from "(int) exp2(8*sizeof(a1)-1)"*/
return;
}
所以我得到了一个溢出警告,正如我想要的那样,这就是这段代码的目标:
warning: overflow in implicit constant conversion [-Woverflow]
然后./a.out,输出为
The last value that DOES NOT overflow in a integer as 'signed short' (2 bytes) is 32766. If I define this variable equal to this value I get the value in the variable 32767. The 1st value that overflows in a integer as 'signed short' (2 bytes) is 32768. If I define this variable equal to this value instead I get the value in the variable 32767.
第二个 printf 工作正常,不是吗?但是我认为第一个应该对变量 a1 (a1=exp2(8*sizeof(a1)-1)-1;) 的 printf 和 (short) exp2(8*sizeof(a1)- 1)-1。 我重写的更清楚:
#include<stdio.h>
#include <math.h>
#include <limits.h>
int main()
{
int short a1=exp2(CHAR_BIT*sizeof(a1)-1)-1;
printf("It should be %hi = %hi.\n",(short) exp2(CHAR_BIT*sizeof(a1)-1)-1, a1);
return;
}
输出为
It should be 32766 = 32767.
当我认为应该是:"It should be 32767 = 32767."
请帮我理解一下
@chux
已解决#include<stdio.h>
#include <math.h>
#include <limits.h>
#include <float.h>
int main()
{
int short a1=exp2(CHAR_BIT*sizeof(a1)-1)-1;
printf("It should be %hi = %hi.\n",(short) (round(exp2(CHAR_BIT*sizeof(a1)-1))-1), a1);
return;
}
我必须指出这里的括号很重要,没有它们,我的意思是 (short) round(exp2(CHAR_BIT*sizeof(a1)-1))-1
,你会得到另一个值。
double
到 int
截断。
未发布的非标准函数 exp2()
当然是 double exp2(double x)
并且没有很好地实现。
当将小 int
转换为 double
时,就像将参数传递给 exp2(8*sizeof(a1)-1
一样,转换是准确的。
当获取结果并转换为 short
时,如 short a1=exp2()
, 就是问题所在。假设 exp2(15)
的结果略有错误,是 32767.99999999 而不是希望的 32768.0。然后转换为 int
是 "truncation toward 0".
通常解决方案是在截断前舍入。
// add vvvvvv v
(short) round(exp2(CHAR_BIT*sizeof(a1)-1)) - 1
尝试使用以下方法进行调试,以足够精确地查看 return 值。
#include <float.h>
int short a1;
printf("%.*f\n", DBL_DECIMAL_DIG - 1, (double) exp2(CHAR_BIT*sizeof(a1)-1));