数组指针、指针数组、指针函数

       如何区分数组指针与指针数组,数组指针是指针。指针数组是数组。可以通过对他们的优先级进行比较。可以根据语句中的优先级来判断,()>[]>*,用下面的例子来说明区分这两种

        char * a[3]:这个优先级最高的a[3]所以是一个数组变量,然后就是数组的类型了,char *说明该类型是char类型指针,所以为指针数组。

        char (*a)[3]:这个中()的优先级高下,所以是一个指针变量,然后再看类型为一个数组类型的,所以叫数组指针。

        数组指针:数组指针是一个指向数组的指针。数组指针用于指向一个数组的起始地址,通常用于函数参数,以传递数组。

int arr[3] = {1, 2, 3}; // 一个包含3个整数的数组
int (*p)[3]; // 一个指向包含3个整数的数组的指针

p = &arr;

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

        下面是数组指针的运算,理解下面的代码,可以把二维数组看为一个一维数组,一维数组里的元素又是一个一维数组。要注意理解p+1与*(p+1),虽然地址是一样的,但是意义是不一样的。p+1是二维数组a[1]的首地址及a[1][0],进行++、--等运算时时移动(int)4*4(数组个数)个字节,而*(p+1)是,p+1到a[1]的地址下,对它进行解引用就为a[1][0]的地址,进行++、--运算时就移动4个字节,如*(p+1)+1即为a[1][1]的地址。 

          指针数组:指针数组是一个数组,其中每个元素都是指针。指针数组可以用来存储多个指针,例如指向字符串的指针。

char *arr[3]; // 一个包含3个指针的数组,每个指针指向一个字符(字符串)
arr[0] = "Hello";
arr[1] = "World";
arr[2] = "C Programming";

for (int i = 0; i < 3; i++) {
    printf("%s\n", arr[i]);
}

        指针指针:指针指针其实就是指针里的数据还是指针(地址),为什么要声明char **p呢、因为ch存的是地址、类型为char *,要个指针指向它的首地址,就应该是char *(ch的数据类型) *p(声明一个指针变量),所以就为char **p,对p解引用就是为ch每个字符串的首地址。

#include <stdio.h>
void sort2Str(char **p,int row){
	for(int i=1;i<row;i++){
		char *q = *(p+i);
		int j = i;
		while(j>0 && strcmp(*(p+j),*(p+j-1))<0){
			*(p+j) = *(p+j-1);
			j--;
		}
		*(p+j) = q;
	}

}
  int main(int argc, const char *argv[])
 {
      char* ch[] = {"hello","word"};//存放字符串常量中的首地址  
      char *ch1[]={"hello","word","adress","slop"};                                  
      char **p = ch;//指针的指针,二级指针
      sort2Str(ch1,4);
      for(int i=0;i<2;i++)
         puts(*(p+i));
       return 0;
   }

        指针函数:指针函数是指返回值为指针的函数。这意味着这个函数在被调用时,返回的是一个指针。下图中、getMax函数返回一个指向整数的指针。函数的返回值是指向a或b的指针,这取决于哪一个值更大。

int* getMax(int *a, int *b) {
    if (*a > *b)
        return a;
    else
        return b;
}
int main() {
    int x = 10, y = 20;
    int *max = getMax(&x, &y);
    printf("Max value: %d\n", *max);
    return 0;
}

        函数指针(回调函数):函数指针是一个指向函数的指针。这意味着你可以通过函数指针来调用函数,就像调用普通函数一样。

        函数指针的声明是:int (*p) (int a,int b)或int (*p) (int,int),声明一个函数指针,返回值为int、参数为2个int类型的数据。

        函数调用:int ret = p(1,2)或(*p)(1,2)。其中(*p)中的*可以很多个(********p),但是编译器也不会去识别它,它只要函数的地址。

#include <stdio.h>
void sortArray(int *a,int n,int (*f)(int)){//接收f形参函数的地址、参数
	for(int i=0;i<n;i++){
		for(int j=i+1;j<n;j++){
			if(f(a[i]) > f(a[j]) ){
				int temp = a[i];
				a[i] = a[j];
				a[j] = temp;
			}
		}
	}
}
int fun1(int n){
	return n*n;
}
int fun2(int n){
	return n*n*n;
}
int main(int argc, const char *argv[])
{
	int a[8]={2,-1,4,3,-7,6,5,8};
	sortArray(a,8,fun1);//函数名就是地址
	for(int i=0;i<8;i++)
		printf("%d ",a[i]);
	putchar('\n');
	return 0;
}

二、void*类型的指针

        在C语言中,void *是一种通用指针类型,可以指向任何类型的数据。与其他指针类型之间的转换关系比较特殊,因为void *在指针类型之间的转换中有一些灵活性。下面详细介绍void *与其他指针类型之间的转换关系,sizeof(void)=1。

1. void *到其他指针类型的转换

 void *可以被隐式转换为任何其他类型的指针,而不需要显式的类型转换。例如:

int a = 10;
void *ptr = &a;  // 隐式转换为void *

int *intPtr = ptr;  // 需要显式转换为int *

        虽然一些编译器允许这种隐式转换(从 void * 到其他类型的指针),但为了确保代码的清晰性和安全性,通常建议显式进行类型转换,如下所示:

int *intPtr = (int *)ptr;  // 显式转换为int *

2. 其他指针类型到void *的转换

        其他类型的指针可以隐式地转换为void *,而不需要显式的类型转换。这种转换是安全的,且符合C语言标准。

int a = 10;
int *intPtr = &a;

void *ptr = intPtr;  // 隐式转换为void *

3. 注意事项

  • 类型安全void *的灵活性带来了一定的类型安全风险。转换不当可能导致未定义行为或程序崩溃。因此,在将void *转换回其他类型的指针时,确保类型是正确的。

  • 指针运算:不能对void *直接进行指针运算(如ptr++),因为void *不知道它指向的数据类型,也不知道步长(步长取决于指针指向的数据类型大小)。要进行指针运算,必须先将void *转换为适当的类型指针

void *ptr = malloc(10 * sizeof(int));  // 分配内存给int数组
int *intPtr = (int *)ptr;  // 转换为int *

intPtr++;  // 现在可以进行指针运算

  • 11
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值