博客文章

浅谈一下C语言中的const

作者: andy.      时间: 2016-03-04 20:18:58

        刚刚在学习C语言的时候使用到strcpy函数的时候,可以看到其原型char *strcpy(char* dest, const char *src);中间有个const呢,研究一下下这个const......

        看看const在各个位置会发生什么。

    int main(void){
        int value_1 = 1;
        int value_2 = 2;
    
        int const *i = &value_1;

        *i = 2;
    }

        因为在const后面跟的是(*i),那么(*i)即为常量。所以在编译的时候自然发生如下错误:

    PS D:\Visual Studio\Projects\C__> gcc .\const.c
    .\const.c: In function 'main':
    .\const.c:7:13: error: assignment of read-only location '*i'
              *i = 2;
                 ^

        提示给得非常清楚,(*i)是只读的。继续测试,将*i = 2;修改为i = &value_2;即:

    int main(void){
        int value_1 = 1;
        int value_2 = 2;

        int const *i = &value_1;

        //*i = 2;

        i = &value_2;
    }

        编译通过。        


        继续修改代码,将const放在*和i之间并对*i进行赋值操作:

    int main(void){
        int value_1 = 1;
        int value_2 = 2;

        int * const i = &value_1;

        *i = 2;

        //i = &value_2;
    }

        这样子是能够编译通过的。当时将*i = 2;修改为i = &value_2;就会提示错误:

        4.png

        同样,可以看出,编译器提示指针变量i是只读的。

        到这儿就已经可以看出const后面跟的是什么,那么其就为只读。        


        继续修改代码进行测试,二级指针:

    int main(void){
        int value_1 = 1;
        int value_2 = 2;

        int *i = &value_1;
        int * const * j = &i;

        *j = &value_2;
    }

        编译报错,错误提示得很明显:

    PS D:\Visual Studio\Projects\C__> vim .\const.c
    PS D:\Visual Studio\Projects\C__> gcc .\const.c
    .\const.c: In function 'main':
    .\const.c:8:22: error: assignment of read-only location '*j'
                       *j = &value_2;
                          ^

        assignment of read-only location '*j'

        证明刚才的推论是正确的。        


        既然编译器报错*j是只读的,那么j存的是i的地址,*j即是存储i的内存块。那么我们往*i中写数据是不会出现错误的。代码测试:

    int main(void){    
        int value_1 = 1;
        int value_2 = 2;
    
        int *i = &value_1;
        int * const * j = &i;
    
        //*j = &value_2;
        *i = value_2;
    }
    int main(void){    
        int value_1 = 1;
        int value_2 = 2;
    
        int *i = &value_1;
        int * const * j = &i;
    
        **j = value_2;
    }

        编译通过。


        看看这种情况:

    int main(void){    
        int value_1 = 1;
        int value_2 = 2;
    
        int *i = &value_1;
        int const ** j = &i;
    
        //*j = &value_2;
    }

        编译一下,看看情况:

        7.png

        居然报错了,这是怎么回事儿?看看,int const ** j = &i;那么**j是只读的,可是在第五行,int *i = &value_1;我们并没有把其定义为只读,所以报了一个指针不匹配的错误。为了验证猜想,将int *i = &value_1;改为int * const i = &value_1;编译就通过了。。


        继续上面的代码上继续验证一下,因为**j 和 *i 是只读的,那么i应该不会受只读的影响。修改代码:

    int main(void){    
        int value_1 = 1;
        int value_2 = 2;
    
        int const *i = &value_1;
        int const ** j = &i;
        *j = &value_2;
    }

        果然编译通过。



        发现在定义函数的时候定义形参的时候为了防止指针位置的到处移动,最后数组之类的指针指向哪儿都不知道了~~~灵活运用const是非常有效的一个方法。