typedef用法总结

typedef与#define之间的差异

1.typedef创建的符号名只限于类型,不限于值
2.typedef由编译器解释,不是预处理器(编译的阶段不一样)

用法

(1) typedef基本数据类型取“别名”

//对变量的类型进行重新定义类型名称
typedef unsigned int size;
typedef unsigned int16 u16;
typedef unsigned int8 u8; //u8 xiaoming 等于 unsigned int8 xiaoming

(2)typedef为自定义数据类型取“别名”

//自定义的数据类型包括:结构体struct name{};共用体unit name{};枚举enum{};
struct students{
	char sex;
	char name[120]; //学生名称
	int ages;
};
struct students std;
//或
struct students{
	char sex;
	char name[120];
	int ages;
} std;
std.name[120] = "xiaoming"

使用typedef 定义

struct students{
	char sex;
	char name[120];
	int ages;
};
typedef struct students std; //别名
std.name[20]="wujunwu"

(3) 数组取"别名"

typedef char arr_name[20];
arr_name ane;
ane[20]="xiaoming"

(4) 指针取"别名"

普通指针

int a=2;
int* pointer;
pointer =&a;
//等于
int a=2;
typedef int* pointer;
pointer p;
p=&a;
//如果a的数据类型是char ,即char a =2;那么,
char a=2;
typedef int* pointer;
pointer p;
p=&(pointer)a; //理解:(pointer)a将a转为(int *)的指针,再取(int *)a指针的地址,再将其赋值给一个pointer类型指针,指针之间的赋值,此时p指针指向(int *)a指针地址

函数指针

typedef unsigned int bool;
typedef bool(*pCopySDMMC2Mem)(int, unsigned int, unsigned short, unsigned int*, bool);
typedef void (*pBL2Type)(void);
pCopySDMMC2Mem p1=(pCopySDMMC2Mem)0xD0037F98;
pBL2Type p2 = (pBL2Type)0x23E00000;

执行的步骤:
第一步:给指针取“别名”

pCopySDMMC2Mem p1;
pBL2Type p2;

第二步:强制类型转换

(pCopySDMMC2Mem)0xD0037F98;
(pBL2Type)0x23E00000;

第三步:给指针赋值

p1=(pCopySDMMC2Mem)0xD0037F98;
p2 = (pBL2Type)0x23E00000;

说明:使用typedef时,typedef并没有创建任何新类型,它只是为某个已经存在的类型提供一个“别名”

typedef中的错误用法
//错误
typedef char* PCHAR;
int strcmp(const PCHAR,const PCHAR); //const PCHAR” 不相当于 “const char*,原因很简单,typedef 是用来定义一种类型的新别名的,它不同于宏,不是简单的字符串替换。因此,“const PCHAR”中的 const 给予了整个指针本身常量性,也就是形成了常量指针“char* const(一个指向char的常量指针)”。即它实际上相当于“char* const”,而不是“const char*(指向常量 char 的指针)”
typedef const char* PCHAR;
int strcmp(PCHAR, PCHAR); //const PCHAR 相当于 const char* ,无论什么时候,只要为指针声明 typedef,那么就应该在最终的 typedef 名称中加一个 const,以使得该指针本身是常量

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

//错误示范
typedef static int INT_STATIC; //不可行的原因是不能声明多个存储类关键字,由于 typedef 已经占据了存储类关键字的位置,因此,在 typedef 声明中就不能够再使用 static 或任何其他存储类关键字了。当然,编译器也会报错,如在 VC++2010 中的报错信息为“无法指定多个存储类”

上述内容参考了:typedef用法详解

重点解析(指针概念)

引用的概念

首先引用仅仅适用于C++,C无此特性
C语言使用指针

#include<stdio.h>
int change(int *i){
	(*i) = 100; //数据的赋值
}
int main(){
	int a = 60;
	printf("%d\n",a);
	change(&a);
	printf("%d\n",a);
	return 0;
}
gcc xxx.c -o xxx
运行的结果:
60
100

C++使用引用

#include<stdio.h>
int change(int &i){
	i = 100;
}
int main(){
	int a = 60;
	printf("%d\n",a);
	change(a);
	printf("%d\n",a);
	return 0;
}
g++ xxx.c -o xxx
运行结果
60
100

C语言创建链表节点:

#include<stdio.h>
#include<stdlib.h>
struct tree
{
	int num;
	struct tree *l;
	struct tree *r;
};
int createTreeNode(struct tree **p) //此时是指针的地址,注意与指针指向的地址相区分 struct tree *(*p)理解
{
	(*p) = (struct tree*)malloc(sizeof(struct tree));//p指针指向的地址
	(*p)->l=NULL;
	(*p)->r=NULL;
	return 0;
}
int main()
{
    struct tree *head=NULL; //head为指向链表第一个元素”**指针地址**“的指针
    createTreeNode(&head); //此时是指针的地址,注意与指针指向的地址相区分
    if (head == NULL) 
        printf("is NULL\n");
    else
        printf("is not NULL\n");   
	return 0;
}

C++创建链表的节点:

#include<stdio.h>
#include<stdlib.h>
struct tree
{
	int num;
	struct tree *l;
	struct tree *r;
};
int createTreeNode(struct tree * &p) //&p为引用,可以理解为struct tree *(&p)
{
	p = (struct tree*)malloc(sizeof(struct tree));//p为引用
	p->l=NULL;
	p->r=NULL;
	return 0;
}
int main(){
    struct tree *head=NULL; //head为指向链表第一个元素“**指针地址**”的指针
    createTreeNode(head);
    if (head == NULL) 
        printf("is NULL\n");
    else
        printf("is not NULL\n");    
	return 0;
}
指针地址与指针指向的地址
#include <iostream>
using namespace std;
int main()
{	
	int a = 4;
	int* q = &a;
	cout << &a << endl;
	cout << q << endl; //指针指向的地址
	cout << &q << endl; //指针本身的地址
}
结果:
0x7ffc1a612b7c
0x7ffc1a612b7c
0x7ffc1a612b80:q表示所指向的地址,&q表示取了指针本身的地址
#include <iostream>
using namespace std;
int main()
{	
	int *p = (int*)malloc(8);
	p[0] = 1;
	p[1] = 5;
	cout << p << endl;
	cout << p + 1 << endl;
	cout << &p << endl;
    cout << "&p[0]: "<< &p[0] <<endl;
    cout << "&p[1]: "<< &p[1] <<endl;
	cout << *p << endl;
	cout << *(p + 1) << endl;
}
结果:
0x55ad6b977eb0
0x55ad6b977eb4
0x7ffc4dec1ad0
&p[0]: 0x55ad6b977eb0
&p[1]: 0x55ad6b977eb4
1
5
注意p与p[0]/p+1与p[1]之间的区别,p[0]等于*p,p[1]等于*(p+1)
&a, (int*)a, (int)&a, (int*)&a四者之间的联系与区别

1.&a:表示取变量a的地址,结果是一个8位的16进制数;

2.(int*)a:表示将变量a转换成指针形式,结果是一个8位的16进制数(此时为指针);

3.(int)&a:表示取变量a的地址,并将该地址数值(16进制数)转换成整型数据(10进制数);

4.(int*)&a:等价于int *p = &a,结果是一个8位的16进制数。

说明:8位的16进制数,系统为32位的系统,也是指针访存的范围:4G(2^32),当系统为64位时,为12位的16进制数,指针访存范围:2的64次方,所以指针的访存范围会随着系统的位数而改变。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值