C语言中的typedef和define static和const的用法和不同:

typedef和define:
是给对象起另外的名字,主要为了简化程序和增强可读性,区别如下
(1)原理不同
#define是C语言中定义的语法,是预处理指令,也称作宏定义,在预处理时进行简单而机械的字符串替换,不作正确性检查,只有在编译已被展开的源程序时才会发现可能的错误并报错。typedef是关键字,在编译时处理,有类型检查功能。它在自己的作用域内给一个已经存在的类型一个别名,但不能在一个函数定义里面使用typedef。用typedef定义数组、指针、结构等类型会带来很大的方便,不仅使程序书写简单,也使意义明确,增强可读性。加上typedef,会由这种变量上升为这种类型比如:typedef int (pfun)(int,int)加上typedef会由函数指针变量变为函数指针类型。
(2)功能不同
typedef用来定义类型的别名,让读者更好记。另一个功能是定义机器无关的类型。如定义一个REAL的浮点类型,在目标机器上它可以获得最高的精度:typedef long double REAL,在不支持long double的机器上,看起来是这样的,typedef double REAL,在不支持double的机器上,是这样的,typedef float REAL。#define不只是可以为类型取别名,还可以定义常量、变量、编译开关等
(3)作用域不同
#define没有作用域的限制,只要是之前预定义过的宏,在以后的程序中都可以使用,而typedef有自己的作用域。
(4)对指针的操作不同
#define INTPTR1 int

typedef int* INTPTR2;
INTPTR1 p1, p2; //声明一个指针变量p1和一个整型变量p2
INTPTR2 p3, p4; //声明两个指针变量p3和p4
#define INTPTR1 int*
typedef int* INTPTR2;
int a = 1;
int b = 2;
int c = 3;
const INTPTR1 p1 = &a;
const INTPTR2 p2 = &b;
INTPTR2 const p3 = &c;
上述代码中,
const INTPTR1 p1是一个常量指针,即不可以通过p1去修改p1指向的内容,但是p1可以指向其他内容。
const INTPTR2 p2是一个指针常量,不可使p2再指向其他内容。因为INTPTR2表示一个指针类型,因此用const限定,表示封锁了这个指针
static和const
static在C语言中主要是两种用法
1、修饰局部变量
2、修饰函数和全局变量
局部变量:按照存储形式来分,分为auto,static,register
首先从内存四区的角度去看,
auto即为普通的局部变量,存储在栈上,当函数结束时,随之释放。
register为寄存器变量,存放在寄存器里面,调用速度快。 在C语言中register变量不能取地址,会报错。而在c++中,对register做了增强,当C++编译器发现程序中需要取register变量的地址时,register对变量的声明变得无效。
static修饰局部变量时该变量是存放在静态存储区,生命周期是整个程序结束。
static局部变量初次定义时就要初始化,且只能初始化一次。如果在定义的时候不初始化,编译器就会自动赋值为0;(也就是说如果重复调用同一个函数,在第二次调用时,就不会再执行static局部变量初始化那句话了)
特点:static局部变量的”记忆性”与生存期的”全局性”
所谓”记忆性”是指在两次函数调用时, 在第二次调用进入时, 能保持第一次调用退出时的值.
注意事项:

  1. “记忆性”,程序运行很重要的一点就是可重复性, 而static变量的”记忆性”破坏了这种可重复性, 造成不同时刻至运行的结果可能不同.
  2. “生存期”全局性和唯一性. 普通的local变量的存储空间分配在stack上, 因此每次调用函数时,分配的空间都可能不一样,而static具有全局唯一性的特点,每次调用时,都指向同一块内存,这就造成一个很重要的问题,不可重入性。
    二、当static修饰全局变量或者函数时,不是为了限制其存储方式,而主要是为了限制该全局变量或者函数的作用域仅限于本文件,所以又称为此件时,对于外部(全局)变量,不论是否有static限制,它的存储区域都是在静态存储区, 生存期都是全局的.此时的static只是起作用域限制作用,限定作用域在本模块(文)内部。
    使用内部函数的好处是:不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名。
    const:关键字const用来定义常量,如果一个变量被const修饰,那么它的值就不能再被改变,我想一定有人有这样的疑问,C语言中不是有#define吗,干嘛还要用const呢,我想事物的存在一定有它自己的道理,所以说const的存在一定有它的合理性,与预编译指令相比,const修饰符有以下的优点:
    1、预编译指令只是对值进行简单的替换,不能进行类型检查
    2、可以保护被修饰的东西,防止意外修改,增强程序的健壮性
    3、编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。
    总结:static用于全局变量和函数时用于限制作用域,只允许在本文件中使用。在C语言中,一般进行声明之后全局变量及函数可以整个程序使用,但是如果有static修饰则只能在同一个c文件使用;用于局部变量是用于存储的不一样,存储将会没有可重复性,第二次调用函数将会使用上一次停留的结果。
    const的作用:
    1.修饰变量说明该变量不能改变
    2.修饰指针,分为指向常量的指针和指针常量
    3.修饰成员函数,说明成员函数内不能修改成员变量
    总之被const修饰的东西都收到保护,可以预防意外更改,可以提高程序的健壮性
    c与c++各是如何定义常量的?有什么不同?
    c中使用#define(宏) c++使用const修饰
    区别:
    1.const是有数据类型的,宏常量没有数据类型,编译器可以对const修饰的变量进行类型安全检查,对宏仅仅是替换,没有类型安全检查,而在字符替换可能会发生意想不到的错误
    2.有些编译器可以对const常量进行调试,不能对宏进行调试
    staic中的作用
    1.隐藏。当我们同时编译多个文件时,所有未加static的全局变量和函数都具有全局可见性,故使用static在不同的文件中定义函数和变量名,不必担心命名冲突。
    2.保持变量内容的持久性。存储在静态数据区的变量会在程序刚开始运行就完成初始化,也是唯一的一次初始化。
    3.默认初始化为0,全局变量也一样。
    const的用法:
    一、修饰局部变量
    const int n=5;等同于int const n=5;
    这两种写法是一样的,都是表示变量n的值不能被改变了,需要注意的是,用const修饰变量时,一定要给变量初始化,否则之后就不能再进行赋值了。
    接下来看看const用于修饰常量静态字符串,例如:
    const char* str=”fdsafdsa”;
    如果没有const的修饰,我们可能会在后面有意无意的写str[4]=’x’这样的语句,这样会导致对只读内存区域的赋值,然后程序会立刻异常终止。有了const,这个错误就能在程序被编译的时候就立即检查出来,这就是const的好处。让逻辑错误在编译期被发现。
    二、常量指针与指针常量
    常量指针是指针指向的内容是常量,可以有一下两种定义方式。
    const int * n;
    int const * n;
    需要注意的是一下两点:
    1、常量指针说的是不能通过这个指针改变变量的值,但是还是可以通过其他的引用来改变变量的值的。
