c和c++各种类型数据左移溢出对比

溢出原理参考:C语言的整型溢出问题 | 酷 壳 - CoolShell

c完整测试代码:

 1 #include<stdio.h>
 2 main(){
 3 //int
 4     printf("int:\n");
 5     int j=1;  //<<31==2147483648
 6             // 1<<32==1
 7             // (1<<32)-1==0
 8             // (1<<32)-2==4294967295
 9     for(int i=30;i<(1<<5)+1;i++)
10         printf("1<<%d==%d\n",i,j<<i);
11     printf("(1<<%d)-1==%d\n",31,(j<<31)-1);
12     printf("(1<<%d)-1==%d\n",32,(j<<32)-1);
13     printf("(1<<%d)-2==%d\n",32,(j<<32)-2);
14 // unsigned int
15     printf("\nunsigned int:\n");
16     unsigned int j2=1;//1<<30==1073741824
17                     // 1<<31==2147483648
18                     // 1<<32==1
19                     // (1<<31)-1==2147483647
20                     // (1<<32)-1==0
21                     // (1<<32)-2==4294967295
22     for(int i=30;i<(1<<5)+1;i++)
23         printf("1<<%d==%u\n",i,j2<<i);
24     printf("(1<<%d)-1==%u\n",31,(j2<<31)-1);
25     printf("(1<<%d)-1==%u\n",32,(j2<<32)-1);
26     printf("(1<<%d)-2==%u\n",32,(j2<<32)-2);
27 //long
28     printf("\nlong:\n");
29     long j3=1;//1<<63==-9223372036854775808
30             // 1<<64==1
31             // (1<<63)-1==9223372036854775807
32             // (1<<64)-1==0
33             // (1<<64)-2==-1
34     for(int i=62;i<(1<<6)+1;i++)
35         printf("1<<%d==%ld\n",i,j3<<i);
36     printf("(1<<%d)-1==%ld\n",63,(j3<<63)-1);
37     printf("(1<<%d)-1==%ld\n",64,(j3<<64)-1);
38     printf("(1<<%d)-2==%ld\n",64,(j3<<64)-2);
39 // unsigned long
40     printf("\nunsigned long:\n");
41     unsigned long j4=1;  //1<<62==4611686018427387904
42                         // 1<<63==9223372036854775808
43                         // 1<<64==1
44                         // (1<<63)-1==9223372036854775807
45                         // (1<<64)-1==0
46                         // (1<<64)-2==18446744073709551615
47     for(int i=62;i<(1<<6)+1;i++)
48         printf("1<<%d==%lu\n",i,j4<<i);
49     printf("(1<<%d)-1==%lu\n",63,(j4<<63)-1);
50     printf("(1<<%d)-1==%lu\n",64,(j4<<64)-1);
51     printf("(1<<%d)-2==%lu\n",64,(j4<<64)-2);
52 }
View Code

 

运行结果:

int:
1<<30==1073741824
1<<31==-2147483648
1<<32==1
(1<<31)-1==2147483647
(1<<32)-1==0
(1<<32)-2==-1

unsigned int:
1<<30==1073741824
1<<31==2147483648
1<<32==1
(1<<31)-1==2147483647
(1<<32)-1==0
(1<<32)-2==4294967295

long:
1<<62==4611686018427387904
1<<63==-9223372036854775808
1<<64==1
(1<<63)-1==9223372036854775807
(1<<64)-1==0
(1<<64)-2==-1

unsigned long:
1<<62==4611686018427387904
1<<63==9223372036854775808
1<<64==1
(1<<63)-1==9223372036854775807
(1<<64)-1==0
(1<<64)-2==18446744073709551615

 --------------------------------------------------------------

c++如果输出用printf则所有结果与c相同。

下面是用std::cout<<;的输出方式的测试中与printf不同的地方(全是我错误使用格式字符引起的)

c++ int:

(1<<32)-2==

printf():4294967295

std::cout<<::-1

 

c++ unsigned long:
(1<<64)-2==
printf():-1   
std::cout<<:18446744073709551615

