C++和C的区别二

1.c和c++函数互相调用

之前也说了,c和c++的函数生成符号不一样,那么c++和c在互相调用对方函数的时候就会出错,因为根本无法找到对应的符号。

而由于c++是基于c语言而来,肯定会想到兼容性的问题,因此如果c++想要使用c的函数,c++会有特殊处理,可以把函数符号转化成c的不带参数的形式,只用在c++文件里这样

  Extern ”C”

{

 Int sum(int ,int )

}

这样编译时同时也会生成c语言版本的函数符号,到时候c++想要使用c中定义的函数也可以找到符号。

 

但是反过来呢,如果c想要使用c++文件里定义的函数呢。c可是不会兼容c++的,c可不能在自己文件里使用extern”c++”这种东西。

那么该怎么做呢?

其实可以创建一个接口文件。

比如这是cpp文件

Sum.cpp

 

Int sum(int a,int b)

{

Return a+b;

}

 

这是.c文件

Main()

{

Int a=10;

Int b=20;

sum(a,b);

}

目前来看,.c文件是绝对使用不了.cpp里的sum定义的。

那么这时就要新建一个mid.cpp接口文件了

这个文件内容如下

Mid.cpp

Int sum(int a,int b)

extern”C”

{

  Mysum(int a,int b)

{

 return sum(a,b);

}

}

2.const用法

c语言里const是常变量,而c++里是常量,即立即数。

因此c语言里const修饰的变量并不能作为初始化数组长度的下标。

而c++里const修饰的变量编译时就被当作立即数,可以当作数组初始化下标

 c语言里用const修饰的值可以不初始化,只是之后再没有机会对这个const修饰的变量赋值了。因此我们可以总结出c语言里const定义的常变量和一般变量的区别很小,只是常变量定义后不能作为左值存在。但其真身,或者说是编译方式,和普通变量是一样的。

 然而c++里的const修饰的量必须初始化,否则编译无法通过,即在编译的时候把使用const修饰的量都替换为其的值,因此就能作为数组下标,因为编译时,编译器看到的下标并非const 定义的量的名字,而是它对应的值的立即数。
 

3.引用

引用是c++的一种新类型,通常表示为 数据类型+&;&单独去表达地址。

如 int& b=a;

 引用就是被引用量的别名,如果改变b的值,同样也会改变a的值。

(1).

我们来看看引用的底层汇编究竟是什么

int a=10;

00ED439E  mov         dword ptr [a],0Ah  

 int &b=a;

00ED43A5  lea         eax,[a]  

00ED43A8  mov         dword ptr [b],eax  

  可以看到b对a引用,实际上先让eax存放了a的地址,然后再将eax存放的a的地址赋给了b。这不就是个指针做的事情吗。我们再看看指针的汇编是什么样的。

int a=10;

012D439E  mov         dword ptr [a],0Ah  

  int *p=&a;

012D43A5  lea         eax,[a]  

012D43A8  mov         dword ptr [p],eax  

可以看到指针的汇编和引用的汇编原理是一模一样的。所以说引用其实就是被包装了的指针,不过每次使用引用时都其实都自动做了相当于指针解引用的操作。
(2)引用是要开辟内存的

引用得本质是指针,指针占四个字节

(3)引用数值指针

引用一纬数组int arr[10]={0};

就相当于对int *arr 数组指针进行引用

我们看整形引用是

int &b=int  a;

b实际上对a取地址,int  *b=&a 只不过&和*都掩盖了,然后在b引用名前紧跟了一个&引用类型

对数组即为对*arr取地址

按上面的推,是不是b其实相当于一个数组指针,对arr数组指针取地址

int (*b)[10]=&arr;

把*用&替代即为

int (&b)[10]=arr;

4.const和指针的结合用法

(1)const和指针

 一级指针

Int a=10;

Int *p=&a;

其中const修饰第二句可以这样2种修饰

即int const *p 和int * const p

前者修饰*p,意味着不能改变p解引用后的值,即不能通过解引用p去修改p指向的内存的值。

后者修饰p,意味着p是常量,即可以通过p改变p指向的内存的值,但并不能改变p这个指针本身的值,即p的指向不能改变。

如果int a定义为 const int a;那么这个p只能定义成int const *p;

因为const int a代表不能直接或间接的对a修改,直接就是直接修改a,当然是不行的。间接呢?间接就是把a的地址或者引用泄露出去,让其他高权限的指针通过解引用进行修改。这种显然不符合我们对const的要求,编译器是要杜绝的。

还有一种情况就是这样的。

Int a=10;

Const int *p1=&a;

Int *p2=p1;

a是可以修改的,然后定义了一个const指针p1,它表示不能通过p1修改a的值,这属于权限缩小,当然是没有错误的。

可是第三句int *p2=p1;却是不对的,那是为什么?

首先可以通过权限来判断,第三句相当于把低权限的指针p1让高权限的指针p2使用,这是权限放大,显然有误。

可是有人会疑问,a不是可以修改呢?P2权限大修改a也不影响最终结果啊。

实际上是这样的。编译器在读到Const int *p1=&a这时已经认为p1的指向是个const int类型了,之后再和p1相等指针都应该是const int *类型,如果改成下面这种语序,表达的意思其实和上面一样,但能通过编译

Int a=10;

Int *p2=&a;

Const int *p1=&a;

二级指针和const 中需要注意下面这一种情况,和上面的很像。

Int a=10;

Const Int *p=&a;

Int **pp=&p;

这样是编译无法通过的。和

Int a=10;

Const int *p1=&a;

Int *p2=p1;

比,就是第三句不同,前者是Int **p=&p;后者是Int *p2=p1;

就是本来把p1赋值给另一个一级指针p2,变成了一个二级指针指向p。

为什么会编译不通过呢。上面也说了Const int *p=&a;

 这句编译器读完后,就认为p1指向的是个const int 类型了,int **pp指向const int *p就会权限扩大,肯定就会失败。虽然 我们想着**pp修改a,a明明可以修改啊,你可以想成编译器并没有记忆力,先到int a了不会记住a的权限,只会记住Const int *p中p的属性,即使pp和a有合理的关联,但无法通过p这关。也就是常说的间接修改。这也算编译器怕你违反 它认为的规则 的一种预防吧。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值