C语言指针详解(下)

一维数组,一级指针;二维数组,二级指针

1)指针和数组在使用上有类似性(比如a[5]可以访问数组中第六个元素,p+5同样也可以访问),但指针和数组是没有关系的,这是两种不同的类型。

2)指针可以做左值也可以做右值(可表示空间,可表示内容),数组只能做右值(可以将数组赋值给别的变量,但不能将变量直接赋值给数组)。
3)指针做右值表示它的内容,数组名做右值表示的是数组首元素的首地址。
4)只有sizeof(数组名),&数组名,这两种情况数组名代表整个数组,其他情况都代表首元素的地址。
二、数组指针、指针数组

指针数组是数组,是一个存放指针的数组,int *a[10]; --> a是一个数组,是一个存放指针的数组,是一个存放的指向整型的指针的数组
数组指针是指针,是一个指向数组的指针,int (*p)[10]; --> p是一个指针,是一个指向数组的指针,是一个指向含10个整型元素的数组的指针
三、指针和数组的定义和声明

 定义分配内存,而声明没有。

1.定义为数组,声明为指针

文件1中定义如下:

zhar arr[100];

文件二声明如下:

extern char * a;

这是错误的,当你声明为extern *a时,编译器理所当然地认为a是一个指针变量,在32位系统下,占4字节。这4字节里保存了一个地址,这个地址上存储的是字符型数据。大多数编译器是按文件分别编译的,编译器只按照本文件声明的类型来处理。所以,虽然a实际大小为100字节,但是在文件2中,编译器认为a只占4字节。

2.定义为指针,声明为数组
文件一:
char *p="abcdefg";

文件2:

extern char p[];

文件1中,编译器分配4字节空间,并命名为p;同时p里保存了字符串常量“abcdefg”的首字符的首地址,这个字符串常量本身保存在内存的静态区,其内容不可更改。在文件2中,编译器认为p是一个大小为4字节的数组,数组内保存的是cha类型的数据。

四、数组指针参数
1)一维数组传参
无法向函数传递一个数组。
在C语言中,当一维数组作为函数参数的时候,编译器总是把他们解析成一个指向其首元素首地址的指针。
以下是正确的传参方式:
void test(int arr[])  
{  
}  
void test(int arr[10])  
{  
}  
void test(int *arr)  
{  
}  
  
void test2(int *arr[20])  
{  
}  
void test2(int **arr)  
{  
}  
  
int main()  
{  
     int arr[10];  
     int *arr2[20];  
     test(arr);      
     test2(arr2);  
}  

2)二维数组传参
void fun(char a[3][4]);

可以把 a[3][4]理解为一个一维数组a[3],其每个元素都是一个含有4个char类型数据的数组。根据上面一维数组的规则,我们可以把这个声明改写为:void fun(char (*p)[4]);这里的括号绝对不能省略,这样才能保证编译器把p解析为一个指向包含4个char类型数据元素,即一维数组a[3]。同样, void fun(char a[ ][4]);也正确。但是第二维不可省略。
如果把上面提到的声明:void fun(char (*p)[4]);中的括号去掉之后,void fun(char *p [4]);可以改写成:void fun(char **p [4]);

3)一级指针传参

void test1(int *p) --> 此时p可以接收:整型数组、整型元素的地址

void test2(char *p) --> 此时p可以接收:字符数组、字符的地址、字符串

4)二级指针传参

void test(char **p) --> 此时p可以接收:二级指针、指针数组、一级指针的地址

数组指针、指针数组、函数指针、函数指针数组、指向函数指针的数组的指针在这里点击调函数打开链接

五、回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个函数被用来调用其所指向的函数时,我们说这是回调函数。

使用回调函数,模拟实现qsort

#include<stdio.h>
int int_cmp(const void * p1, const void * p2)
{
	return (*(int *)p1 > *(int *)p2);
}
void _swap(const void * p1, const void * p2, int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *((char *)p1 + i);
		*((char *)p1 + i) = *((char *)p2 + i);
		*((char *)p2 + i) = tmp;
	}
}
void my_qsort(void *base, int sz, int width, int(*cmp)(void *, void *))
{
	int i = 0;
	int j = 0;
	for (i = 0; i < sz - 1; i++)
	{
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (cmp((char *)base + j*width, (char *)base + (j + 1)*width)>0)
			{
				_swap((char *)base + j*width, (char *)base + (j + 1)*width, width);
			}
		}
	}
}
int main()
{
	int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
	int i = 0;
	my_qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp);
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		printf("%d", arr[i]);
	}
	printf("\n");
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41268108/article/details/80511990