tdcall、stdcall、pascall是什么?C++默认是哪种?
__cdecl、__stdcall是声明的函数调用协议。主要是传参和弹栈方面的不同。
__cdecl:一般c++用的是__cdecl
函数参数按照从右到左的顺序入栈
由调用函数者把参数弹出栈以清理堆栈
PS:那么为什么还需要_cdecl呢?当我们遇到这样的函数如fprintf()它的参数是可变的,不定长的。
__stdcall:windows里大都用的是__stdcall(API)
函数参数按照从右到左的顺序入栈
被调用的函数在返回前清理传送参数的栈
__fastcall:约定用于对性能要求非常高的场合
约定将函数的从左边开始的两个大小不大于4个字节(DWORD)的参数分别放在ECX和EDX寄存器,其余的参数仍旧自右向左压栈传送,
被调用的函数在返回前清理传送参数的堆栈
static_cast, dynamic_cast, reinterpret_cast, const_cast区别比较
static_cast <new_type> (expression) 静态转换
static_cast最接近于C风格转换了,但在无关类的类指针之间转换上,有安全性的提升
该运算符把exdivssion转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:
①用于类层次结构中基类和子类之间指针或引用的转换。
进行上行转换(把子类的指针或引用转换成基类表示)是安全的;
进行下行转换(把基类指针或引用转换成子类表示)时,由于没有动态类型检查,所以是不安全的。
②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
③把空指针转换成目标类型的空指针。
④把任何类型的表达式转换成void类型。
注意:static_cast不能转换掉exdivssion的const、volitale、或者__unaligned属性。
dynamic_cast <new_type> (expression) 动态转换
动态转换确保类指针的转换是合适完整的,它有两个重要的约束条件,其一是要求new_type为指针或引用,其二是下行转换时要求基类是多态的(基类中包含至少一个虚函数)。
该运算符把exdivssion转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *;
如果type-id是类指针类型,那么exdivssion也必须是一个指针,如果type-id是一个引用,那么exdivssion也必须是一个引用。
dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。
在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;
在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
reinterpret_cast <new_type> (expression) 重解释转换
这个转换是最“不安全”的,两个没有任何关系的类指针之间转换都可以用这个转换实现
const_cast <new_type> (expression) 常量向非常量转换
这个转换好理解,可以将常量转成非常量。
C++内存分配有几种方式
-
在静态存储区分配:此时的内存在程序编译的时候已经分配好,并且在程序的整个运行期间都存在。全局变量,static变量等在此存储。
-
在栈区分配:相关代码执行时创建,执行结束时被自动释放。局部变量在此存储。栈内存分配运算内置于处理器的指令集中,效率高,但容量有限。
-
在堆区分配:动态分配内存。用new/malloc时开辟,delete/free时释放。生存期由用户指定,灵活。但有内存泄露等问题。
常见内存错误及对策
1. 内存分配未成功,却被使用。
对策:使用内存之前检查是否分配成功。用p!=NULL判断。
2. 内存分配成功,未初始化就被使用。
内存的缺省值没有统一的标准。大部分编译器以0作为初始值,但不完全是。
对策:内存初始化时赋初值。
3. 内存操作越界。
对策:只能是小心了。
4. 释放了内存,仍然使用。
(1) 使用显示delete和free的野指针。
对策:释放完内存,将指针置为NULL。
(2) 使用隐式delete和free的野指针。主要是指函数返回指向栈内存的指针或引用。
对策:当然是不要返回就可以了。
5. 未释放内存,导致内存泄露。
用new/malloc开辟了内存,没用delete/free释放.
对策:new和delete的个数一定相同;malloc和free的个数一定相同;new[]和[]delete一定对应。
模板的实现可以放在cpp里吗?为什么?
模板声明和实现要放在一个文件。因为放在CPP里面实现会编译不过。
volatile
- volatile的本意是“易变的” 因为访问寄存器要比访问内存单元快的多,所以编译器一般都会作减少存取内存的优化,但有可能会读脏数据。当要求使用volatile声明变量值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。精确地说就是,遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问;如果不使用valatile,则编译器将对所声明的语句进行优化。(简洁的说就是:volatile关键词影响编译器编译的结果,用volatile声明的变量表示该变量随时可能发生变化,与该变量有关的运算不要进行编译优化,以免出错)
- 看两个事例:
1>告诉compiler不能做任何优化
比如要往某一地址送两指令:
int *ip =…; //设备地址
*ip = 1; //第一个指令
*ip = 2; //第二个指令
以上程序compiler可能做优化而成:
int *ip = …;
*ip = 2;
结果第一个指令丢失。如果用volatile, compiler就不允许做任何的优化,从而保证程序的原意:
volatile int *ip = …;
*ip = 1;
*ip = 2;
即使你要compiler做优化,它也不会把两次付值语句间化为一。它只能做其它的优化。
volatile关键字的使用示例
struct和class有什么区别?
C++中,class与struct都可以定义一个类。他们有以下两点区别:
-
默认继承权限,如果不指定,来自class的继承按照private继承处理,来自struct的继承按照public继承处理;
-
成员的默认访问权限。class的成员默认是private权限,struct默认是public权限。
以上两点也是struct和class最基本的差别,也是最本质的差别;
但是在C++中,struct进行了扩展,现在它已经不仅仅是一个包含不同数据类型的数据结构了,它包括了更多的功能。
Struct能包含成员函数、有自己的构造函数、可以有析构函数、支持继承、支持多态、支持Private、Protected、Public关键字。
如果是class的父类是struct关键字描述的,那么默认访问属性是什么?
当出现这种情况时,到底默认是public继承还是private继承,取决于子类而不是基类。
class可以继承自struct修饰的类;同时,struct也可以继承自class修饰的类,继承属性如下列描述:
class A{};
class B:A{}; // private 继承
struct B:A{}; // public 继承
最后,那么到底是使用struct,还是使用class呢?
一般来说,两个关键字都是可以的,但是由于编程规范的问题,如果要定义的是一种数据结构,那么用struct,如果是一种对象的话,那么用class。
default
default也是一种case,但它是指“除了指定的几个case以外的其他情况”,它无论放在哪个位置,都是等待读完所有case且没有符合的条件下再被使用。
唯一需要注意的就是,default和其他case一样都是一直往下读的,碰到break停止。而我们平常使用时将其放在句尾,还有在每个语句后打break的习惯,可能会让我们混肴这一点,产生default就是结束语这样简单的思维错误。
内存页面大小
绝大多数处理器上的内存页的默认大小都是 4KB,虽然部分处理器会使用 8KB、16KB 或者 64KB 作为默认的页面大小,但是 4KB 的页面仍然是操作系统默认内存页配置的主流;除了正常的内存页大小之外,不同的处理器上也包含不同大小的大页面,我们在 x86 处理器上就可以使用 2MB 的内存页。
计算机网络
ip地址0,0,0,0是什么意思
首先说一下ip地址:127.0.0.1,这是大家最熟悉不过的本地loopback(回环)地址,代表本地主机,在windows和linux上等价于localhost,可在C:\Windows\System32\drivers\etc\hosts文件中修改主机名或定义ipv6地址(# ::1 localhost)。
192.168.1.x,是公网ip地址,这些是在网络中代表本机的ip地址,可通过此ip地址远程访问或控制主机。
0.0.0.0,最特殊的一个ip地址,代表的是本机所有ip地址,不管你有多少个网口,多少个ip,如果监听本机的0.0.0.0上的端口,就等于监听机器上的所有ip端口。换句话说,就是只要数据报目的地址是你机器上的一个ip地址,那么就能被接受。这个ip相当于java中的this,代表当前设备的IP。
端口占用命令
netstat -ano:可以看到系统当前所有的端口使用情况;
netstat -ano |findstr “端口号”,然后回车就可以看到这个端口被哪个应用占用;
mtu
最大传输单元(Maximum Transmission Unit,MTU)用来通知对方所能接受数据服务单元的最大尺寸,说明发送方能够接受的有效载荷大小。
内存转储文件
内存转储是用于系统崩溃时,将内存中的数据转储保存在转储文件中,供给有关人员进行排错分析用途。而它所保存生成的文件就叫做内存转储文件。