C語言怎么計算數(shù)據(jù)類型范圍?

之前在網(wǎng)上看到的一個討論,是誰決定了數(shù)據(jù)類型的范圍?
比如說,怎么確定 char 就是 ?-128~127 ,而不是 -127~128 呢?
說下規(guī)定
signed 的取值范圍是 -(2N-1) to 2N-1 - 1
unsigned 的取值范圍是 0 to (2N-1) + (2N-1 - 1)
只要記住一點就好了,就是最小值,有符號的最小值是 -128 開始,因為0占用了一個位置,所以最大值就只能是127。
無符號的最小值是 0 ,那最大值就是255了。
#怎么計算呢?
如果我們知道 #include 這個頭文件后,可能就很容易了,因為最大值最小值都在這里面有宏定義。
#看一個老外的代碼
#include?
#include?
#include?
int?main()
{
????printf("Range?of?signed?char?%d?to?%d\n",?SCHAR_MIN,?SCHAR_MAX);
????printf("Range?of?unsigned?char?0?to?%d\n\n",?UCHAR_MAX);
????printf("Range?of?signed?short?int?%d?to?%d\n",?SHRT_MIN,?SHRT_MAX);
????printf("Range?of?unsigned?short?int?0?to?%d\n\n",?USHRT_MAX);
????printf("Range?of?signed?int?%d?to?%d\n",?INT_MIN,?INT_MAX);
????printf("Range?of?unsigned?int?0?to?%lu\n\n",?UINT_MAX);
????printf("Range?of?signed?long?int?%ld?to?%ld\n",?LONG_MIN,?LONG_MAX);
????printf("Range?of?unsigned?long?int?0?to?%lu\n\n",?ULONG_MAX);
????//?In?some?compilers?LLONG_MIN,?LLONG_MAX
????printf("Range?of?signed?long?long?int?%lld?to?%lld\n",?LONG_LONG_MIN,?LONG_LONG_MAX);?
????//?In?some?compilers?ULLONG_MAX
????printf("Range?of?unsigned?long?long?int?0?to?%llu\n\n",?ULONG_LONG_MAX);?
????printf("Range?of?float?%e?to?%e\n",?FLT_MIN,?FLT_MAX);
????printf("Range?of?double?%e?to?%e\n",?DBL_MIN,?DBL_MAX);
????printf("Range?of?long?double?%e?to?%e\n",?LDBL_MIN,?LDBL_MAX);
????return?0;
}
#輸出
Range?of?signed?char?-128?to?127
Range?of?unsigned?char?0?to?255
Range?of?signed?short?int?-32768?to?32767
Range?of?unsigned?short?int?0?to?65535
Range?of?signed?int?-2147483648?to?2147483647
Range?of?unsigned?int?0?to?4294967295
Range?of?signed?long?int?-2147483648?to?2147483647
Range?of?unsigned?long?int?0?to?4294967295
Range?of?signed?long?long?int?-9223372036854775808?to?9223372036854775807
Range?of?unsigned?long?long?int?0?to?18446744073709551615
Range?of?float?1.175494e-038?to?3.402823e+038
Range?of?double?2.225074e-308?to?1.797693e+308
Range?of?long?double?-0.000000e+000?to?-1.#QNAN0e+000
--------------------------------
#尷尬了
要是我記不住那個頭文件,或者是我記不住那些宏,那要怎么搞呢?所以就有了下面的代碼
#include?"string.h"
#include?"stdio.h"
int?main()
{
?printf("Range?signed?char?%lld?to?%lld\n",-(1LL?<(8*sizeof(char)?-1)),(1LL?<(8*sizeof(char)?-1))?-?1);
?printf("Range?unsigned?char?0?to?%lld\n",(1LL?<(8*sizeof(char)?-1))?+?(1LL?<(8*sizeof(char)?-1))?-?1);
?
?printf("Range?signed?int?%lld?to?%lld\n",-(1LL?<(8*sizeof(int)?-1)),(1LL?<(8*sizeof(int)?-1))?-?1);
?printf("Range?unsigned?int?0?to?%lld\n",(1LL?<(8*sizeof(int)?-1))?+?(1LL?<(8*sizeof(int)?-1))?-?1);
?
?printf("Range?signed?long?%lld?to?%lld\n",-(1LL?<(8*sizeof(long)?-1)),(1LL?<(8*sizeof(long)?-1))?-?1);
?printf("Range?unsigned?long?0?to?%lld\n",(1LL?<(8*sizeof(long)?-1))?+?(1LL?<(8*sizeof(long)?-1))?-?1);
?
?
?printf("Range?signed?long?long?%lld?to?%lld\n",-(1LL?<(8*sizeof(long?long)?-1)),(1LL?<(8*sizeof(long?long)?-1))?-?1);
?printf("Range?unsigned?long?long?0?to?%llu\n",(1LL?<(8*sizeof(long?long)?-1))?+?(1LL?<(8*sizeof(long?long)?-1))?-?1);
}
#輸出
Range?signed?char?-128?to?127
Range?unsigned?char?0?to?255
Range?signed?int?-2147483648?to?2147483647
Range?unsigned?int?0?to?4294967295
Range?signed?long?-2147483648?to?2147483647
Range?unsigned?long?0?to?4294967295
Range?signed?long?long?-9223372036854775808?to?9223372036854775807
Range?unsigned?long?long?0?to?18446744073709551615
--------------------------------
Process?exited?after?0.03036?seconds?with?return?value?51
如果對上面的不是很理解的話,可以看看我這個圖片

#還有一種寫法
這里使用了庫函數(shù)pow,但是這個函數(shù)返回值是double,這里需要特別注意一下。
#include?"stdio.h"
#include?"math.h"
int?main()
{
?printf("signed?char?%ld?to?%ld\n",(int)-pow(2,sizeof(char)*8-1),(int)pow(2,sizeof(char)*8-1)?-1);
?printf("unsigned?char?0?to?%ld\n",(int)pow(2,sizeof(char)*8)?-1);
?printf("signed?int?%lld?to?%lld\n",(long?long)-pow(2,sizeof(int)*8-1),(long?long)pow(2,sizeof(int)*8-1)?-1);
?printf("unsigned?int?0?to?%lld\n",(long?long)pow(2,sizeof(int)*8)?-?1);
????return?0;
}
#輸出
signed?char?-128?to?127
unsigned?char?0?to?255
signed?int?-2147483648?to?2147483647
unsigned?int?0?to?4294967295
--------------------------------
因為pow的返回值是 double 使用的時候需要特別注意
# 說一下
數(shù)值在計算機里面都是用補碼的形式存儲的,補碼和原碼是不一樣的,特別是負數(shù)。
正數(shù)的原碼、反碼、補碼都相同。
原碼: 最高位是符號位,其余為是數(shù)值位「8421定律」,最高位是0表示正數(shù),1表示負數(shù)。
負數(shù)的反碼: 在原碼的基礎(chǔ)上,符號位不變,數(shù)值位取反。
負數(shù)的補碼: 在反碼的基礎(chǔ)上加 1 。

評論
圖片
表情
