C语言作答

C语言作答,第1张

21C //数组越界时,编译器不会报错

22C //int(ptr)();中ptr先与结合所以是指针,有两个是指针的指针后面是括号表函数,因此是指向函数指针的指针

21C //数组越界时,编译器不会报错

22C //int(ptr)();中ptr先与结合所以是指针,有两个是指针的指针后面是括号表函数,因此是指向函数指针的指针

23D //单项循环链表中尾结点的next指针指向链表头,这里p->next指向的是尾结点,那么p直接后继是尾结点

24C //b++是先输出然后自己增1,增1后与1的差是2

25D //编译出错,函数定义了void型就不能有返回值

26B //第一个循环,a为1,执行+5变为6;第二循环,a-3变为3,第三循环,a+5变为8,第四循环判断a为8结束。

27A //形参和实参存储空间各自独立,形参是调用时分配的空间,在栈里

28A //c里就这样

29D //函数是面向过程的

30A //元的作用在于提高程序的运行效率,但是,它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。

ppNext是一个指针,这个指针指向另外一个指针,这个指针指向一个类

即ppNext(指针) ------->(指向) 另一个指针--------->类IOBuffer

指针的指针

其实是 (p)

意思是该指针指向 int p

数组

以指针为元素的数组

是函数指针

这个函数指针指向的函数的返回类型是一个函数指针构成的数组

参考:

复杂指针解析

因为C语言所有复杂的指针声明,都是由各种声明嵌套构成的。如何解读复杂指针声明呢?右左法则是一个既著名又常用的方法。不过,右左法则其实并不是C标准里面的内容,它是从C标准的声明规定中归纳出来的方法。C标准的声明规则,是用来解决如何创建声明的,而右左法则是用来解决如何辩识一个声明的,两者可以说是相反的。右左法则的英文原文是这样说的:

The right-left rule: Start reading the declaration from the innermost parentheses, go right, and then go left When you

encounter parentheses, the direction should be reversed Once everything in the parentheses has been

parsed, jump out of it Continue till the whole declaration has been parsed

这段英文的翻译如下:

右左法则:首先从最里面的圆括号看起,然后往右看,再往左看。每当遇到圆括号时,就应该掉转阅读方向。一旦解析完圆括号里面所有的东西,就跳出圆括号。重复这个过程直到整个声明解析完毕。

笔者要对这个法则进行一个小小的修正,应该是从未定义的标识符开始阅读,而不是从括号读起,之所以是未定义的标识符,是因为一个声明里面可能有多个标识符,但未定义的标识符只会有一个。

现在通过一些例子来讨论右左法则的应用,先从最简单的开始,逐步加深:

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元素的数组。

要注意有些复杂指针声明是非法的,例如:

int func(void) [5];

func是一个返回值为具有5个int元素的数组的函数。但C语言的函数返回值不能为数组,这是因为如果允许函数返回值为数组,那么接收这个数组的内容的东西,也必须是一个数组,但C语言的数组名是一个右值,它不能作为左值来接收另一个数组,因此函数返回值不能为数组。

int func[5](void);

func是一个具有5个元素的数组,这个数组的元素都是函数。这也是非法的,因为数组的元素除了类型必须一样外,每个元素所占用的内存空间也必须相同,显然函数是无法达到这个要求的,即使函数的类型一样,但函数所占用的空间通常是不相同的。

作为练习,下面列几个复杂指针声明给读者自己来解析。

int ((func)[5][6])[7][8];

int (((func)(int ))[5])(int );

int ((func[7][8][9])(int))[5];

实际当中,需要声明一个复杂指针时,如果把整个声明写成上面所示的形式,对程序可读性是一大损害。应该用typedef来对声明逐层分解,增强可读性,例如对于声明:

int ((func)(int p))[5];

可以这样分解:

typedef int (PARA)[5];

typedef PARA (func)(int );

这样就容易看得多了。

答案,同时给出用typedef的分解方法:

int ((func)[5][6])[7][8];

func是一个指向数组的指针,这类数组的元素是一个具有5X6个int元素的二维数组,而这个二维数组的元素又是一个二维数组。

typedef int (PARA)[7][8];

typedef PARA (func)[5][6];

int (((func)(int ))[5])(int );

func是一个函数指针,这类函数的返回值是一个指向数组的指针,所指向数组的元素也是函数指针,指向的函数具有int形参,返回值为int。

typedef int (PARA1)(int);

typedef PARA1 (PARA2)[5];

typedef PARA2 (func)(int);

int ((func[7][8][9])(int))[5];

func是一个数组,这个数组的元素是函数指针,这类函数具有int的形参,返回值是指向数组的指针,所指向的数组的元素是具有5个int元素的数组。

typedef int (PARA1)[5];

typedef PARA1 (PARA2)(int);

typedef PARA2 func[7][8][9];

A正确

B,C定义的不是函数指针;D类型错(应为char ),赋值也错(函数fun这个名字指的就是这个函数的地址)。

A是定义的void类型的函数指针,赋值时是把函数首地址(用fun表示)赋给pf这个函数指针。

定义不同,写法不同。

指针函数本质是一个函数,其返回值为指针。函数指针本质是一个指针,其指向一个函数。指针函数:intfun(intx,inty);函数指针:int(fun)(intx,inty);可以简单粗暴的理解为,指针函数的是属于数据类型的,而函数指针的星号是属于函数名的。再简单一点,可以这样辨别两者:函数名带括号的就是函数指针,否则就是指针函数。

函数的定义:给定一个数集A,对A施加对应法则f,记作f(A),得到另一数集B,也就是B=f(A)。那么这个关系式就叫函数关系式,简称函数。函数概念含有三个要素:定义域A、值域C和对应法则f。其中核心是对应法则f,它是函数关系的本质特征。函数,最早由中国清朝数学家李善兰翻译,出于其著作《代数学》。之所以这么翻译,他给出的原因是“凡此变数中函彼变数者,则此为彼之函数”,也即函数指一个量随着另一个量的变化而变化,或者说一个量中包含另一个量。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/12183565.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-21
下一篇2023-05-21

发表评论

登录后才能评论

评论列表(0条)

    保存