【C功能体】关键字:typedef、const与define

本文主要讲解:

  • typedef在基础数据类型、在指针、在结构体、在指向结构体的指针、在枚举类型的用法;
  • const和define语法和本质区别,用法注意事项;

 


typedef

1、typedef为各种数据类型定义一个新名字。

#include<stdio.h>
typedef int Interger;
typedef unsigned int UInterger;
typedef float Float;
int main()
{
	Interger i = -1;
	UInterger ui = 1;
	Float f = 12.33f;
	printf("%d %d %.2f", i, ui, f);
}

2、typedef与指针

#include <stdio.h>

typedef char *String;

int main(int argc, const char * argv[])
{
	// 相当于char *str = "This is a string!";
	String str = "This is a string!";
	printf("%s", str);
	return 0;
}

3、typedef与结构体

#include<stdio.h>

struct MyPoint
{
	float x;
	float y;
};

typedef struct MyPoint point; //起别名
int main()
{
	struct MyPoint p;
	p.x = 10.0f;
	p.y = 20.0f;

	point pp;
	pp.x = 10.0f;
	pp.y = 20.0f;

	return 0;
}

// 定义一个结构体,顺便起别名
typedef struct MyPoint {
	float x;
	float y;
} Point;

//甚至可以省略结构体名称:
typedef struct {
	float x;
	float y;
} Point;

4、typedef与指向结构体的指针

#include <stdio.h>

// 定义一个结构体并起别名
typedef struct {
	float x;
	float y;
} Point;

// 起别名
typedef Point *PP;

int main(int argc, const char * argv[]) {
	// 定义结构体变量
	Point point = { 10, 20 };

	// 定义指针变量
	PP p = &point;

	// 利用指针变量访问结构体成员
	printf("x=%f,y=%f", p->x, p->y);
	return 0;
}

5、typedef与枚举类型

// 定义枚举类型
enum Season { spring, summer, autumn, winter };
// 给枚举类型起别名
typedef enum Season Season;

int main(int argc, const char * argv[]) {
	// 定义枚举变量
	Season s = spring;
	return 0;
}
// 定义枚举类型,并且起别名
typedef enum Season {spring, summer, autumn, winter} Season
甚至可以省略枚举名称,简化为:
typedef enum {spring, summer, autumn, winter} Season;

6、typedef与指向函数的指针

#include <stdio.h>

// 定义一个sum函数,计算a跟b的和
int sum(int a, int b) {
	int c = a + b;
	printf("%d + %d = %d", a, b, c);
	return c;
}

//给指向函数的指针类型,起了个别名叫MySum,被指向的函数接收2个int类型的参数,
//返回值为int类型。
typedef int(*MySum)(int, int);

int main(int argc, const char * argv[]) {
	// 定义一个指向sum函数的指针变量p
	//int (*p)(int, int) = sum; //原始
	MySum p = sum; //使用了typedef后

				   // 利用指针变量p调用sum函数
	(*p)(4, 5);

	return 0;
}

const和define

 

一句话说明白它们之间的区别:const是定义一个不可再变的量(常量),define是为一个变量或表达式定义一个别名,在使用时替换成变量或表达式。

 

const

  1. 本质上来说,const修饰的是假常量,它本质还是变量!只不过编译器不让你修改!const 是 constant 的缩写,意思是“恒定不变的”!
  2. const一般修饰于定义变量的前面,比如cosnt int a = 10,意味着a就一直是19,是一个不可修改的变量了。往后试图给a重新赋值都会引发错误。这就是const修饰之后的结果,但请注意,这里不可修改的原因其实是编译器在做检查,检查是否有修改这块内存上的值,一旦有就会报错,所以从根本上说,cosnt修饰的变量依然是一个变量!只不过编译器不让你修改而已!
  3. 用const float MAX = 255; 定义的常量有类型名字,存放在内存的静态区域中,在程序运行过程中const变量只有一个拷贝
  4. const是不可以定义函数的
  5. 用const定义的常量是可以用指针去指向该常量的地址的;

 

define

  1. 本质上来说,define修饰出来的是常量!并且是真常量
  2. 为什么说define修饰出来的是真常量呢?因为,define是宏定义,是宏替换,意味着程序在编译前期会进行文本替换,例如代码define PI 3.1415926 这句话,编译器会将代码中所有出现PI的地方全部用3.1415926替换,然后在进行编译,所以本质它就是一个常量!
  3. 用#define MAX 255定义的常量是没有类型的,所给出的是一个立即数,编译器只是把所定义的常量值与所定义的常量的名字联系起来,define所定义的宏变量在预处理的时候进行替换,在程序中使用到该常量的地方都要进行拷贝替换;#define 所定义的宏变量却有多个拷贝,所以宏定义在程序运行过程中所消耗的内存要比const变量的大得多;
  4. 用define可以定义一些简单的函数
  5. 用define定义的常量是不可以用指针变量去指向
const与指针
const int* p;   //p可变,p指向的对象不可变
int const* p;  //p可变,p指向的对象不可变

int* const p;  //p不可变,p指向的对象可变
const int* const p;  //指针p和p指向的对象都不可变

编译器处理方式不同

  • define – 在预处理阶段进行替换
  • const – 在编译时确定其值
  •  
  • define是宏定义,程序在预处理阶段将用define定义的内容进行替换,因此程序运行时常量表中并没有用define定义的常量,系统不为其分配内存。
  • const常量是编译运行时的常量,系统为其分配内存。

类型与安全检查不同

  1. define – 无类型,不进行类型安全检查,可能会产生意想不到的错误(边际效应)
  2. const – 有数据类型,编译时会进行类型检查
define注意“边际效应”。

例:

#define N 2+3 //N的值是5

int a = N/2; //在编译时预想a=2.5,实际打印结果是3.5原因是在预处理阶段,编译器将a=N/2处理成a=2+3/2,这就是define宏的边际效应;所以我们应该写成#define N (2+3)

存储方式不同

  1. define – 不分配内存,给出的是立即数,有多少次使用就进行多少次替换,在内存中会有多个拷贝,消耗内存大
  2. const – 在静态存储区中分配空间,在程序运行过程中内存中只有一个拷贝,const可以节省空间,避免不必要的的内存分配

其他

  1. 在编译时, 编译器通常不为const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。
  2. define是宏定义,程序在预处理阶段将用define定义的内容进行替换,因此程序运行时常量表中并没有用define定义的常量,只作替换,不做计算,不做表达式求解。
#include <stdio.h>
#define N 10  //将代码中出现N的地方全部替换为10

int main()
{
	const int a = 10; //const强调不变性
	//a = 20;  报错!

	printf("%d, %d", N, a);
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值