千家信息网

C和C++的区别有哪些

发表于:2025-01-22 作者:千家信息网编辑
千家信息网最后更新 2025年01月22日,本篇内容介绍了"C和C++的区别有哪些"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!通过程序来介绍/
千家信息网最后更新 2025年01月22日C和C++的区别有哪些

本篇内容介绍了"C和C++的区别有哪些"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

    通过程序来介绍

    //c++ program#includeusing namespace std;int main(void){        cout << "This is a c++ program." << endl;        return 0;}

    1.iostream文件

    iostream中的io指的是输入(进入程序的信息)和输出(从程序中发送出去的信息)。

    并且c++的输入、输出方案涉及iostream文件中的多个定义。比如用来输出信息的cout就在其中。

    2.头文件名的区别

    C语言

    C语言的传统是头文件使用扩展名 h,将其作为一种通过名称标识文件类型的简单方式。例如 math.h支持一些数学函数。

    C++

    C++头文件没有扩展名。
    有些C头文件被转换成C++头文件,这些文件被重新命名,去掉了扩展名h,并在文件名称前面加上前缀c(表示来自C语言)

    3.名称空间namespace

    如果使用的是iostream,而不是iostream.h,则应使用名称空间编译指令来使iostream中的定义对程序可用,即

    using namespace std;

    有了这句using编译指令,才能使用cout、cin等,或者用第二种方式:

    using std::cout;using std::cin;using std::endl;

    名称空间是C++的特性之一,简单理解为:可以将自己的产品封装起来。

    示例

    封装性

    示例:

    首先定义一个头文件

    在里面写上我们自己编的东西:

    #pragma oncenamespace AA{        typedef int INT;        typename char CHAR;};

    然后在cpp文件中引入该头文件,但我们却无法使用之前写好的东西。

    INT a会报错,因为我们只引入了头文件,没有使用里面的名称空间。

    正确做法:

    //c++ program#include#include"AA.h"using namespace std;using namespace AA;//using AA::INT;int main(void){        INT a = 10;        cout << a << endl;        return 0;}

    需要第六行的该名称空间才可以使用其中的产品。或者可以用第七行这种写法来确定自己只需要哪个产品。

    4.使用cout进行C++的输出

    上面的程序有这条C++语句:

            cout << "This is a C++ program." << endl;

    <<符号表示该语句将把这个字符串发送给cout,该符号指出了信息流动路径。 cout是一个预定义的对象。

    从概念上看,输出是一个流,即从程序流出的一系列字符。cout对象表示这种流,其属性是在iostream文件中定义的。
    cout的对象属性包括一个插入运算符(<<),它可以将其右侧的信息插入到流中。

    指针和数组名的区别

    程序示例:

    #includeusing namespace std;int main(void){        int a = 10;        int* p = &a;        int arr[] = { 0,1,2,3,4 };        cout << p << endl;        cout << arr << endl;        return 0;}

    这里定义了一个指针p和一个数组arr。

    运行结果都是地址

    反汇编查看区别

    cout << p << endl;

        cout << p << endl;008F52AF  mov         esi,esp  008F52B1  push        offset std::endl > (08F103Ch)  008F52B6  mov         edi,esp  008F52B8  mov         eax,dword ptr [p]  008F52BB  push        eax

    cout << arr << endl;

          cout << arr << endl;008F52DE  mov         esi,esp  008F52E0  push        offset std::endl > (08F103Ch)  008F52E5  mov         edi,esp  008F52E7  lea         eax,[arr]  008F52EA  push        eax

    区别

    在输出指针时,需要先从p里面取出四字节,再放到寄存器里push;

    在输出arr时,直接把arr放到寄存器里再push。

    结论

    指针是变量;

    数组名是一个地址--常量。

    解引用

    在C语言中学到,对指针解引用后得到的值就是它寸的地址对应的变量值。

    可以来探索原理

    程序示例

    #includeusing namespace std;int main(void){        int a = 10;        int* p = &a;        *p = 20;        return 0;}

    反汇编代码:

        int a = 10;000D18FF  mov         dword ptr [a],0Ah          int* p = &a;000D1906  lea         eax,[a]  000D1909  mov         dword ptr [p],eax          *p = 20;000D190C  mov         eax,dword ptr [p]  000D190F  mov         dword ptr [eax],14h

    对于*p = 20

    先从p的内存中取四个字节,即变量a的地址放入寄存器,再将20给到寄存器所存的的四字节中。完成对变量a的改变。

    所以解引用的意思就是从地址中把值取出来,这里是去p的地址里取出所存的变量a的地址。

    程序示例2:

    #includeusing namespace std;int main(void){        int a = 10, b = 20;        int* p = &a;        b = *p;        return 0;}

    反汇编代码:

        int a = 10, b = 20;000818FF  mov         dword ptr [a],0Ah  00081906  mov         dword ptr [b],14h          int* p = &a;0008190D  lea         eax,[a]  00081910  mov         dword ptr [p],eax          b = *p;00081913  mov         eax,dword ptr [p]  00081916  mov         ecx,dword ptr [eax]  00081918  mov         dword ptr [b],ecx

    对于 b = *p;

    1.先去p里取出四字节放入寄存器

    2.再从寄存器eax取出四字节放入寄存器ecx再把ecx

    3.的内容放入到变量b的四字节中。

    也可以看出:解引用这一步其实是去地址里取值的。

    这样也可以得出:用一个变量赋值给另一个变量,其实也是在解引用

    示例:

    #includeusing namespace std;int main(void){        int a = 10;        int b;        b = a;        return 0;}

    反汇编:

         int a = 10;002D18F5  mov         dword ptr [a],0Ah          int b;        b = a;002D18FC  mov         eax,dword ptr [a]  002D18FF  mov         dword ptr [b],eax

    对于 b = a;

    也是从a地址里取出四字节放到寄存器,再通过寄存器给入b。

    结论

    解引用:到地址里去取值。

    const的区别

    C语言中为常变量

    示例:

    //const#includeint main(void){        const int a = 10;        int b = 100; //常量赋值        b = a; //常变量赋值        return 0;}

    两次赋值的区别:

            const int a = 10;00311825  mov         dword ptr [a],0Ah          int b = 100;0031182C  mov         dword ptr [b],64h          b = a;00311833  mov         eax,dword ptr [a]  00311836  mov         dword ptr [b],eax

    常量赋值时,是直接把值给到b的四字节中;

    用const修饰的a赋值时,还是需要从a里取出四字节再赋给b。

    所以C语言中const修饰的变量叫做常变量--不能作为左值。

    甚至可以用指针改变它的值:

    #includeint main(void){        const int a = 10;        int b = 100;        b = a;        int* p = &a;        *p = 20;        return 0;}

    a的变化:const修饰的变量a居然能被改变

    C++中的const

    在C++中,const修饰的变量就是常量,和常量性质一样:

    在编译期间直接将常量的值替换到常量的使用点。

    示例:

    int main(void){        const int a = 10;        int b, c;        b = 16;        c = a;        return 0;}

    反汇编代码:

     const int a = 10;00B917F5  mov         dword ptr [a],0Ah          int b, c;        b = 16;00B917FC  mov         dword ptr [b],10h          c = a;00B91803  mov         dword ptr [c],0Ah

    可以看出,对b赋值常量是直接赋值;

    对c赋值const修饰的变量a,同样是用常量赋值的。所以:

    在C++中, const修饰的变量和常量性质一样,都是在编译期将常量值替换到常量的使用点。

    另外

    1.而且const修饰的变量必须初始化,同样因为编译期间就会替换为常量,不初始化,后面也没有机会再对其赋值。

    2.如果用变量对const修饰的变量赋值,则会使其退化成常变量。

    声明时const位置不同的区别

    示例:

    const可在不同位置修饰变量

    int main(void){        int a = 10;        int* p1 = &a;        const int* p2 = &a;        int const* p3 = &a;        int* const p4 = &a;        int* q1 = &a;        const int* q2 = &a;        int const* q3 = &a;        int* const q4 = &a;        return 0;}

    要注意的是:

    const与离他最近的类型结合,是该变量的类型,除了最近的类型,剩下的就是const修饰的内容。

    const修饰的内容是不可作为左值。

    根据上面的原理,来判断以下内容:

        p1 = q1;        p1 = q2;        p1 = q3;        p1 = q4;        p2 = q1;        p2 = q2;        p2 = q3;        p2 = q4;        p3 = q1;        p3 = q2;        p3 = q3;        p3 = q4;        p4 = q1;        p4 = q2;        p4 = q3;        p4 = q4;

    p1是普通指针。

    对于

    const int* p2和int const* p3

    const修饰的类型是离他最近的类型,即int,剩下的为const所修饰的内容,所以它们两个所修饰的内容为 *p2 、*p3。

    对于int* const p4

    const修饰的类型为int*,那修饰的内容就是p4。

    下面的四个q同理。

    可以推出错误的是:

           p1 = q2;        p1 = q3;        p4 = q1;        p4 = q2;        p4 = q3;        p4 = q4;

    因为 *q2 和 *q3不能改变,所以把 q2/q3赋值给普通指针时,会造成普通指针来改变其中内容的后果,即 泄露常量地址给非常量指针 ,所以不能这样赋值。

    p4为const修饰的内容,不能被改变。

    const修饰形参

    这里主要说能否形成函数重载的问题

    程序示例:

    int fun(int a){        return a;}int fun(const int a){        return a;}

    编译器并没有报错,但编译无法通过。

    结论:如果const修饰的内容不包括指针,则不参与类型问题。

    引用变量

    之前C语言学到,&符号用来指示变量的地址。

    C++给该符号赋予了另一个含义,将其用来声明引用。

    示例,若我想用 A作为变量 a的别名,可以这样用:

    #includeusing namespace std;int main(void){        int a = 10;        int& A = a;        A = 20;        cout << a << endl;        cout << A << endl;        return 0;}

    运行示例:

    通过A可以改变a的值,这就是引用。A相当于a的别名,就和鲁迅和周树人一样。。。

    引用的原理

    示例:

    int a = 10;        int& A = a;        int* p = &a;

    反汇编代码:

       int& A = a;00ED5326  lea         eax,[a]  00ED5329  mov         dword ptr [A],eax          int* p = &a;00ED532C  lea         eax,[a]  00ED532F  mov         dword ptr [p],eax

    可以看出:引用的实现居然和指针是一样的。

    所以引用的底层是一个指针。

    结论:在使用到引用的地方,编译期会自动替换成底层指针的解引用。

    常问问题

    1.引用为什么必须初始化?

    2.引用为什么一经过初始化,就无法改变引用的方向?

    答:因为只有在初始化的时候能给它赋值,其他使用到它的地方都替换成了底层指针

    无法改变底层指针的指向,所以无法改变引用的方向。

    3.不能将const限定的变量赋给普通引用变量:

    原因是将常量的地址赋给了普通指针。

         const int a = 10;        int& b = a; //错误

    4.当引用一个不可以取地址的量的时候,使用常引用。

    会生成一个临时量,然后常引用临时量,临时量都有常属性。

    示例:

    int& a = 10; //错误const int& a = 10; //正确

    动态申请空间的区别

    C语言

    使用malloc和free

    示例:

    int main(void){        //申请一维数组与释放        int* arr = (int*)malloc(sizeof(int) * 10);        if (arr == NULL)                return -1;        free(arr);        //申请二维数组与释放        int** brr = (int**)malloc(sizeof(int*) * 10);        if (brr == NULL)                return -1;        for (int i = 0; i < 10; ++i)        {                free(brr[i]);        }        return 0;}

    C++

    int main(void){        //申请int类型变量        int* p = new int;        *p = 10;        delete p;        //申请int类型数组        int* arr = new int[10];        arr[0] = 10;        delete[]arr;        //申请二维数组        int** brr = new int* [5];        for (int i = 0; i < 5; ++i)        {                brr[i] = new int[10];        }        for (int i = 0; i < 5; ++i)        {                delete[]brr[i];        }        return 0;}

    new后面跟的类型就表示申请的大小。

    面向过程和面向对象

    C语言

    面向过程语言

    示例

    void echo(){        if (flag == 0)        {                printf("printf screen\n");        }        else if (flag == 1)        {                printf("printf file\n");        }}void Set_flag_file(){        flag = 1;}void Set_flag_screen(){        flag = 0;}

    对于这个打印函数,可以通过改变flag的值来控制其打印的结果。

    但如果改变flag,也会改变其他地方调用的打印函数的结果。

    所以C语言没有封装性。

    C++

    面向对象语言

    class Note{public:        Note()        {                flag = 0;        }        void echo()        {                if (flag == 0)                {                        printf("printf screen\n");                }                else if (flag == 1)                {                        printf("printf file\n");                }        }        void Set_flag_file()        {                flag = 1;        }        void Set_flag_screen()        {                flag = 0;        }private:        int flag;};

    使用示例:

    int main(void){        Note n;        n.echo();        n.Set_flag_file();        n.echo();        return 0;}

    C语言作为面向过程语言,如果示例中的flag做出改变,会影响全局的改变。

    C++作为半面向对象语言,具有封装性,若想改变示例中想打印的值,只会影响到这个模块。

    "C和C++的区别有哪些"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

    0