C++深度解析教程学习笔记(1)C到C++的升级

比如商场收银系统

C++深度解析教程学习笔记(1)C到C++的升级

2.C 到 C++ 的升级

2.1变量的定义

C++中所有的变量都可以在需要使用时再定义,而 C 语言中的变量都必须在作用域开始位置定义。

2.2 register 关键字

(1)register 关键字请求编译器将局部变量存储于寄存器中

在 C++中依然支持 register 关键字,但这只是为了兼容 C,C++编译器有自己的优化方式,在 C 语言中无法获取 register 变量的地址,因为 C认为寄存器是没有地址的。但 C++中可以取得 register 变量的地址。

①C++编译器发现程序中需要取变量地址时,register 对变量的声明变得无效。所以C++将无视这个关键字,直接将其 register 的变量放入内存(注意,不是寄存器)。

②早期 C 语言编译器不会对代码进行优化。因此可以利用 register 变量来进行一个很好补充。但 C++认为寄存器非常宝贵,这个 register 关键字并不被推荐使用,它只是为了兼容C 而存在。

2.3 重命名全局变量名

(1)在 C 语言中,重复定义多个同名的全局变量是合法的。C 编译器将把多个同名的全局变量最终链接到全局数据区的同一个地址空间上。

(2)在 C++中,不允许定义多个同名的全局变量。因为这是一种有二义性的做法,会被C++直接拒绝

#include <stdio.h>

int g_v;
//重复定义全局变量,C是合法的,会映射到同一个地址,C++是非法的
//ing g_v; 

int main()
{
    printf("Begin...\n");
    //C变量必须定义在作用域开始的位置,C++中可以随时定义
    int c = 0; 
   
    //在for循环内定义变量i和j
    for (int i=1; i<=3;i++)  
    {
        for(int j=1; j<=3; j++)
        {
            c += i * j;
        }
    }

    printf("c = %d\n", c);
   //声明为register
    register int a = 0;  
    //对a取地址,C++会将a放到内存而不是寄存器,C语言中&a是非法的。
    printf("&a = %p\n", &a);。

    printf("End...\n");

    return 0;
}

2.4 struct 关键字的加强

(1)C 语言中的 struct 定义了一组变量的集合,其定义的标识符并不是一种新的类型。

(2)C++中的 struct 用于定义一种全新的类型

C++深度解析教程学习笔记(1)C到C++的升级

2.5 标识符的类型

(1)C++中所有的标识符都必须显式的声明类型。C 语言中的默认类型(int 型)在 C++中是不合法的。(C++的返回值与 C 一样,可以不必声明类型,默认仍为 int)

(2)在 C 和 C++中无参与 void 参数的区别

 

 

C语言

C++语言

int func()

返回值为int,接受任意参数

返回值为int,

的无参函数

int func(void)

返回值默认为int,无参函数

func()

返回值为int,接受任意参数

func(void)

返回值默认为int,无参函数

func(i)

参数为默认的int,等价于int func(int i)

非法

#include <stdio.h>

//在C++中Student是一种新的类型,但在C语言要用typedef来重命名
struct Student
{
    const char* name;
    int age;
};

//C语言中下面的定义方法是合法的,等价于int f(int i);
//但C++所有的标识符须定义类型,如果不认识i的类型,会报错
//f(i)
//{
//    printf("i = %d\n", i);
//}

//C语言中下列是合法的,表示返回值int,接受任意参数
//但C++表示返回值int的无参数,相于当int g(void)
g()
{
    return 5;
}

int main()
{

    Student s1 = {"Hello", 30};
    Student s2 = {"World", 20};

    //C合法,C++会报错
    //f(10);
    //C语言合法,C++中报错
    printf("g() = %d\n",g(1,2,3,4,5));

    return 0;
}

2.6 C和C++中的const

1. C 语言中的 const

(1)const 修饰的变量是只读的,使得变量具有只读属性,但本质还是变量。所以不是真正的常量,它只是告诉编译器该变量不能出现在赋值符号的左边。

(2)const 修饰的局部变量在栈上分配空间,全局变量在只读存储区分配空间

(3)const 只在编译期有用,在运行期无用

#include <stdio.h>

