文章目录:
1.复杂指针讲解以及练习。
2.typedef与define作用以及区别。
3.用typedef对复杂指针重命名。
一。复杂指针讲解以及练习。
我觉得有一遍文章讲解讲解复杂指针非常好,直接引用过来。
下面第一段就是分析复杂指针的方法:
右左法则:首先从最里面的圆括号(未定义的标识符)看起,然后往右看,再往左看。每当遇到圆括号时,就应该掉转阅读方向。一旦解析完圆括号里面所有的东西,就跳出圆括号。重复这个过程直到整个声明解析完毕。
下面是例题讲解:(首先最基本的概念要理解,从简单开始)
int p;
这是一个普通的整型变量
int *p;
首先从p处开始, 先与*结合. 所以p是一个指针, 然后再与int结合. 说明p指向的为int型. 所以p是一个指向整型的指针变量
int p[n];
首先从p处开始, 先与[]结合, 所以p是一个数组, 然后再与int结合, 说明数组的元素为int型, 所以p是由n个int型数据的数组.
int *p[n];
从p处开始, 先与[]结合([]的优先级比*高), 所以p是一个数组, 然后再与*结合,说明数组的元素是指针类型, 再与int结合,说明指针的类型为整型,所以p是由n个int型指针的数组.
int (*p)[n]
从p处开始, 括号里面先执行, 先与*号结合, 说明p是一个指针. 然后再与[]结合,说明p指向的是一个数组. 再与int结合. 说明数组元素的值为int型, 所以p是一个指向由n个元素的数组的指针.
int **p
首先p与*结合, 说明p是一个指针, 然后再与*结合, 说明指针所指向的元素是指针. 再与int结合, 说明指针为int开进, 所以p是指向int型指针的指针.
int p(int)
首先p与()结合, 说明p是一个函数, 然后分析括号里面, 说明该函数接收一个int型的参数. 再与int结合, 说明该函数的返回值为int型
int (*p)(int)
首先p与*结合, 说明p是一个指针(括起p的括号起改变优先级), 然后与()结合说明p指向的是一个函数, 然后再与int结合说明函数的返回类型是整型.所以p是一个指向有一个整型参数, 返回值为整型的函数的指针.
int *(*p(int))[n]
从p开始先与()结合, 说明p是一个函数, 函数的参数为int型, 再与*结合, 说明函数的返回值为指针. 再与[]结合说明指针指向是一个数组,再与*结合说明数组的元素为指针, 再与int 结合说明数组的元素指针为int 型指针.所以p
p是带一个int型参数返回值为指向n个int型指针元素的数组的函数
int (*func)(int *p);
首先找到那个未定义的标识符,就是func,它的外面有一对圆括号,而且左边是一个*号,这说明func是一个指针,然后跳出这个圆括号,先看右边,也是一个圆括号,这说明(*func)是一个函数,而func是一个指向这类函数的指针,就是一个函数指针,这类函数具有int*类型的形参,返回值类型是int。
int (*func)(int *p, int (*f)(int*));
func被一对括号包含,且左边有一个*号,说明func是一个指针,跳出括号,右边也有个括号,那么func是一个指向函数的指针,这类函数具有int *和int (*)(int*)这样的形参,返回值为int类型。再来看一看func的形参int (*f)(int*),类似前面的解释,f也是一个函数指针,指向的函数具有int*类型的形参,返回值为int。
int (*func[5])(int *p);
func右边是一个[]运算符,说明func是一个具有5个元素的数组,func的左边有一个*,说明func的元素是指针,要注意这里的*不是修饰func的,而是修饰func[5]的,原因是[]运算符优先级比*高,func先跟[]结合,因此*修饰的是func[5]。跳出这个括号,看右边,也是一对圆括号,说明func数组的元素是函数类型的指针,它所指向的函数具有int*类型的形参,返回值类型为int。
int (*(*func)[5])(int *p);
func被一个圆括号包含,左边又有一个*,那么func是一个指针,跳出括号,右边是一个[]运算符号,说明func是一个指向数组的指针,现在往左看,左边有一个*号,说明这个数组的元素是指针,再跳出括号,右边又有一个括号,说明这个数组的元素是指向函数的指针。总结一下,就是:func是一个指向数组的指针,这个数组的元素是函数指针,这些指针指向具有int*形参,返回值为int类型的函数。
int (*(*func)(int *p))[5];
func是一个函数指针,这类函数具有int*类型的形参,返回值是指向数组的指针,所指向的数组的元素是具有5个int元素的数组。
原文:https://blog.csdn.net/xuxhong/article/details/8182533
2.typedef与define作用以及区别。
define(宏定义)形式:#define 标识符 字符串 #表示这是一个预处理命令,预处理不检查程序的对错。后面不用加 ‘;’号
作用:1.宏定义有两种形式:带参与不带参。宏定义计算时要注意优先级问题,它只是简单的替换。
2.作为条件编译开关避免重复包含。 #ifndef *** #defnie *** #endif *号代替文件名,两个是相同的。
3.用于条件编译。#ifdef dosomething #endif 或者 #ifden do (#else do ) #endif
4.定义宏后取消: #undef *** * 表示宏名
typedef用法:
1.定义一种类型别名。
2.定义与平台无关的类型,大大减少改动代码劳动力。
比如定义一个real浮点类型,在一个平台上它可以表示为最高精度类型为:typedef long double real;
在系统移植后,新平台不支持long double 类型,哪我们只需要将typdef long double real; 中的类型该为支持且合适的。这样就大大减少了工作量。
3.为复杂的声明定义一个新的简单的名字。
define与typedef区别: define只是简单的一个替换,它不会做其他事情,而且在替换中经常有优先级的的问题。在预处理时,系统遇到define的宏就要替换。而typedef只替换一次就就行。
一个例子区别typedef,define:
typedef char * pStr;
char String[4] = "abc";
const char *p1=String;
const pStr p2 = String;
p1++;
p2++;
问p1++或p2++ 那个会出错?
答案是p2++会出错。因为typedef 的作用是定义一种类型别名。此题中,替换掉pStr后 const char * p2 =String;看似是对指向内容的封锁。然而不是。例如 const int a 一样,a在这里是一个常量。而typedef为char *起别名后为pStr,哪也就是const pStr p2中p2也是一个常量。所以此处p2是一个常量指针,而非指向物为常量。这块与一般的常量指针定义不一样,一般的是char* const p2;
然后也可以用define pStr char *试试,会发现p2是正确的。
3.用typedef对复杂指针重命名。
例子: int *(*A[10]) (int, char* );
直接一步替换:
typedef int *(*A[10]) (int, char* ); //重命名
int * test(int a,char *)
{
int *p =new int(a);
return p;
}
int main()
{
A a; //定义了一个复杂指针类型
a[0] = test;
int *p = a[0](10,0);
cout<<*p<<endl;
return 0;
}
可以从上面代码看到A 代替了一个类型,这个类型就是 存着函数参数为int,char*,返回值为int*类型的函数指针,数组大小为10.
所以A的本质是一个数组,只是里面存的是函数指针。所以就可以使用这样的代码a[0] =test;
分步替换:
例子:void (*b[10]) (void (*)());
先替换右边括号里面的参数,将void (*)()的类型起个别名pParam:
typedef void (*pParam) ();
再替换左边的变量b,为b的类型起个别名B:
typedef void (*B) (pParam);
原声明的简化版: B b[10];