复杂指针的声明和关于指针的几个小例子

参考自:《C和C++程序员面试秘籍》

a: 一个有10个指针的数组,该指针是指向一个整型数的

int *a[10]

b:一个指向有10个整型数数组的指针

int (*a)[10]

c:一个指向函数的指针,该函数有一个整形参数并返回一个整型数

int (*fun)(int)

d:一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数

int (*fun[10])(int)

如何解读复杂指针?

int (*func)(int *p);

解析上面这行代码:
首先找到未定义的标识符,就是func,它的外面有一对圆括号,而且左边是一个*号,这说明fun是一个指针;然后跳出这个圆括号,先看右边,也是一个圆括号,这说明(int fun)是一个函数,而func是一个指向这类函数的指针,就是一个函数指针,这类函数具有int类型的形参,返回值类型时int。

int (*func)(int *p, int (*f)(int*));

解析上面这行代码:
func被一对括号包含,而且左边是号,说明func是一个指针。跳出括号,右边也有个括号,那么func是一个指向函数的指针。这个函数具有int 和int ()(int)这样的形参,返回值为int类型。
至于第二个形参int (f)(int),与前面的解释相同,f也是一个函数指针,指向的函数具有int*类型的形参,返回值是int。

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

解析上面这行代码:
func的右边是一个[]运算符,说明func是一个具有5个元素的数组;func的左边有一个*,说明func的元素是指针。
注意:这里的不是修饰func的,而是修饰func[5]的原因是[]运算符的优先级比高。
跳出这个括号,看右边,也是一对括号,说明func数组的元素是函数类型的指针,它所指向的函数具有int*类型的形参,返回值是int类型。

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

解析上面这行代码:
func是一个指向数组的指针,这个数组的元素是指针。这些指针指向的函数,具有int*类型的形参,返回值为int类型。

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

解析上面这行代码:
func是一个函数指针,这类函数具有int*类型的形参,返回值是指向数组的指针;所指向的数组是具有5个int元素的数组。

看了好多次,但是总会忘记,可能还是不理解的缘故。

指针赋值操作:

#include <stdio.h>
#include <stdlib.h>

int main()
{
        char a[] = "hello world";
        char *ptr = a;

        printf("%c \n",*(ptr+4));
        printf("%c \n",ptr[4]);
        printf("%c \n",a[4]);
        printf("%c \n",*(a+4));

        *(ptr+4) += 1;
        printf("%s\n",a);



        return 0;
}

输出:

o 
o 
o 
o 
hellp world

指针加减操作:对指针进行+1的操作,得到的是下一个元素的地址,而不是原有地址值直接加1.所以,一个类型时t的指针的移动,以sizeof(t)为移动单元。

int a[5] = {1,2,3,4,5};
int *ptr = (int *)(&a + 1);/*注意:这里的ptr究竟指向哪里?*/
/*a是数组首地址,也就是a[0]的地址;&a是对象(数组)的首地址,a+1是数组下一元素的地址,即a[1];而&a+1是下一个对象的地址,即a[5]。*/

 printf("%d\n",*(a+1));/*输出2*/
 printf("%d\n",*ptr);/*输出一个随机数*/
 printf("%d\n",*(ptr-1));/*输出5*/

指针的比较:下面这个程序考察的是内存中各个数据的存放方式。

 char str1[]       = "abc";
 char str2[]       = "abc";
 const char str3[] = "abc";
 const char str4[] = "abc";
 /*数组str1 str2 str3 str4都是在栈中分配的,内存中的内容都是"abc\0”,但是它们的位置是不同的。*/
 
 const char* str5  = "abc";
 const char* str6  = "abc";
 char* str7        = "abc";
 char* str8        = "abc";
/*指针str5 str6 str7 str8也是在栈中分配的,它们都指向"abc"字符串,注意:"abc"字符串存放在数据区,所以str5 str6 str7 str8其实是指向同一块数据区的内存。*/

printf("%d\n",(str1==str2));/*输出0*/
printf("%d\n",(str2==str3));/*输出0*/
printf("%d\n",(str3==str4));/*输出0*/
printf("%d\n",(str5==str6));/*输出1*/
printf("%d\n",(str6==str7));/*输出1*/
printf("%d\n",(str7==str8));/*输出1*/

指针的隐式转换:

    int ival = 1024;
    int ival2 = 2048;
    int *pi1 = &ival;
    int *pi2 = &ival2;
    int **pi3 = 0;

     ival = *pi3;/*编译出错:int*型不能转换成int型*/
     *pi2 = *pi3;/*编译出错:int*型不能转换成int型*/
     ival = pi2;/*编译出错:int*型不能转换成int型*/
     pi2 = *pi1;/*编译出错:int型不能转换成int*型*/
     pi1 = *pi3;/*运行时出错:*pi3是NULL指针,是禁止访问的,该进程将终止运行*/
     ival = *pi1;
     pi1 = ival;/*编译出错:int型不能转换成int*型*/
     pi3 = &pi2;

编译出错:

zhizhen.c: In function ‘main’:
zhizhen.c:50:14: warning: assignment makes integer from pointer without a cast [enabled by default]
         ival = *pi3;
              ^
zhizhen.c:51:7: warning: assignment makes integer from pointer without a cast [enabled by default]
  *pi2 = *pi3;
       ^
zhizhen.c:52:7: warning: assignment makes integer from pointer without a cast [enabled by default]
  ival = pi2;
       ^
zhizhen.c:53:6: warning: assignment makes pointer from integer without a cast [enabled by default]
  pi2 = *pi1;
      ^
zhizhen.c:56:6: warning: assignment makes pointer from integer without a cast [enabled by default]
  pi1 = ival;

运行时出错:

Segmentation fault (core dumped)

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页