int a=5;
const int *n=&a;
a=6;

2、常量指针指向的值不能改变,但是这并不是意味着指针本身不能改变,常量指针可以指向其他的地址。

int a=5; 
int b=6; 
const int* n=&a; 
n=&b;

指针常量是指指针本身是个常量,不能在指向其他的地址,写法如下:
int *const n;
需要注意的是,指针常量指向的地址不能改变,但是地址中保存的数值是可以改变的,可以通过其他指向改地址的指针来修改。

int a=5; 
int *p=&a; 
int* const n=&a; 
*p=8;

区分常量指针和指针常量的关键就在于星号的位置,我们以星号为分界线,如果const在星号的左边,则为常量指针,如果const在星号的右边则为指针常量。如果我们将星号读作‘指针’,将const读作‘常量’的话,内容正好符合。int const * n;是常量指针,int const n;是指针常量。
指向常量的常指针
是以上两种的结合,指针指向的位置不能改变并且也不能通过这个指针改变变量的值,但是依然可以通过其他的普通指针改变变量的值。
const int
const p;
三、修饰函数的参数
根据常量指针与指针常量,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、以上两种的结合。
四、修饰函数的返回值
如果给以“指针传递”方式的函数返回值加 const 修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const 修饰的同类型指针。
例如函数
const char * GetStr
如下语句将出现编译错误:

char *str = GetString();
正确的用法是
const char *str = GetString();

五、修饰全局变量
全局变量的作用域是整个文件,我们应该尽量避免使用全局变量,因为一旦有一个函数改变了全局变量的值,它也会影响到其他引用这个变量的函数,导致除了bug后很难发现,如果一定要用全局变量,我们应该尽量的使用const修饰符进行修饰,这样防止不必要的人为修改,使用的方法与局部变量是相同的。

猜你喜欢

转载自blog.csdn.net/chris__x/article/details/88866430