int main()
{
    const int c = 0;   //C语言中会为变量c分配内存
    int* p = (int*)&c; //C++中遇到&才为c分配内存

    printf("Begin...\n");

    *p = 5;  //内存中的值己被改为5.

    printf("c = %d\n", c);//C语言会输出内存中的5.
                          //C++中会从符号表(而不是内存)中取值
                          //所以为0.

    printf("End...\n");
    return 0;
}

2. C++中的 const

(1)C++在 C 的基础上对 const 进行了优先处理,当碰见 const 声明时在符号表中放入常量。

(2)编译过程中若发现使用常量,则直接以符号表中的值替换。

C++深度解析教程学习笔记(1)C到C++的升级

(3)编译过程中若发现对 const 常量使用了 extern 或&操作符,则会给对应的常量分配存储空间。注意,C++编译器虽然可能为 const 常量分配空间,但不会使用其存储空间中的值。

3. 对比 C/C++中的 const

 

C语言

C++

本质

只读变量

常量

分配内存

会分配

当使用&操作符对const常量取地址时分配

当const常量为全局,并且需要在其它文件中使用时会分配内存

4. C++中的 const 与宏的区别

 

 

C++中的const

定义

const int c = 5;

#define c 5

处理方式

由编译器处理,编译器会进行类型检查和作用域检查

由预处理器处理,只是简单的文本替换

#include <stdio.h>

void f()
{
    //宏由预编译处理,其后面的宏起作用
    #define a 3

    const int b = 4;//作用域仅限于f函数
}

void g()
{
    printf("a = %d\n", a); //合法,只要是宏定义之后都可以使用
    
    //printf("b = %d\n", b); //非法b的作用域仅限于f函数
}

int main()
{
    const int A = 1;
    const int B = 2;
    int array[A + B] = {0};//C++中合法,因为它认为A、B都是常量。
                           //而C语言的const本质还是变量,数组大小只能是常量

    int i = 0;

    for(i=0;i<(A + B); i++)
    {
        printf("array[%d] = %d\n", i, array[i]);
    }

    f();
    g();

    return 0;
}

2.7 布尔类型

(1)C++在 C 语言的基本类型系统之上增加了 bool,其可能的取值只有 true(1)和false(0)

(2)理论上 bool 只占用一个字节

(3)bool 类型是基本类型,可以用来定义 bool 型的全局变量、常量、指针和数组等。

(3)C++编译器会将非 0 值转换 true(即 1),0 值转换为 false(即 0)

#include <stdio.h>

int main()
{
    bool b = false;
    int a = b;

    printf("sizeof(b) = %d\n", sizeof(b)); //1
    printf("b = %d\n, a = %d\n", b, a);    //0, 0

    b = 3;  //编译器发现会bool型赋值非0,就会转化为1
    a = b;  //a为1

    printf("b = %d, a = %d\n",b, a);
    
    b = -5; //非0,被转为1
    a = b;  //a为1

    printf("b = %d, a = %d\n",b, a); //1,1

    a = 10; 
    b = a; //非0,被转为1

    printf("a = %d, b = %d\n",a, b); //10,1

    a = 0; 
    b = a; //0

    printf("a = %d, b = %d\n",a, b); //0,0

    return 0;     
}

2.8 三目运算符

(1)C 语言中的三目运算符返回的是变量的值,因值不能作为左值使用

(2)C++中的三目运算符

   ①如果?后面的两个操作数有一个是常量,则行为与 C 语言的运算符一样,返回的是变量的值。

   ②如果?后面的两个操作数都是变量,则返回变量的引用(相当于变量本身),如此,既可以作为右值,也可以作为左值使用。

#include <stdio.h>

int main()
{
    //C++中的三目运算符
    int m = 1;
    int n = 2;
    
    printf("m = %d, n = %d\n", m, n);

    (m < n ? m : n) = 3;//?后的m、n都是变量,返回的是引用,
                        //将3赋值给一个变量的引用,是合法的


    //(m < n ? m : 2) = 3;//?后的操作数2为常量,将返回的是值,
                        //从语义看,要将3赋值给2,是非法的

    printf("m = %d, n = %d\n", m, n);

    //在C语言中,可通过其返回的是值的特点,可以通过如下方式来修改m或n
    *(m < n ?&m : &n) = 4;//返回m,n的地址,再通过地址给变量赋值,非法的。
    
    printf("m = %d, n = %d\n", m, n);

    return 0;     
}