zoukankan      html  css  js  c++  java
  • Thinking in C++ 第三章 C++中的C

    一、函数的声明和定义

    1. 函数重载

    C语言中函数不能被重载。

    2. 函数使用前的函数声明

    C语言中:

    如果函数在使用之前没有进行声明,那么编译器会对其进行隐式声明:

    假设这个函数的返回类型为int类型,但不对其参数做任何假设。

    C++中:

    一个函数在使用之前必须进行声明。

    3. 在函数声明中没有参数列表

    C语言中:

    如果一个函数声明没有参数列表,如下:int func();

    那么编译器不会对func的参数做任何假设,并且不会检查func的参数是否合法。这时,

    func可以定义为:int func(int i){}

    上述func函数的定义不会出错,因为编译器已经关闭了对其参数的检查。

    C++中:

    如果一个函数声明没有参数列表,则表明这个函数没有参数,等价于:int func(void);

    4. 函数定义中未命名的参数

    C语言中:

    每一个参数都必须指定名字,若函数定义为如下形式:int func(int ){}

    则,编译器就会报错

    C++中:

    允许出现未命名的参数。当然,如果一个参数没有名字,那么也就无法使用它。

    5. 忽略返回值类型

    C语言中:

    如果一个函数声明或函数定义忽略返回值类型,如:fun(void);

    那么这个函数的返回类型默认为是int类型。

    C++中:

    上述情况不合法,一个函数声明或定义必须显示的指定它的返回类型。

    6. 函数中的return

    C语言中:

    编译器不会检查函数的返回类型,如:int func(){}

    上述定义是不会出错的,但是它的返回值是没有意义的。

    C++中:

    编译器会强制检查函数的返回值类型。

    二、内部链接 外部链接

    在一个程序中标识符代表存放变量或被编译过的函数体的存储空间。链接这些变量或函数的方式有两种:内部链接(internal linkage)和外部链接(external linkage)

    如果一个变量的链接方式是内部链接,那么意味着此变量只在定义它的文件中可见,对于这个变量的引用仅限于这个文件;在其他的文件中可以使用相同的名字定义标识符,这不会引起命名冲突。在c/c++中,内部链接是由关键字static指定的。

    全局变量(C++中的const常量除外)和函数 默认为外部链接。在其他文件中可以使用extern关键字来访问具有外部链接的标识符。在全局变量定义时可以使用static关键字修饰,使它们成为内部链接方式;也可以使用extern关键字进行修饰,显示指定标识符为外部链接。

    对于局部变量来说,它们不存在链接方式。因为局部变量只是临时存在于堆栈,链接器看不到它们。

    C++中的const常量(不是C语言)是一个特例,它默认为内部链接的方式,若想使它变为外部链接,则必须使用extern关键字进行修饰。

    三、const

    C语言中的const

    C语言中对于表达式:const int i = 0;

    它的含义是定义了一个变量i,并且变量i的值不能被修改。

    你不能使用一个const变量定义一个数组,如下:

    const int size = 3;

    char arr[size]; // 错误,因为size是一个变量而不是常量

    C语言中定义常量的方式有两种,

    1. 使用宏,如:#define size 3

    2. 使用enum,如:enum{size = 3};

    C++中的const

    C++中,const有许多种用法,这里只讨论使用它定义常量的情况

    C++中对于表达式:const int size = 0;

    它的含义是定义了一个常量size,它可以被这样使用:

    char arr[size];

    对于表达式:const int size = str.size();

    此时,这个size就不是一个常量了,因为它的值不能再编译期间确定。

    const在这里的含义只是表示:size的值不能被改变。

    如果你这样使用size

    char arr[size]; // 错误,此时size不是常量

    所以说在C++中使用const修饰的标识符可能是常量也可能是变量。

    使用const常量替换宏常量

    宏常量只是简单的进行值替换,它无法进行类型检查,这可能会导致一些问题;而使用const常量则可以避免这些问题。

    要在多个文件中使用const常量,可以把const常量的定义放在头文件中。要使用这个常量,只需包含头文件即可。因为const常量的链接方式是内部链接,所以这不会造成命名冲突。

    const常量的存储空间

    先给出这样一个结论:如果在程序中不需要const常量的地址,那么编译器不会为const常量分配存储空间。

    如果程序中只使用了const常量的值,而没有使用它的地址的话,那么这个const常量会被保存在符号表中,不用在堆或栈中为其分配存储空间。

     

    const常量分配存储空间的情况:

    1.       示例代码如下:

    const int i = 10;        // 定义了一个整型的常量

    void *addr = (void *)&i; // i的地址

    分析:第一行定义了一个编译期的常量i,第二行需要i的地址,此时编译器被迫为i分配了内存空间,因为只有这样,i才会具有一个地址。

    2.       示例代码如下:

    extern const int i = 10; // 使用extern修饰i,使之成为外部链接的方式

    分析:此时i成为了外部链接的方式,这意味着其他的编译单元也可以对它进行引用,因此编译器必须为它分配空间。

    四、volatile关键字

    volatile关键字告诉编译器,这个变量是“易变的”,不要对它做任何优化。这样做的好处是,一旦某个变量发生变化,程序会立刻知道它。例如在多线程 程序中A线程根据某个变量的值而进行某些操作,将这个变量定义为volatile的,这样这个变量一旦被修改,线程A就会检测到。

    五、逗号运算符

    一个例子:

    1 int a = 0, b = 1,c = 2, d = 3;
    a = (b++, c++, d++); // 相当于 (a = b++), c++, d++, e++;

    也就是说,逗号运算符返回的是最后一个表达式的值。

    六、宏

    宏的两个特殊的用法:

    先看如下示例:

    1 #define OUT(x) cout<<#x ” = ”<<endl  // 输出一个变量
    2 #define DEFINT(x) int int_##x       // 定义一个int类型的变量
    3  
    4 DEFINT(1);   // 产生如下定义:int int_1;
    5 int_1 = 1;
    6 OUT(int_1);  // 输出:int_1 = 1

     

    1. 字符串定义

    如上例所示,使用#x可以产生一个字符串,

    如果传递进来的xabc,那么将产生”abc”

    如果传递进来的x123,那么将产生”123”

     

    这个特性在某些情况下非常有用,比如可以利用上例中的OUT宏来跟踪一个变量的值。

    1 int a = 1;
    2 int b = 2;
    3 OUT(a);   // 输出:a = 1
    4 OUT(b);   // 输出:b = 2

    2. 标志粘贴

    如上例所示,使用 ## 可以将其两边的符号连接起来

    比如:a ## b,将会产生标识符:ab##会忽略第一次遇到的空格

    在某些情况你可能想要创建许多以某种前缀开头的变量,那么就可以如上例中的DEFINT一样定义自己的宏。 

     以后会关注的

     1. C/C++中调用其他语言,如汇编,Python

     2. makefile 

  • 相关阅读:
    第七节:详细讲解Java中的日期,java.util.date
    第七节:详细讲解Java中的日期,java.util.date
    第六节:详细讲解Java中的装箱与拆箱及其字符串
    第六节:详细讲解Java中的装箱与拆箱及其字符串
    第五节:详细讲解Java中的接口与继承
    第五节:详细讲解Java中的接口与继承
    第四节:详细讲解Java中的类和面向对象思想
    第四节:详细讲解Java中的类和面向对象思想
    第三节:带你详解Java的操作符,控制流程以及数组
    第三节:带你详解Java的操作符,控制流程以及数组
  • 原文地址:https://www.cnblogs.com/hdtianfu/p/2275081.html
Copyright © 2011-2022 走看看