编译器可以根据自身硬件来选择合适的大小,但是需要满足约束:short和int型至少为16位,long型至少为32位,并且short型长度不能超过int型,而int型不能超过long型。这即是说各个类型的变量长度是由编译器来决定的,而当前主流的编译器中一般是32位机器和64位机器中int型都是4个字节(例如,GCC)。
数据类型占内存的位数实际上与操作系统的位数和编译器(不同编译器支持的位数可能有所不同)都有关
,具体某种数据类型占字节数得编译器根据操作系统位数两者之间进行协调好后分配内存大小。具体在使用的时候如想知道具体占内存的位数通过sizeof(int)可以得到准确的答案。对于0来说,它的原码和反码都有两种(分别为0000 0000,1000 0000,和0000 0000, 1111 1111),但是补码只有一种(即0000 0000),-0的补码形式等于对应的正数0的原码00000000,取反为11111111,加1是00000000,答案仍然是0,溢出了。整数0,小数0的补码都只有这一种形式。同时也是说,补码没有1000 0000这个值(用来干啥好呢?所以就赋给-128.。。。),其实不是的,-127的原,反,补为:1111 1111, 1000 0000, 1000 0001,因为穷举法,补码 1000 0000 为 -128 是不用怀疑的,所以, 8位有符号的整数取值范围的补码表示 1000 0000 到 0000 0000, 再到 0111 1111 即 -128 到 0, 再到 127 最终 -128 ~ +127,中间没有中断,一直是往上加1的,只不过到0的时候溢出了。-128没有原码,也没有反码,都被-0占了(分别是1000 0000和1111 1111)。
一个二进制数的补码的补码就是原码!!!(2019/3/27 补充一下,一个正数的补码的补码是它相对应的负数的补码,同理,一个负数的补码的补码是它相对应的正数的补码,也就是说,一个正数的原码就是它相对应的负数的补码,懂了没?)
枚举类型enum的元素长度根据编译器而定。在visual c++下,它和int一样长,是4个字节,在GCC下它会取尽可能短的长度,例如你这个枚举类型只有3种标识,那么它是一个字节。
12的平方是int在GCC中的极限平方了,到了13的平方就会溢出,int型数组建立20万个没事,建立100万个就创建不出了,因此在数组建立不出来时,尽量让数组放在函数之外,因为如果数组太大,放在函数内有可能会崩溃,在函数之外则不会有这样的问题。因为在函数外定义属于全局变量,全局变量在静态存储区分配内存,而局部变量是在栈上分配内存空间的,如果数组太大,可能会造成栈溢出。
使用static_cast可以找回存放在void指针中的值。一般用于malloc,它的返回值正是void,这叫自带解释。。double * dptr = static_cast<double*>(vptr);
C11增加了一些新特性,and,or,not 何以取代&& || !真方便!
for(expression : struct) 完全也可以用普通数组这个语法糖,但是指针就不行,而且是值传递的,也就是不能修改。
括号失效:有时你明明以为加了括号可以保证万无一失,但是还是可能跑偏了,例如int c = ++b * (a+b) 因为有那个自增的运算符,整个表达式异常凶险。。。
要注意int的有无符号的问题,如果不注意的话,得出的结果会非常奇怪,例如: int x = 2; char * str = "abcd"; int y = (x - strlen(str) ) / 2; printf("%d ",y); 结果应该是 -1 但是却得到:2147483647 。为什么?因为strlen的返回值类型是size_t,也就是unsigned int ,与 int 混合计算时,int类型被自动转换为unsigned int了,结果自然出乎意料。。。解决办法就是强制转换,变成 int y = (int)(x - strlen(str) ) / 2; 强制向有符号方向转换(编译器默认正好相反),所以牵扯到有符号无符号计算的问题,特别是存在讨厌的自动转换时,要倍加小心!(这里自动转换时,无论gcc还是cl都不提示!!!) 为了避免这些错误,建议,凡是在运算的时候,确保你的变量都是 signed 的。
c编译器中,仅支持C89规范的编译器,只支持在作用域起始部分(大括号最开始)定义变量。支持C99或者部分支持C99的编译器, 局部变量可以定义在任何位置。基本上绝大多数都支持了,甚至还有一部分支持for(int i),但是并不建议在C语言中用这个。
早在C++98标准中就存在了auto关键字,那时的auto用于声明变量为自动变量,自动变量意为拥有自动的生命期,这是多余的,因为就算不使用auto声明,变量依旧拥有自动的生命期,C++98中的auto多余且极少使用,C++11已经删除了这一用法,取而代之的是全新的auto:变量的自动类型推断。auto可以在声明变量的时候根据变量初始值的类型自动为此变量选择匹配的类型。
有时候不引用string头文件仍然可以使用string,那是因为有可能某一个头文件里包括了它自己的,不同平台可能有不同,在这里不要偷懒。
map的值是按照key升序排列的,也就是说,自动排列。
对于输入输出,在最后输出回车还是空格的问题上,聪明人都用三目元表达式(i==n-1)?" ":" ",但是注意要把表达式全部用括号括起来,为了防止编译器分析不当,而且这种情况时有发生。
如何在类似 for(auto var:set){} 这种语句里确定var到底是不是最后一个?或者说set怎么确定其中的值是最后一个?这里有讲究: var == *(--set.end()) 注意是自减而不是-1,--是重载了的,而-没有重载,所以会报错的,而且注意是前面自减才对。
要用<iostream>而不要用<iostream.h>,后者只是仅仅支持字符流,而前者包含了一系列模板化的I/O类,二者在接口和执行上都是不同的。
scanf 函数的返回值反映的是按照指定的格式符正确读入的数据的个数。也就是说,可以运用while(scanf(“%d”,&x)==1){}来更加简化没有确定数据个数时的代码段,那么,这里只能输入字母来结束输入,在scanf中,回车,空格,tab键是无关紧要的,也就是输入多少也不会管,只有按下空格,再按Ctrl+z,然后再按回车,才算结束输入,这时候scanf接受的是第一个空格之前的字符,在Linux中,按下回车,再按下Ctrl+D即可结束输入,也就是说,scanf的这种特性基本没用,只有在ACM中有用。scanf的返回值用在什么地方呢?用在没有给出有多少数据,一次性输入完就算的那种,这么写: while(scanf("%d %d",&m,&n)!=EOF){}感觉还方便.
gets在C ++中会产生bug,而且在C11标准中 被废除,因此不建议使用,getline(cin, str)函数只能读取string类型,不能读取字符数组类型,cin.get可以读取字符数组类型,并且只会遇到回车而结束。用法为cin.get(ch,长度),另外需要注意的是,这个函数会将换行符留在输入队列中,如果连续两次调用,第二次将无法读入,应加上一个不带参数的cin.get吃掉换行符,推荐用cin.ignore(),因为看起来自带注释的感觉,另外cin>>noskipws也有读取空格字符串的功能。一般的,常会有使用一次cin之后连续多次使用getline,但是,由于cin不读入空格的特性,getline总会少输入一行,所以正确姿势是用cin.get()或者cin.ingnore(),感觉用后者更自带注释一些。
" " 表示内容为一个回车符的字符串。std::endl 是流操作子,输出的作用和输出 “ ” 类似,但可能略有区别。std::endl 输出一个换行符,并立即刷新缓冲区,由于流操作符 << 的重载,对于 ‘ ’ 和 “ ”,输出效果相同。对于有输出缓冲的流(例如cout、clog),如果不手动进行缓冲区刷新操作,将在缓冲区满后自动刷新输出。不过对于 cout 来说(相对于文件输出流等),缓冲一般体现得并不明显。但是必要情况下使用 endl 代替 ‘ ’ 一般是个好习惯。对于无缓冲的流(例如标准错误输出流cerr),刷新是不必要的,可以直接使用 ‘ ’。
fgets(buff,MAXN,fin)将读取完整的一行存放到buff字符数组中,而且往往是以 结尾(除了在文件结束前没有遇到 这种特殊情况)。当一个字符也没有读到,函数返回null。同样有一个标准输入板的gets(s)函数,里面只有一个数组参数,风险较大,不建议使用。而在scanf中,是不包括 的,但是也不能在接受字符串中打上 ,回车是一个输入完成键,在scanf与fgets混用时(我为什么要混用?可能以后再也不会混用了)要注意这个点。
对于上下左右和别的一些扩展键使用getch会先返回一个224,再使用一次getch()这时返回的才是扫描码。
关于memset,只用它来初始化0就行了,初始化其他的,全错!相信我,memset函数也是以字节为单位进行赋值的,对于int型,是四个字节,也就是将这四个字节设置成0x01010101, 转换成十进制就是16843009。memset的作用是来将一段内存按自己进行初始化, 并非用来进行变量初始化。
值得注意的是,c++的结构体是可以有构造函数的,这也可以说,如果构造一个链表结构体的话,那么就非常有用了是不是,在销毁的时候顺便释放空间什么的,结构体中可以包含函数;也可以定义public、private、protected数据成员,结构体定义中默认情况下的成员是public,而类定义中的默认情况下的成员是private的。类中的非static成员函数有this指针,(而struct中没有是错误的,一直被误导啊,经过测试struct的成员函数一样具有this指针),类的关键字class能作为template模板的关键字 即template<class T> class A{}; 而struct不可以。
C++中定义结构体变量时可以不加struct关键字,也就是说,typedef可以在c++中省掉了。
不建议使用全局对象,因为debug只能从main处进入,而类的初始化在main开始之前,所以根本没办法调试。另外,由于全局变量创建顺序完全不可控,更不要让全局变量之间相互依赖。
额,就先这么多吧。。