一、const定义常变量
定义局部变量,未赋值:
参照对比,定义未赋值的常变量,无法通过编译:
尝试修改常变量的值:
2、const与define区别:
输出变量的地址,代码如下:
int a ;
printf(“%p\n”,&a);
#include <stdio.h>
int main()
{
int a = 10;
int *p;
p = &a;
printf("输出变量a的数值:%d\t%d\n", a, *p);
printf("输出变量a的地址:%p\t%p\n", &a, p);
return 0;
}
运行结果:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a = 100;
int *ap = &a;
printf("%p\n", &a);//输出:002AF744 输出的是a变量的地址
printf("%p\n", ap);//输出:002AF744 通过指针变量ap输出a变量的地址
printf("%p\n", &ap);//输出:002AF738 指针变量ap本身自己的地址
printf("%d\n", *ap);//输出:100
printf("%p\n", &*ap);//输出:002AF744
scanf("%d");
return 0;
}
代码如下:
#include <stdio.h>
int main()
{
#define NUM 3.14159 //常量宏
const double Num = 3.14159; //此时并未将Pi放入ROM中 ......
double i = Num; //此时为Pi分配内存,以后不再分配!
double I = NUM; //编译期间进行宏替换,分配内存
double j = Num; //没有内存分配
double J = NUM; //再进行宏替换,又一次分配内存!
printf("输出地址:\n");
printf("常变量Num的地址:%p\n",&Num);
printf("变量i的地址:%p\n", &i);
printf("变量I的地址:%p\n", &I);
printf("变量j的地址:%p\n", &j);
printf("变量J的地址:%p\n", &J);
}
运行结果:
链接中说的有问题!,每个变量还是要分配内存的。
const修饰字符串:.c中可以通过编译、但是无法运行;.cpp中报错为:E0144 "const char *" 类型的值不能用于初始化 "char *" 类型的实体 ;错误 C2440 “初始化”: 无法从“const char [12]”转换为“char *”
二、指针常量和常量指针
区分常量指针和指针常量的关键就在于星号的位置,我们以星号为分界线,如果const在星号的左边,则为常量指针,如果const在星号的右边则为指针常量。从左向右读!
- int const * n;是常量指针;
- int *const n;是指针常量。
1、int const * p 和 const int * p 常量指针
const修饰变量时, const int a 和 int const a 一样;因此上面也一致!
意思为:常量指针本质是指针,常量修饰它,表示这个指针乃是一个指向常量的指针(变量)。指针指向的对象是常量,那么这个对象不能被更改。(p)地址指向的内容不可以改变!
当用在函数传参数时:
使用字符串处理函数的时候,应该会注意到这些函数的声明。它们的参数一般声明为常量指针。例如,字符串比较函数的声明是这样的:
int strcmp(const char *str1, const char *str2);
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *str1, *str2;
str1 = "abcde1234";
str2 = "bcde";
//str1[1] = 'B'; //修改后不能运行
if (strcmp(str1, str2) == 0)
{
printf("str1 equals str2.");
}
else
{
printf("str1 not equals str2.");
}
return 0;
}
运行结果:
当试图修改str1时,会出现程序无法运行!
2、int * const p 指针常量
就是这个指针只能指向那个变量,但是那个变量的值可以改变!
解释:int * const p来说:首先p被const修饰p变量的内容是不能变的(如上面的基础类型的int const i)然后p又被告诉是指向整型变量的指针,那么也就是说p是一个指针变量,指针变量存储的内容是不能改变的,也就是说,p指针指向某一个地址,那么p就不能再指向其他地址了。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a = 5;
int *p = &a; //普通整形指针
int* const n = &a; //指针常量,由于congst挨着n,既n的内容(a的地址)不可改变,既只能指向a;
*p = 8;
printf("变量a的值为:%d\t%d\n",a,*n);
return 0;
}
运行结果:
3、const int* const p 指向常量的指针常量
const int a = 25;
const int * const b = &a;
看,指针声明操作符左边有一个const,说明声明的是一个指向常量的指针。再看,指针声明操作符右边有一个const,说明声明的是一个指针常量。前后都锁死了,那么指向的对象不能变,指针常量本身也不能变。
4、函数中的应用
根据常量指针与指针常量,const修饰函数的参数也是分为三种情况
1、防止修改指针指向的内容
void StringCopy(char *strDestination, const char *strSource);
其中 strSource 是输入参数,strDestination 是输出参数。给 strSource 加上 const 修饰后,如果函数体内的语句试图改动 strSource 的内容,编译器将指出错误。
2、防止修改指针指向的地址
void swap ( int * const p1 , int * const p2 )
指针p1和指针p2指向的地址都不能修改。
3、以上两种的结合。
简单总结:
int a=10;
int const * p=&a; //常量指针,指针的指向可以变化,但是a的值不能改变;用于:被调函数中的参数
const int *p=&a; //和上面一样,即const在int前后,效果是一样的
int * const p=&a; //指针常量,指针的指向是固定的,但是a的值可以变化
const int * const p =&a; //指向常量的指针常量,指针的指向是固定的,a的值也是固定的