限定修饰符const

const int a = 1;
int const a = 1;

const关键字修饰变量a,表示a是一个整型变量,且这个变量的值是不可改变的。这两个定义的做用同样,编译后变量a分配在只读数据段中,这个数据段在一块只读的内存区域中,任何对这块区域的操做都是非法的。函数

以下面的程序:spa

#include <stdio.h>

int main(void)
{
  int const a = 100;
  a = 200;
  return 0;
}

编译器会报错:指针

因此在定义的时候对该变量温馨化是使得该变量具备值的惟一机会。调试

 

const关键字修饰指针--在指针定义以前

const关键字在指针变量的定义以前,以下所示:code

int const a = 100;
const int *p;  //指针指向的内容不能改变
//等同于 int const *p;
p = &a;

该定义表示p是一个指针变量,指向一个整型变量的存储空间,而且这个整型变量是一个不可改变的值的变量。也就是说指针p是能够改变的,而指针所指向的内容是不可改变的。内存

例如:开发

#include <stdio.h>

int main(void)
{
  int a = 100;
  int b = 200;
  const int *p;
  p = &a;
  printf("a = %d\n", *p);
  *p = 200;   //错误,指针所指向的内容(经过*p方式)不能改变
  p = &b;     //正确,指针自己能够改变
  printf("a = %d\n", *p);
  return 0;
}

运行结果为:字符串

const关键字修饰指针--在指针定义之中

const关键字在指针变量的定义之中:编译器

int a = 100;
int * const p = &a;  //指针自己不能改变

该定义表示p是一个指针变量,指向一个整型变量的存储空间,而且这个整型变量是一个能够改变值的变量。而指针p的值不能改变,只能永远指向这个内存单元,也就是说指针p是不能够改变的,而指向的内容是能够改变的。string

例如:

#include <stdio.h>

int main(void)
{
  int a = 100;
  int b = 200;
  int  * const p = &a;
  printf("a = %d\n", *p);
  *p = 200;   //正确,指针所指向的内容(经过*p方式)能够改变
  //p = &b;     //指针自己不能够改变
  printf("a = %d\n", *p);
  return 0;
}

运行结果:

const关键字修饰指针--在指针定义以前和定义之中

在指针变量定义以前和定义之中均有关键字,以下:

const int a = 100;
int const * const p = &a; //指针和指针指向的内容都不能改变

该定义表示a是一个指针变量,指向一个整型变量的存储空间。这个整型变量是一个不能改变值的变量,并且指针a的值也不能改变:

例如:

#include <stdio.h>

int main(void)
{
  int a = 100;
  int b = 200;
  int const * const p = &a;
  printf("a = %d\n", *p);
  *p = 200;   //错误,指针所指向的内容不能改变
  p = &b;     //错误,指针自己不能够改变
  printf("a = %d\n", *p);
  return 0;
}

编译结果:

指向非const变量的指针或者非const变量的地址能够传给指向const变量的指针,C语言能够作隐式转换,以下:

int a = 100;
const int *p;
p = &a;  //常量指针指向一个普通变量

可是指向const变量的指针,或者const变量的指针币能够传给非const变量的指针,以避免意外修改了const存储区的内容,以下:

const int a = 100;
int *p = &a;  //普通指针不能指向一个常量变量

使用const关键字的意义

  • 合理的只用cosnt关键字,可使编译器保护那些不但愿被改变的参数,防止被意外修改,能够较少bug的出现。
  • 关键字const是为了告诉用户这个参数的引用目的。例如一个函数的参数是const char*,这样用户就能够放心的传给它char*或者const char*指针,而没必要担忧指针所指的内存区域被改写
  • 经过给编译器一些附加信息,是const关键字也许能产生更紧凑的代码

第一点是最重要的,来看一个程序:

#include <stdio.h>

//将全部空格替换为"_",失败返回NULL
char * replace(char *str)
{
  char *p;
  if(str == NULL)
    return NULL;
  p = str;
  while(*p != '\0'){
    if(*p == ' ')
      *p = '_';  //进行字符串的替换
    p++;
  }
  return p;
}

int main(void)
{
  char *p = "hello world and china\n";
  if(replace(p) != NULL)
    printf("the string : %s\n", p);
  return 0;
}

编译并运行程序:

程序出现了段错误,说明内存访问出错了,这个错误出如今*p = '_';这个语句上。该语句将字符串的值修改,可是做为replace()函数的参数的源字符串是一个字符串常量,这个常量被分配在只读数据段中。所以对次字符串的操做形成了非法内存访问,出现了段错误。

若是使用const关键字能够很好的预防这个问题。

修改上面的程序,使用const关键字对字符创常量进行声明,编译器会发现修改常量的错误:

#include <stdio.h>

//将全部空格替换为"_",失败返回NULL
const char * replace(const char *str)  //使用const修饰变量
{
  const char *p;
  if(str == NULL)
    return NULL;
  p = str;
  while(*p != '\0'){
    if(*p == ' ')
      *p = '_';  //进行字符串的替换
    p++;
  }
  return p;
}

int main(void)
{
  const char *p = "hello world and china\n"; //将源字符串声明为const变量
  if(replace(p) != NULL)
    printf("the string : %s\n", p);
  return 0;
}

编译结果:

编译器报错,提示*p = '_';出错,程序试图写只读数据段的错误被编译器发现了,这时开发人员能够很容易就能够发现这个错误。原本在运行时才出现的错误,在编译阶段就由编译器发现了,这样就省了大量的调试时间,这对程序开发来讲是颇有益的。

相关文章
相关标签/搜索