zoukankan      html  css  js  c++  java
  • # const关键字

    1、遇到的情景

    int MaxSubsequenceSum(const int A[], int N)
    {
        int ThisSum, MaxSum, j;
        
        ThisSum = MaxSum = 0;
        for(j = 0; j < N; j++)
        {
            ThisSum += A[j];
            
            if(ThisSum > MaxSum)
                MaxSum = ThisSum;
            else if(ThisSum < 0)
                ThisSum = 0;
        }
        return MaxSum;
    }
    

    const限定符在这里的作用是使得传入的数组得状态是只读,就是无法修改。

    2、扩充

    C90标准中新增了const关键字,用于限定一个变量为只读(在C语言中,用const类型限定符声明的是变量,不是常量)。其声明如下:

    const int MONTHS = 12; // MONTH在程序中不可更改,值为12
    

    这使得MONTHS成为一个只读值。也就是说,可以在计算机中使用MONTHS,可以打印MONTHS,但是不能更改MONTHS的值。

    注意,const的用法比#define指令更加灵活。可以创建const数组、const指针和指向const的指针。

    • 对形参使用const

    ANSI C提供了一种预防手段。如果函数的意图不是修改数组中的数据内容,那么在函数原型和函数定义中声明形式参数时应使用关键字const。例如,sum()函数的原型和定义如下:

    int sum(const int ar[], int n); /* 函数原型 */
    int sum(const int ar[], int n) /* 函数定义 */
    {
        int i;
        int total = 0;
        for( i = 0; i < n; i++)
        total += ar[i];
        return total;
    }
    

    以上代码中的const告诉编译器,该函数不能修改ar指向的数组中的内容。如果在函数中不小心使用类似ar[i]++的表达式,编译器会捕获这个错误,并生成一条错误信息。这里一定要理解,这样使用const并不是要求原数组是常量,而是该函数在处理数组时将其视为常量,不可更改。这样使用const可以保护数组的数据不被修改,就像按值传递可以保护基本数据类型的原始值不被改变一样。一般而言,如果编写的函数需要修改数组,在声明数组形参时则不使用const;如果编写的函数不用修改数组,那么在声明数组形参时最好使用const。

    • 使用const关键字保护数组
    #define MONTHS 12
    ...
    const int days[MONTHS] = {31,28,31,30,31,**,**,**,**,31,30,31};
    

    如果程序稍后尝试改变数组元素的值,编译器将生成一个编译期错误消息:

    days[9] = 44; /* 编译错误 */
    
    • 指向const的指针不能用于改变值。考虑下面的代码:
    double rates[5] = {88.99, 100.12, 59.45, 183.11, 340.5};
    const double * pd = rates;        // pd指向数组的首元素
    

    第2行代码把pd指向的double类型的值声明为const,这表明不能使用pd来更改它所指向的值:

    *pd = 29.89;        // 不允许
    pd[2] = 222.22;     // 不允许
    rates[0] = 99.99;   // 允许,因为rates未被const限定
    

    无论是使用指针表示法还是数组表示法,都不允许使用pd修改它所指向数据的值。但是要注意,因为rates并未被声明为const,所以仍然可以通过rates修改元素的值。另外,可以让pd指向别处:

    pd++; /* 让pd指向rates[1] -- 没问题 */
    
    • 指向const的指针通常用于函数形参中,表明该函数不会使用指针改变数据。例如:
    void show_array(const double *ar, int n);
    
    • 关于指针赋值和const需要注意一些规则。

    首先,把const数据或非const数据的地址初始化为指向const的指针或为其赋值是合法的:

    double rates[5] = {88.99, 100.12, 59.45, 183.11, 340.5};
    const double locked[4] = {0.08, 0.075, 0.0725, 0.07};
    const double * pc = rates;    // 有效
    pc = locked;                  // 有效
    pc = &rates[3];               // 有效
    

    然而,只能把非const数据的地址赋给普通指针:

    double rates[5] = {88.99, 100.12, 59.45, 183.11, 340.5};
    const double locked[4] = {0.08, 0.075, 0.0725, 0.07};
    double * pnc = rates;    // 有效
    pnc = locked;            // 无效
    pnc = &rates[3];         // 有效
    

    这个规则非常合理。否则,通过指针就能改变const数组中的数据。

    应用以上规则的例子,如show_array()函数可以接受普通数组名和const数组名作为参数,因为这两种参数都可以用来初始化指向const的指针:

    show_array(rates, 5);        // 有效
    show_array(locked, 4);       // 有效
    

    这样一来,就不可以通过指针改变数组中的数据了。因此,对函数的形参使用const不仅能保护数据,还能让函数处理const数组。

    另外,C标准规定,使用非const标识符修改const数据导致的结果是未定义的。即在函数的形参使用了const限定符,而传入的实参没有使用const限定符,这样的用法是不建议的。

    • const还有其他的用法。例如,可以声明并初始化一个不能指向别处的指针,关键是const的位置:
    double rates[5] = {88.99, 100.12, 59.45, 183.11, 340.5};
    double * const pc = rates;  // pc指向数组的开始
    pc = &rates[2];             // 不允许,因为该指针不能指向别处
    *pc = 92.99;                // 没问题 -- 更改rates[0]的值
    
    • 最后,在创建指针时还可以使用const两次,该指针既不能更改它所指向的地址,也不能修改指向地址上的值:
    double rates[5] = {88.99, 100.12, 59.45, 183.11, 340.5};
    const double * const pc = rates;
    pc = &rates[2];     //不允许
    *pc = 92.99;        //不允许
    

    说起来,这些个用法确实是有些繁琐,还是需要在实际使用的过程中来慢慢巩固的。

    参考与摘录:《C Primer Plus》


    未完待续...

  • 相关阅读:
    [转]进程与线程及其区别
    [转]工厂模式
    [转]Filter实现处理中文乱码,转义html标签,过滤敏感词
    [转]JAVA设计模式之单例模式
    [转]Servlet 中文乱码问题及解决方案剖析
    Servlet作业2-将表单提交的商品信息输出到页面中
    Servlet作业1-实现注册登录
    [转] ServletContext 与application的异同
    [转]servlet中的service, doGet, doPost方法的区别和联系
    [转]Servlet 3.0 新特性详解
  • 原文地址:https://www.cnblogs.com/fanlumaster/p/13643073.html
Copyright © 2011-2022 走看看