一
、一维数组,一级指针;二维数组,二级指针
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; }