C/C++关键字及运算符的简单用法3

1.typedef关键字
1.1简单介绍
C语言允许用户使用 typedef 关键字来定义自己习惯的数据类型名称,来替代系统默认的基本类型名称、数组类型名称、指针类型名称与用户自定义的结构型名称、共用型名称、枚举型名称等。一旦用户在程序中定义了自己的数据类型名称,就可以在该程序中用自己的数据类型名称来定义变量的类型、数组的类型、指针变量的类型与函数的类型等。
1.2简单用法
typedef的4种主要用法
1)为基本数据类型定义新的类型名。有利于增强程序的可拓展性。
示例:

typedef long double REAL;
typedef unsigned int COUNT;

当跨平台移植程序时,我们只需要修改一下 typedef 的定义即可,而不用对其他源代码做任何修改。其实,标准库中广泛地使用了这个技巧,比如 size_t 在 VC++2010 的 crtdefs.h 文件中的定义如下所示:

#ifndef _SIZE_T_DEFINED
#ifdef  _WIN64
typedef unsigned __int64    size_t;
#else
typedef _W64 unsigned int   size_t;
#endif
#define _SIZE_T_DEFINED
#endif

2)为自定义数据类型(结构体、共用体和枚举类型)定义简洁的类型名称。
以结构体为例,下面我们定义一个名为 Game的结构体

struct Game
{
    char * rule;
    char * name;
    int age;
};

在调用这个结构体时,我们必须像下面的代码这样来调用这个结构体:

strucy Game game1 = {"man","tom",20};

在这里,结构体 struct Game为新的数据类型,在定义变量的时候均要向上面的调用方法一样有保留字 struct,而不能像 int 和 double 那样直接使用 Game 来定义变量。现在,我们利用 typedef 定义这个结构体,如下面的代码所示:

typedef struct itGame
{
    char * rule;
    char * name;
    int age;
}Game;

在上面的代码中,实际上完成了两个操作:
1)定义了一个新的结构体itGame
2)使用 typedef 为这个新的结构起了一个别名,叫 Point,即:

typedef struct itGame Game;

但是typedef还是有坑的,例子如下:
在写链表时经常有:

typedef struct tagNode
{
    char *pItem;
    pNode pNext;
} *pNode;

上面的示例代码与前面的定义方法相同,所以应该没有什么问题。但是编译器却报了一个错误,为什么呢?莫非 C 语言不允许在结构中包含指向它自己的指针?
其实是因为:新结构建立的过程中遇到了 pNext 声明,其类型是 pNode。这里要特别注意的是,pNode 表示的是该结构体的新别名。于是问题出现了,在结构体类型本身还没有建立完成的时候,编译器根本就不认识 pNode,因为这个结构体类型的新别名还不存在,所以自然就会报错。因此,我们要做一些适当的调整,比如将结构体中的 pNext 声明修改成如下方式:

typedef struct tagNode
{
    char *pItem;
    struct tagNode *pNext;
} *pNode;

3)为数组定义简洁的类型名称
例如:

typedef int int_Array[10];
int_Array arr;

4)为指针定义简洁的名称

typedef char* PCHAR;
PCHAR arr;

适用于复杂类型的重命名

int *(*a[5])(int,char*);

除此之外还有一点需要特别注意:

typedef char* PCHAR;
int strcmp(const PCHAR,const PCHAR);

这里的“const PCHAR” 不是 “const char*”,而是char* const,因为typedef修饰的是一个指针所以const也是一样,此时const修饰的是一个指针并非所指的变量。

还需要特别注意的是,虽然 typedef 并不真正影响对象的存储特性,但在语法上它还是一个存储类的关键字,就像 auto、extern、static 和 register 等关键字一样。

2.define关键字
2.1简单介绍
C语言中,可以用 #define 定义一个标识符来表示一个常量。其特点是:定义的标识符不占内存,只是一个临时的符号,预处理后这个符号就不存在了。
用 #define 定义标识符的一般形式为:
#define 标识符 常量

凡是以“#”开头的均为预处理指令,#define也不例外。//在预处理时都会被替换。

还有变量名表示的是一个变量,但宏名表示的是一个常量。可以给变量赋值,但绝不能给常量赋值。

2.2解决的问题
宏定义最大的好处是“方便程序的修改”。使用宏定义可以用宏代替一个在程序中经常使用的常量。注意,是“经常”使用的。这样,当需要改变这个常量的值时,就不需要对整个程序一个一个进行修改,只需修改宏定义中的常量即可。且当常量比较长时,使用宏就可以用较短的有意义的标识符来代替它,这样编程的时候就会更方便,不容易出错。因此,宏定义的优点就是方便和易于维护。

2.3注意
宏定义 #define 一般都写在函数外面,与 #include 写在一起。当然,写在函数里面也没有语法错误,但通常不那么写。#define 的作用域为自 #define 那一行起到源程序结束。如果要终止其作用域可以使用 #undef 命令,格式为:
#undef
标识符undef 后面的标识符表示你所要终止的宏。比如前面在程序开头用 define 定义了一个宏 M,它原本的作用范围是一直到程序结束,但如果现在在程序中某个位置加了一句:

#undef 宏名

那么这个宏的作用范围到此就结束了。#undef 用得不多,但大家要了解。

2.3简单实例

#define MAX 100

2.4特别注意的与typedef的不同
看以下代码:

#include<iostream>
#include<typeinfo>
using namespace std;

#define PIN1 int *
typedef int * PIN2;

int main()
{
    PIN1 a,b;
    cout<<"用define类型为 "<<typeid(a).name()<<" "<<typeid(b).name()<<endl;
    PIN2 c,d;
    cout<<"用typedef类型为 "<<typeid(c).name()<<" "<<typeid(d).name()<<endl;
    return 0;
}

DEVC++输出如下:
tu这里先提一下怎么查看变量类型
使用typeinfo库里的typeid(变量).name()
如果想再了解可以查看以下文章
c++查看变量类型
在DECC++里Pi我指针,i为int类型
由上图可知define与typedef的不同。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include<iostream> #include<string> #include<algorithm> #include<cstring> #include<vector> using namespace std; //使用C++的标准名字空间 const int N = 1010; //用关键字const来定义常量 struct BigNum { //定义结构体 BigNum,用于存储大整数 int len; int num[N]; BigNum() { memset(num, 0, sizeof num); len = 0; } BigNum(string str) { memset(num, 0, sizeof num); len = str.length(); for (int i = 0; i < len; i++) { num[i] = str[len - 1 - i] - '0'; } } bool operator < (const BigNum &b) const { // 小于号运算符重载函数,用于比较两个 BigNum 类型的对象的大小 if (len != b.len) { return len < b.len; } for (int i = len - 1; i >= 0; i--) { if (num[i] != b.num[i]) { return num[i] < b.num[i]; } } return false; } bool operator > (const BigNum &b) const { //大于号运算符重载函数,用于比较两个 BigNum 类型的对象的大小 return b < *this; } bool operator <= (const BigNum &b) const { //小于等于号运算符重载函数,用于比较两个 BigNum 类型的对象的大小 return !(b < *this); } bool operator >= (const BigNum &b) const { //大于等于号运算符重载函数,用于比较两个 BigNum 类型的对象的大小 return !(*this < b); } bool operator == (const BigNum &b) const { //等于号运算符重载函数,用于比较两个 BigNum 类型的对象是否相等 return !(*this < b) && !(b < *this); } bool operator != (const BigNum &b) const { //不等于号运算符重载函数,用于比较两个 BigNum 类型的对象是否不相等 return *this < b || b < *this; }这段函数的设计思路是什么?
05-24

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值