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次方,所以指针的访存范围会随着系统的位数而改变。