c++完整测试代码:

 1 #include<iostream>
 2 main(){
 3 //int
 4     printf("int:\n");
 5     int j=1;  //<<31==2147483648
 6             // 1<<32==1
 7             // (1<<31)-1==2147483647
 8             // (1<<32)-1==0
 9             // (1<<32)-2==4294967295    -1
10     for(int i=30;i<(1<<5)+1;i++){
11         printf("1<<%d==%ld\n",i,j<<i);
12         std::cout<<"1<<"<<i<<"=="<<(j<<i)<<"\n";}
13     std::cout<<"(1<<31)-1"<<"=="<<(j<<31)-1<<"\n";
14     std::cout<<"(1<<32)-1"<<"=="<<(j<<32)-1<<"\n";
15     std::cout<<"(1<<32)-2"<<"=="<<(j<<32)-2<<"\n";
16     printf("(1<<%d)-1==%ld\n",31,(j<<31)-1);
17     printf("(1<<%d)-1==%ld\n",32,(j<<32)-1);
18     printf("(1<<%d)-2==%ld\n",32,(j<<32)-2);
19 // unsigned int
20     printf("\nunsigned int:\n");
21     unsigned int j2=1;//1<<31==2147483648
22                     // 1<<32==1
23                     // (1<<32)-1==0
24                     // (1<<32)-2==4294967295
25     for(int i=30;i<(1<<5)+1;i++){
26         printf("1<<%d==%ld\n",i,j2<<i);
27         std::cout<<"1<<"<<i<<"=="<<(j2<<i)<<"\n";}
28     std::cout<<"(1<<31)-1"<<"=="<<(j2<<31)-1<<"\n";
29     std::cout<<"(1<<32)-1"<<"=="<<(j2<<32)-1<<"\n";
30     std::cout<<"(1<<32)-2"<<"=="<<(j2<<32)-2<<"\n";
31     printf("(1<<%d)-1==%ld\n",31,(j2<<31)-1);
32     printf("(1<<%d)-1==%ld\n",32,(j2<<32)-1);
33     printf("(1<<%d)-2==%ld\n",32,(j2<<32)-2);
34 //long
35     printf("\nlong:\n");
36     long j3=1;//1<<63==-9223372036854775808
37             // 1<<64==1
38             // (1<<63)-1==9223372036854775807
39             // (1<<64)-1==0
40             // (1<<64)-2==-1
41     for(int i=62;i<(1<<6)+1;i++){
42         printf("1<<%d==%ld\n",i,j3<<i);
43         std::cout<<"1<<"<<i<<"=="<<(j3<<i)<<"\n";}
44     std::cout<<"(1<<63)-1"<<"=="<<(j3<<63)-1<<"\n";
45     std::cout<<"(1<<64)-1"<<"=="<<(j3<<64)-1<<"\n";
46     std::cout<<"(1<<64)-2"<<"=="<<(j3<<64)-2<<"\n";
47     printf("(1<<%d)-1==%ld\n",63,(j3<<63)-1);
48     printf("(1<<%d)-1==%ld\n",64,(j3<<64)-1);
49     printf("(1<<%d)-2==%ld\n",64,(j3<<64)-2);
50 // unsigned long
51     printf("\nunsigned long:\n");
52     unsigned long j4=1;//1<<63==-9223372036854775808
53                     // 1<<64==1
54                     // (1<<63)-1==9223372036854775807
55                     // (1<<64)-1==0
56                     // (1<<64)-2==-1    ,18446744073709551615
57     for(int i=62;i<(1<<6)+1;i++){
58         printf("1<<%d==%ld\n",i,j4<<i);
59         std::cout<<"1<<"<<i<<"=="<<(j4<<i)<<"\n";}
60     std::cout<<"(1<<63)-1"<<"=="<<(j4<<63)-1<<"\n";
61     std::cout<<"(1<<64)-1"<<"=="<<(j4<<64)-1<<"\n";
62     std::cout<<"(1<<64)-2"<<"=="<<(j4<<64)-2<<"\n";
63     printf("(1<<%d)-1==%ld\n",63,(j4<<63)-1);
64     printf("(1<<%d)-1==%ld\n",64,(j4<<64)-1);
65     printf("(1<<%d)-2==%ld\n",64,(j4<<64)-2);
66 }
View Code

 运行结果:

int:
1<<30==1073741824
1<<30==1073741824
1<<31==2147483648
1<<31==-2147483648
1<<32==1
1<<32==1
(1<<31)-1==2147483647
(1<<32)-1==0
(1<<32)-2==-1
(1<<31)-1==2147483647
(1<<32)-1==0
(1<<32)-2==4294967295

unsigned int:
1<<30==1073741824
1<<30==1073741824
1<<31==2147483648
1<<31==2147483648
1<<32==1
1<<32==1
(1<<31)-1==2147483647
(1<<32)-1==0
(1<<32)-2==4294967295
(1<<31)-1==2147483647
(1<<32)-1==0
(1<<32)-2==4294967295

long:
1<<62==4611686018427387904
1<<62==4611686018427387904
1<<63==-9223372036854775808
1<<63==-9223372036854775808
1<<64==1
1<<64==1
(1<<63)-1==9223372036854775807
(1<<64)-1==0
(1<<64)-2==-1
(1<<63)-1==9223372036854775807
(1<<64)-1==0
(1<<64)-2==-1

unsigned long:
1<<62==4611686018427387904
1<<62==4611686018427387904
1<<63==-9223372036854775808
1<<63==9223372036854775808
1<<64==1
1<<64==1
(1<<63)-1==9223372036854775807
(1<<64)-1==0
(1<<64)-2==18446744073709551615
(1<<63)-1==9223372036854775807
(1<<64)-1==0
(1<<64)-2==-1

 

为什么printf和cout不完全一致:https://tieba.baidu.com/p/8421942192
别人:cout的类型推断一定是正确的,如果printf和cout的结果不同,那说明使用了错误的转换说明
我:刚刚学完signed和unsigned、%d和%D、以及整数和位移溢出。 cout的类型推断一定是正确的,这一点我认同。在cout中它并没有错误地将无符号数当成有符号数或将有符号数当成无符号数输出。 而printf就不一样了,即便我指定了正确的占位符,它有时还是会将有符号是当成无符号数输出,如第7行第1列应该是(1<<32)-2==-1而不是(1<<32)-2==4294967295;第14行第2列应该是(1<<64)-2==18446744073709551615而不是(1<<64)-2==-1
我:搞错了,无符号整型的输出占位符应该是%u而不是%D,%D不知道是干嘛用的

我:总结:

1、printf错误地将负数当成整数输出的原因:格式字符使用错误,%d写成了%ld使得编译器将-1的负号当成了数值。解决方法:%ld改回%d
2、printf将无符号数当成有符号数输出的原因:格式字符错误,本来应该用%lu却用了%ld使得编辑器将最高位当成了负号。解决方法:将%ld改为%lu。

posted @ 2023-05-20 16:48  败人两字非傲即惰  阅读(141)  评论(0编辑  收藏  举报