“指针”相关

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_43909184/article/details/90753967

指针是什么?

在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元。
在这里插入图片描述
指针是用来存放地址的,地址是唯一标示一块地址空间的。
指针的大小在32位平台是4个字节,在64位平台是8个字节。

指针和指针类型

这里我们在讨论一下:指针的类型 我们都知道,变量有不同的类型,整形,浮点型等。那指针有没有类型呢? 准确的说:有的。
指针的定义方式是: type + * 。其实: char* 类型的指针是为了存放 char 类型变量的地址。 short* 类型的指针是为了存放 short 类型变量的地址。 int* 类型的指针是为了存放 int 类型变量的地址。
指针±整数
指针的类型决定了指针向前或者向后走一步有多大(距离)。
指针的解引用
指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。 比如: char* 的指针解引用就 只能访问一个字节,而 int* 的指针的解引用就能访问四个字节。

指针和数组

数组名表示的是数组首元素的地址。

	 int arr[10] = {1,2,3,4,5,6,7,8,9,0};
	 int *p = arr;//p存放的是数组首元素的地址 

p+i 其实计算的是数组 arr 下标为i的地址。
那我们就可以直接通过指针来访问数组。
如下:

int main() {  
 	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };  
 	int *p = arr; //指针存放数组首元素的地址  
 	int sz = sizeof(arr) / sizeof(arr[0]);
 	int i = 0;  
 	for (i = 0; i<sz; i++) {  
 		 printf("%d ", *(p + i));  
 	 } 
 	  return 0;
 } 

指针数组

指针数组是指针还是数组?
答案:是数组。是存放指针的数组。
数组我们已经知道整形数组,字符数组。
那指针数组是怎样的?
int* arr[5];//是什么?
arr是一个数组,有五个元素,每个元素是一个整形指针。

字符指针

在指针的类型中我们知道有一种指针类型为字符指针 char* ;
一般使用:

int main() {    
	char ch = 'w';    
	char *pc = &ch;    
	*pc = 'w';   
	 return 0; 
}

还有一种使用方式如下:

int main() {   
	 char* pstr = "hello bit.";//这里是把一个字符串放到pstr指针变量里了吗?   
	 printf("%s\n", pstr);    
	 return 0; 
} 

代码 char* pstr = “hello bit.”;特别容易让同学以为是把字符串 hello bit 放到字符指针 pstr 里了,但是本质是把字符串 hello bit. 首字符的地址放到了pstr中。上面代码的意思是把一个常量字符串的首字符 h 的地址存放到指针变量 pstr 中。
在这里插入图片描述

数组指针

数组指针是指针?还是数组?
答案是:指针。
我们已经熟悉: 整形指针: int * pint;能够指向整形数据的指针。 浮点型指针: float * pf;能够指向浮点型数 据的指针。
那数组指针应该是:能够指向数组的指针。
下面代码哪个是数组指针?

int *p1[10]; 
int (*p2)[10]; 
//p1, p2分别是什么

int (*p)[10];
//解释:p先和 * 结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组。所以p是一个指针,指向一个数组,叫数组指针。

//这里要注意:[]的优先级要高于 * 号的,所以必须加上()来保证p先和 * 结合。
&数组名VS数组名

#include <stdio.h> 
int main() {    
	int arr[10] = {0};   
	printf("%p\n", arr);    
	printf("%p\n", &arr);   
	return 0; 
} 

在这里插入图片描述
可见数组名和&数组名打印的地址是一样的。
难道两个是一样的吗?
我们再看一段代码:

#include <stdio.h> 
int main() {  
	int arr[10] = { 0 };  
	printf("arr = %p\n", arr);  
	printf("&arr= %p\n", &arr); 
  	printf("arr+1 = %p\n", arr+1);  
  	printf("&arr+1= %p\n", &arr+1);  
  	return 0;
} 

在这里插入图片描述
根据上面的代码我们发现,其实&arr和arr,虽然值是一样的,但是意义应该不一样的。
实际上: &arr 表示的是数组的地址,而不是数组首元素的地址。数组的地址+1,跳过整个数组的大小,所以 &arr+1 相对于 &arr 的差值是40。

函数指针

首先看一段代码:

#include <stdio.h> 
void test() {  
	printf("hehe\n"); 
} 
int main() {  
	printf("%p\n", test);  
	printf("%p\n", &test);  
	return 0; 
} 

在这里插入图片描述
输出的是两个地址,这两个地址是 test 函数的地址。 那我们的函数的地址要想保存起来,怎么保存? 下面我们看代码:

void test() {  
	printf("hehe\n"); 
} 
//下面pfun1和pfun2哪个有能力存放test函数的地址? 
void (*pfun1)(); 
void *pfun2();

首先,能给存储地址,就要求pfun1或者pfun2是指针,那哪个是指针? 答案是:
pfun1可以存放。pfun1先和*结合,说明pfun1是指针,指针指向的是一个函数,指向的函数无参数,返回值类型为void。
回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

#include<stdio.h>
typedef int(*Cmp)(int a, int b);
void swap(int *a, int *b) {
	int tmp;
	tmp = *a;
	*a = *b;
	*b = tmp;
}
void bubbleSort(int *a, int num, Cmp cmp) {
	int i, j;
	for (i = 0; i < num; ++i) {
		for (j = 0; j < num - i - 1; ++j) {
			if (!cmp(a[j], a[j + 1])) {
				swap(&a[j], &a[j + 1]);
			}
		}
	}
}
int Less(int a, int b) {
	return a < b ? 1 : 0;
}
int Greater(int a, int b) {
	return a > b ? 1 : 0;
}
int main() {
	int a[4] = { 9, 5, 2, 7 };
	bubbleSort(a, 4, Greater);
	int i;
	for (i = 0; i < 4; ++i) {
		printf("%d ", a[i]);
	}
	putchar('\n');
	system("pause");
	return 0;
}

以上代码是冒泡排序,而是通过回调函数的方式,来确定排序规则。

猜你喜欢

转载自blog.csdn.net/qq_43909184/article/details/90753967