• C语言学习——指针


    C语言的格式输出,%c,%y这些代表你要输出的数据的数据类型;%d 表示输出十进
    制有符号的整数。 
    1、%u 十进制无符号整数。 
    2、%f 表示输出浮点数。
    3、%s表示输出 字符串。 
    4、%c表示输出单个字符。
    5、%p表示输出指针的值。
    6、%e表示输出指数形式的浮点数。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    前言

    • 指针是一个变量,用来存放地址,地址唯一标识一块内存空间。
    • 指针的大小是固定的4/8个字节。
    • 指针有类型,指针的类型决定了指针的±整数的步长,指针解引用的操作时候的权限。

    1.字符指针

    char ch='w';
    char *cp=&ch;   //用来存放地址
    
    • 1
    • 2
    int main(){
    const char *str="abcde";  //这里是把字符串abcde的首地址放在了指针变量里面
    	//abcde是常量字符串
    	// const 使变量里面的内容不可改
    	//*str='m';  // 不可以这样写,常量字符串不可以被修改
    	printf("%c\n",*str);
    	//a
    	printf("%s\n",*str);
    	//abcde
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2.数组指针

    数组指针是指针,

    int *p=NULL;  //p是整形指针,指向整形的指针
    char *p=NULL; //p是字符指针,指向字符的指针
    
    int arr[10]={0};
    //arr 首元素的地址;
    //&arr[0] 首元素的地址
    //&arr  数组的地址
    
    int arr[5]={1,2,3,4,5};
    int (*p)[5]=&arr;  //存储数组的地址
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    char * arr[5];
    char * (*pa)[5]=&arr;  //第二个*表示pa是一个指针,pa变量的名字,5 pa指向的数组是5个元素,第一个*表示 pa指向的数组是char*类型的数组。
    
    • 1
    • 2
    int arr[]={1,2,3,4,5,6,7,8,9,10};
    int (*p)[10]=&arr;
    int i=0;
    for(i=0;i<10;i++){
    	printf("%d ",*(*p+i));   //*p==arr  首元素地址
    }
    
    //for(i=0;i<10;i++){
    	//printf("%d ",(*p)[i]);
    //}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    //参数是指针的形式
    void print(int (*p)[4],int x,int y){
    	int i=0;
    	for(i=0;i{1,2,3,4},{2,3,4,5},{3,4,5,6}};
    	print(arr,3,4);//  arr首元素(第一行)地址,二维数组的首元素地址就是第一行地址
    
    	int arr1[]={1,2,3,4,5,6,7};
    	int *p=arr1;
    	for(i=0;i<7;i++){
    		printf("%d ",arr1[i]);
    		printf("%d ",*(p+i));
    		printf("%d ",*(arr1+i));
    		printf("%d ",p[i]);
    	}
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    3.指针数组

    指针数组使数组,用来存放指针

    int arr[4]={0};  //整形数组
    char arr[5]={0}; // 字符数组
    int *p[10];           //用来存放整形指针的数组
    
    • 1
    • 2
    • 3

    小试一手

    int main(){
    	int arr1[]={1,2,3,4,5};
    	int arr2[]={2,3,4,5,6};
    	int arr3[]={3,4,5,6,7};
    	int *parr[3]={arr1,arr2,arr3};分别把三个首元素的地址存进去
    	//打印三个数组
    	for(i=0;i<3;i++){
    		for(j=0;j<5;j++){
    			printf("%d ",*(parr[i]+j));
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    int arr[10];
    int *arr[10];
    int (*p)[10];
    int (*arr[10])[5];
    
    • 1
    • 2
    • 3
    • 4

    4.指针传参

    一级指针传参

    void print(int* p, int sz) {
    	int i = 0;
    	for (i = 0; i < sz; i++) {
    		printf("%d ", *(p + i));
    	}
    }
    
    int main() {
    	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    	int* p = arr;
    	int sz = sizeof(arr) / sizeof(arr[0]);
    	print(p, sz);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    二级指针传参

    void test(int** pp) {
    	printf("n=%d\n", * *pp);
    }
    
    int main() {
    	int n = 10;
    	int* p = &n;
    	int** pp = &p;
    	test(pp);
    	test(&p);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    5.函数指针

    指向函数的指针 存放函数地址的指针

    int Add(int x, int y) {
    	int z = 0;
    	z = x + y;
    	return z;
    }
    
    int main() {
    
    	printf("%p\n", &Add);  //&Add是上面函数Add的地址
    	printf("%p\n", Add);   //Add也是上面函数Add的地址
    
    	int (*p)(int, int) = &Add;  //指向函数的指针,这里可以参照数组指针
    	第一个int是函数返回值类型,另外两个int是参数类型
    	printf("%d\n", (*p)(3, 2));  //找到这个函数,然后调用这个函数,最后结果为5;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
     (* ( void (*) () ) 0) ()
      void (*) ()  是一个函数指针类型,
      这里是把0强制转换为void (*) () 函数指针类型,0就是一个
      函数地址。
      这里就调用0地址处的该函数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    void (*signal(int ,void(*)(int) ) ) (int)
    
     signal(int , void(*)(int))   //这是个函数,参数是int
     和函数指针。
     剩余的返回值类型是void (*     ) (int)  是一个函数指针,
     返回值是void,指向的函数的参数是int。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    6.函数指针数组

    一个数组,可以存放函数的地址——函数指针数组

    int Add(int x, int y) {
    	return x + y;
    }
    
    int Sub(int x, int y) {
    	return x - y;
    }
    
    int Mul(int x, int y) {
    	return x * y;
    }
    
    int Div(int x, int y) {
    	return x / y;
    }
    
    int main() {
    	int (*p[4])(int, int) = { Add,Sub,Mul,Div };
    	int i = 0;
    	for (i = 0; i < 4; i++) {
    		printf("%d\n", p[i](2, 3));
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    7.指向函数指针数组的指针

    是一个指针,指针指向一个数组,数组的元素都是函数指针。

    int Add(int x, int y) {
    	return x + y;
    }
    
    int main() {
    	int arr[10] = { 0 };
    	int (*p)[10] = &arr;   //数组指针
    
    	int (*pfarr[4])(int, int) = {Add};  // pfarr是一个数组---这个是函数指针数组
    	int(* (*ppfarr)[4])(int,int) = &pfarr;
    	//ppfarr是一个数组指针,指针指向的数组有四个元素
    	//指向的数组的每个元素的类型是一个函数指针int (* )(int,int)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    8.qsort—库函数—排序

    使用qsort库函数可以排序任意类型的数

    整型,字符型,结构体类型

    struct Stu {
    	char name[20];
    	int age;
    };
    
    //void qsort(void* base, size_t num, size_t width, int(*cmp)(const void* e1, const void* e2)) {
    //
    //}
    
    int cmp_int(const void* e1,const void* e2) {
    	//比较两个数的大小
    	return *(int*)e1 - *(int*)e2;
    }
    void test1() {
    	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
    	int sz = sizeof(arr) / sizeof(arr[0]);
    	qsort(arr, sz, sizeof(arr[0]), cmp_int);
    	//第一个参数:待排序数组首元素的地址
    	//第二个参数:到排序数组的个数
    	//第三个参数:待排序数组的每个元素的大小,单位是字节
    	//第四个参数:函数指针,比较两个元素大小的地址,,此函数是自己实现,函数指针的两个参数:待排序的两个数的
    	int i = 0;
    	for (i = 0; i < sz; i++) {
    		printf("%d ", arr[i]);
    	}
    }
    
    int cmp_f(const void* e1, const void* e2) {
    	return ((int)*(float*)e1 - *(float*)e2);
    }
    
    void test2() {
    	float f[] = { 9.0,8.0,7.0,6.0,5.0,4.0,3.0,2.0,1.0 };
    	int sz = sizeof(f) / sizeof(f[0]);
    	qsort(f, sz, sizeof(f[0]), cmp_f);
    	int j = 0;
    	for (j = 0; j < sz; j++) {
    		printf("%f ", f[j]);
    	}
    }
    
    int cmp_stubyage(const void* e1, const void* e2) {
    	return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
    }
    
    int cmp_stubyname(const void* e1, const void* e2) {
    	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
    }
    
    void test3() {
    	struct Stu s[] = { {"zhangsan",30},{"lisi",20},{"wanger",10} };
    	int sz = sizeof(s) / sizeof(s[0]);
    	qsort(s, sz, sizeof(s[0]), cmp_stubyname);
    }
    
    int main() {
    	test1();
    	printf("\n");
    	test2();
    	printf("\n");
    	test3();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    int main(){
    	int a=10;
    	int *p=&a;
    	char ch='w';
    	void *pa=&a;
    	pa=&ch;
    	// void * 是无类型的指针,,可以接受任意类型的地址。
    	//void * 类型的指针不能进行解引用操作,也不能进行+-整数操作。
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    比较名字是比较字符串
    字符串比较不能用><=比较,用库函数Strcmp函数

  • 相关阅读:
    SSM足球联赛管理系统
    Qt之进程通信-QProcess(含源码+注释)
    LeetCode //C - 190. Reverse Bits
    人工智能学习:CIFAR-10数据分类识别-VGG网络(5)
    Banana Pi BPI-M7 迷你尺寸开源硬件开发板采用瑞芯微RK3588芯片设计
    面试题:ElasticSearch是什么?应用场景是什么?
    【Python】Python安装指定版本库
    面试算法12:左右两边子数组的和相等
    最全语音特征总结
    优先队列排序(JAVA)
  • 原文地址:https://blog.csdn.net/weixin_47306453/article/details/126200942