C语言勘误---指针

本文主要介绍在指针使用过程中容易出现的错误

目录

本文主要介绍在指针使用过程中容易出现的错误

1.字符指针(常量字符串赋值给指针)

2.指针数组的使用(存放指针的数组)

3.数组指针(指向数组的指针)

4.函数指针

5.函数指针数组

6.回调函数

7.传参


理解名词:

一个十六进制地址占用的是一个字节

p[0] = *(p+0)

char *p  (字符指针) -- int *p(整形指针) -- int p[10](整形数组) 

int *p [10] (指针数组:数组里边有10个元素,每个元素类型是int *)

int (*p)[10] (数组指针:*p是一个指针,指向一个数组,数组里边有10个元素,每个元素类型是int) 

int *p()   (指针函数)

int (*p)(int,int)  (函数指针)

int(*p[10])(int)(函数指针数组)

int (*p[10])[5] (一个数组,数组里边有10个元素,每个元素类型是数组指针,该数组指针指向5个元素,每个元素类型是int   )对于这种类型数据,先找到主语---数------拿出来-----剩下的int (*p)[5]-----数组指针

void *:可以接受任意类型的地址,不能解引用操作,不能进行++--等操作,如果要解引用操作,需要进行强制转换(比如*(int *)p)

1.字符指针(常量字符串赋值给指针)

(1)先看下列代码

#include<stdio.h>
int main(int argv,char *argc[])
{
	
	char *p = "abcdef";
	printf("%s\n",p);
	printf("%c\n",*p);

	*p = 'A';

    return 0;
}

输出结果

上述结果表明:指针存放的是字符串元素的首地址,而并非整个字符串(指针在32位/64系统中占4/8字节)

                        为什么会出现段错误呢,那是因为“abcdef”是一个常量字符串,是不可以被更改的

(2)再看下列代码

#include<stdio.h>
int main(int argv,char *argc[])
{
	char arr1[] = "abcdef";
	char arr2[] = "abcdef";
	char *p = "abcdef";
	char *n = "abcdef";

	if(arr1 == arr2){
		printf("arr1 == arr2\n");
	}
	else{
		printf("arr1 != arr2\n");
	}
	if(p == n){
		printf("p == n\n");
	}
	else{
		printf("p != n\n");
	}

    return 0;
}

输出结果

上述结果表明:指针赋值的字符串是常量字符串,在我们操作系统中为了节约内存,常量字符串只会保存一次。即指针p和指针n都指向a(字符串元素首地址)

                         而字符串数组可以多个开辟。

2.指针数组的使用(存放指针的数组)

int * arr【10】(根据优先级先arr先结合【10】,arr[10]存放int*)

#include<stdio.h>
int main(int argv,char *argc[])
{
	char arr1[] = {1,2,3,4};
	char arr2[] = {5,6,7,8};
	char arr3[] = {9,10,11,12};

	char *p[3] = {arr1,arr2,arr3};

	for(int i = 0;i < 3;i ++)
	{
		for(int j = 0;j < 4;j ++)
		{
			printf("%d",*(p[i]+j));
		}
		printf("\n");
	}
//	printf("%d\n",*(p[0]+1));

    return 0;
}

3.数组指针(指向数组的指针)

int (* arr)【10】(根据优先级先arr先结合*,指针*arr指向int 【10】)

假设一位数组int arr[10]

那么int *p = arr;         则arr[i] == p[i] == *(p+i) == *(arr+i) 

假设二维数组int arr[3][5]

那么int arr[3][5] = int (*p)[5]   则 ---->   arr[i][j] == p[i][j] == *(*(p+i) + j)  == *(p[i] + j)

4.函数指针

对比数组指针理解函数指针

int (*p)(int a,int b)

int add(int a,int b)
{
    return a+b;
}
int main()
{
    int a = 10;
    int b =20;
    
                                //数组指针int (*p)[10]
    int (*p)(int,int) = add;    //函数指针 指针p指向add,*p相当于调用
    printf("sum = %d\n",(*p)(2,3));
    printf("sum = %d\n",p(2,3));  //*没有实际意义
}

1)看下列代码段(*(void (*)())0)();相当于一次函数调用

(*(xxx)xxx)()表示调用

2)

signal是一个函数声明

该函数的返回类型是函数指针,该函数指针指向参数int,返回类型是void

该函数的第一个参数是,第二个参数的类型是函数指针,该函数指针指向int,返回类型是void

注意:用typedef重新命名函数指针

void (*signal(int, void(*)(int)))(int);

typedef void (*function)(int);
function signal(int,function);

5.函数指针数组

指针数组是用来存放指针,函数指针数组是用来存放函数指针,两个是有区别的

函数指针数组表示:void(*p[4])(int,int)  /  void(*p[4])()........

初始化 

//void(*p[4])(int,int);
void SUM(int,int)
{}
void SUB(int,int)
{}
void MUL(int,int)
{}
void DIV(int,int)
{}

int main(int,int)
{
    void(*p[4])(int,int) = {SUM,SUB,MUL,DIV};
}

使用示例:

                    1.char *(*pf)(char *,const char *)

                    2.char *(*pf[4])(char *,const char *)

用于计算器加减乘除这种相同参数,不同函数的场景(转移表

6.回调函数

  回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。(并不是直接调用本函数--间接

 
#include <stdio.h>
//回调函数
int ADD(int (*callback)(int,int), int a, int b){
	return (*callback)(a,b);//此处回调add函数...
}
//普通函数
int add(int a, int b){
	return a + b;
}
 
int main(void){
	printf("%d\n",add(1,2));
	printf("%d\n",ADD(add,1,2));
	return 0;
}

7.传参

二维数组传参-----二维数组的数组名 如果表示首元素则是数组的第一行

void test(int arr[5][10])
{}
void test1(int arr[][10])
{}
void test3(int arr[5][])  //error
{}
void test4(int arr[][])  //error
{}
void test5(int **arr)  //error  二级指针用来存放一级指针的变量的地址,arr对于二维数组来说就是第一行数组的地址,数组的地址不能存放在二级指针里边
{}
void test6(int (*arr)[10])//指向数组的指针,可以用来存贮一位数组
{}
int main()
{
    int arr[5][10] = {0};
    test(arr);
    test1(arr);
    test6(arr);
}

二级指针传参

void test(char **p)
{
    printf("%c\n",**p);
}

int main()
{
    char a = 'b';
    char *p = &a;
    char **pp = &p;
    char *buff[32] = {p};
    test(pp); //用二级指针传参
    test(&p); //用一级指针的地址传参
    test(buff);//用指针数组传参
}

函数指针传参(指向函数的指针,用来存放函数的地址)

int add(int a,int b)
{
    return a+b;
}
int main()
{
    int a = 10;
    int b =20;
    
                                //数组指针int (*p)[10]
    int (*p)(int,int) = add;    //函数指针 指针p指向add,*p相当于调用
    printf("sum = %d\n",(*p)(2,3));
    printf("sum = %d\n",(p)(2,3)); //*其实没有实际意义
}

猜你喜欢

转载自blog.csdn.net/qq_45604814/article/details/112844269