C语言 变量
一.const
被 const 修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。
1.const 使用
使用const修饰变量必须初始化
用 const 修饰的变量,无论是全局变量还是局部变量,生存周期都是程序运行的整个过程。
而使用 const 修饰过的局部变量就有了静态特性,它的生存周期也是程序运行的整个过程。
但是用 const 修饰过的局部变量只是有了静态特性,并没有说它变成了静态变量。
2.const 修饰指针
a.指针
int *p = 5;
/*p:指针的内存地址,类似门牌号,十六进制表示:0xffff
*p:指针的内存地址对应的值,类似门牌号对应里面住的人,即5
*/
b.const int *p & int const *p
const int *p 和 int const *p是等价的
当把 const 放最前面的时候,它修饰的就是 *p,那么 *p 就不可变。*p 表示的是指针变量 p 所指向的内存单元里面的内容,此时这个内容不可变 。
其他的都可变,如 p 中存放的是指向的内存单元的地址,这个地址可变,即 p 的指向可变。但指向谁,谁的内容就不可变。
# include <stdio.h>
int main(void)
{
int a = 10;
const int *p = &a;
int * q = &a;
*q = 20;
printf("a = %d\n", a);
a = 30;
printf("a = %d\n", a);
//const int *p = &a; //表示 *p 值不能发生改变否则 error: assignment of read-only location '* p'
//*p = 30; //这么写就是错的
return 0;
}
/*
输出:a = 20
a = 30
*/
c.int * const p
此时 const 修饰的是 p,所以 p 中存放的内存单元的地址不可变,而内存单元中的内容可变。即 p 的指向不可变,p 所指向的内存单元的内容可变。
# include <stdio.h>
int main(void)
{
const char *p = "hello"; //(*p)值不变,但p代表的起始地址可变
char* const q = "bbb"; //q地址不能改变(即q值不变)
p++; //ok
//q++; //这句是错误的. error: increment of read-only variable 'q'
printf("%s\n",p);
printf("%s\n",q);
return 0;
}
/*
输出:
ello
bbb
*/
d. const int * const p
*p 和 p 都被修饰了,那么 p 中存放的内存单元的地址和内存单元中的内容都不可变。
3.const 修饰在函数名前面
当 const 在函数名前面的时候修饰的是函数返回值;在函数名后面表示是 C++ 常成员函数,该函数不能修改对象内的任何成员,只能读操作,不能写操作。
const char * GetString(void);
const double GetDdouble(void);
如果给以“指针传递”方式的函数返回值加 const 修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加 const 修饰的同类型指针;
const char * GetString(void);
//如下语句将出现编译错误:
//char *str = GetString();
//正确的用法是
const char *str = GetString();
4.const 修饰在函数名后面
当 const 在函数名前面的时候修饰的是函数返回值;在函数名后面表示是 C++ 常成员函数,该函数不能修改对象内的任何成员,只能发生读操作,不能发生写操作。
5.const 修饰函数参数
如果函数参数采用“指针传递”,那么加 const 修饰可以防止意外地改动该指针,起到保护作用。
void StringCopy (char*strDestination, const char *strSource);
其中 strSource 是输入参数,strDestination 是输出参数。给 strSource 加上 const 修饰后,如果函数体内的语句试图改动 strSource 的内容,编译器将指出错误。
如果输入参数采用“值传递”,由于函数将自动产生临时变量用于复制该参数,该输入参数本来就无需保护,所以不要加 const 修饰。
例如不要将函数 void Func1(int x) 写成 void Func1(const int x)。
如果参数作为输出参数,不论它是什么数据类型,也不论它采用“指针传递”还是“引用传递”,都不能加 const 修饰,否则该参数将失去输出功能(因为有 const 修饰之后,不能改变他的值)。
如果参数作为输入参数,可以防止数据被改变,起到保护作用,增加程序的健壮性;
二. define
1.define用法
//定义常量
#define MAX_VALUE 100 //定义整型变量MAX_VALUE值为100
#define USER_NAME "huge" //定义字符串变量USER_NAME值为"huge"
#define PI 3.1415926 //定义浮点数变量PI值为3.1415926
//定义函数
#define MAX(a,b) (a>b)?a:b //取两个数最大值
#define MIN(a,b) (a<b)?a:b //取两个数最小值
2.const比define的优点
const 可节省空间,避免不必要的内存分配,提高效率
三. 枚举常量enum
1.赋值
#include <stdio.h>
enum color
{
red,
green,
yellow
};
int main()
{
printf("%d\n", red); //0
printf("%d\n", green); //1
printf("%d\n", yellow);//2
return 0;
}
但是我们又需要注意,如果只给其中一个枚举常量赋值,但是后面的值没有被赋予。那么后的常量会根据被赋予值开始,依次递增。而被赋值前的值从0开始递增。
#include <stdio.h>
enum color
{
red,
black,
green = 4,
yellow
};
int main()
{
printf("%d\n", red); //0,被赋予值之前的从0开始递增
printf("%d\n", black); //1
printf("%d\n", green); //4,被赋予值之后,从赋予值开始递增
printf("%d\n", yellow); //5
return 0;
}
2.使用
有了枚举常量之后,我们可以这样使用。这样能够方便的得知我所选择的颜色是什么,并且根据所选的颜色进行相对应的操作。
#include <stdio.h>
enum color
{
red,
green,
yellow
};
int main()
{
int Select_color = red;
if (Select_color == red)
{
printf("red\n");
}
if (Select_color == green)
{
printf("green\n");
}
if (Select_color == yellow)
{
printf("yellow\n");
}
return 0;
}
3.应用
看下面图片,我们有一个IE中断运行寄存器。从最低位B0到最高位B7,有七个bit位。每一位表示进行一个操作,很明显我们难以记下来。那怎么办呢?枚举就是最好的办法
如下为枚举之后的代码。很明显,如果我们想打开寄存器中的某一个位,就不需要再去看数据手册了,直接根据这个枚举就很轻松的可以随意操作。
#include <stdio.h>
enum IE
{
EX0 = 0x01,//0000 0001
ET0 = 0x02,//0000 0010
EX1 = 0x04,//0000 0100
ET1 = 0x08,//0000 1000
ES = 0x10,//0001 0000
ET2 = 0x20,//0010 0000
Retain = 0x40,//0100 0000
EA = 0x80 //1000 0000
};
int main()
{
int Select_IE = EX0;
if (Select_IE == EX0)
{
printf("EX0\n");
}
if (Select_IE == ET0)
{
printf("ET0\n");
}
if (Select_IE == EX1)
{
printf("EX1\n");
}
return 0;
}
4.注意
不能给枚举常量赋值是说,不能再enum外给枚举常量赋值。
#include <stdio.h>
enum IE
{
EX0 = 0x01,//0000 0001
ET0 = 0x02,//0000 0010
EX1 = 0x04,//0000 0100
ET1 = 0x08,//0000 1000
ES = 0x10,//0001 0000
ET2 = 0x20,//0010 0000
Retain = 0x40,//0100 0000
EA = 0x80 //1000 0000
};
int main()
{
EX0 = 30; //报错,表达式必须是可修改的左值
int Select_IE = EX0; //可以,枚举常量的值可以赋予其他变量
return 0;
}
原文转载:
https://blog.csdn.net/ZhaDeNianQu/article/details/120195045
https://blog.csdn.net/qq_63922192/article/details/127324040