【c语言】指针

本文详细介绍了指针的基本概念,包括指针的定义、类型、解引用、野指针、指针运算、数组与指针的关系、二级指针、字符指针、数组指针以及函数指针的使用。通过实例演示了指针在编程中的实际应用,如传参和函数指针数组。
摘要由CSDN通过智能技术生成

1.指针是什么

指针也是一种变量,这种变量专门存储地址值

int a = 100;

int* b = &a;

上面的代码很清晰,a是一个整形变量,值为100;b是一个指针变量,值是变量a的地址。变量和指针的类型必须相同。

解引用:

#include<stdio.h>
int main() {
	int a = 10;
	int* pa = &a;
	//printf("%p\n", pa);
	//printf("%p\n", &a);
	*pa = 20; //*为解引用操作
	printf("%d\n",a);
	return 0;
}

20

 2.指针和指针类型

int占4个字节,char 占1个字节,short占2个字节,double占8个字节。

指针类型有多种多样,int* ,float* ,char*等等,

2.1 指针+-整数

指针的类型决定了指针向前或者向后走一步有多大(距离)
2.2指针的解引用
指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。
比如: char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字节

3.野指针

野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)

 要规避野指针!!!

 4.指针运算

指针 +- 整数
指针 - 指针
指针的关系运算

 5.指针与数组

数组名表示的是数组首元素的地址
引用一个数组元素,可以用以下两种方法:
1. 下标法,如  a[i] 形式;
2. 指针法,如  *(a+i)或  *(p+i)。其中 a 是数组名,p是指向数组元素的指针变量,其初值为  p=a

 6.二级指针

二级指针就是取一级指针的地址,一级指针就是取原来数字的地址。

 **ppa 先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作: *pa ,那找到的是 a .

** ppa = 30 ;
// 等价于 *pa = 30;
// 等价于 a = 30;

7. 字符指针

#include <stdio.h>
int main()
{
 char str1[] = "hello bit.";
 char str2[] = "hello bit.";
 const char *str3 = "hello bit.";
 const char *str4 = "hello bit.";
 if(str1 ==str2)
 printf("str1 and str2 are same\n");
 else
 printf("str1 and str2 are not same\n");
 
 if(str3 ==str4)
 printf("str3 and str4 are same\n");
 else
 printf("str3 and str4 are not same\n");
 
 return 0;
}

这里 str3 str4 指向的是一个同一个常量字符串。 C/C++ 会把常量字符串存储到单独的一个内存区域,当几个指针指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。所以str1 str2 不同, str3 str4 相同。

8.指针数组

指针数组是一个存放指针的数组
int* arr1 [ 10 ]; // 整形指针的数组
char * arr2 [ 4 ]; // 一级字符指针的数组
char ** arr3 [ 5 ]; // 二级字符指针的数组
#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 的类型是: int(*)[10] ,是一种数组指针类型
数组的地址 +1 ,跳过整个数组的大小,所以 &arr+1 相对于 &arr 的差值是 40

9.数组指针

数组指针是指向数组的指针

需要明确一个优先级顺序:()>[]>*,所以:

(*p)[n]:根据优先级,先看括号内,则p是一个指针,这个指针指向一个一维数组,数组长度为n,这是“数组的指针”,即数组指针;

*p[n]:根据优先级,先看[],则p是一个数组,再结合,这个数组的元素是指针类型,共n个元素,这是“指针的数组”,即指针数组。

int *p1[5];//指针的数组

int (*p2)[5];//数组的指针

10.数组参数、指针参数 

10.1一维数组传参
#include <stdio.h>
void test(int arr[])//ok
{}
void test(int arr[10])//ok
{}
void test(int *arr)//ok
{}
void test2(int *arr[20])//ok
{}
void test2(int **arr)//ok,二级指针为一级指针的地址
{}
int main()
{
 int arr[10] = {0};
 int *arr2[20] = {0};
 test(arr);
 test2(arr2);
}
10.2二维数组传参
void test(int arr[3][5])//ok
{}
void test(int arr[][])//err
{}
void test(int arr[][5])//ok
{}
//总结:二维数组传参,函数形参的设计只能省略第一个[]的数字。
//因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。
//这样才方便运算。
void test(int *arr)//err 一级指针啥也找不到
{}
void test(int* arr[5])//err 是个数组但找不到元素
{}
void test(int (*arr)[5])//ok 指针指向的数组
{}
void test(int **arr)//err 存放的是一级指针的地址
{}
int main()
{
 int arr[3][5] = {0};
 test(arr);
}
10.3一级指针传参
#include <stdio.h>
void print ( int * p , int sz )
{
int i = 0 ;
for ( i = 0 ; i < sz ; i ++ )
{
printf ( "%d\n" , * ( p + i ));
}
}
int main ()
{
int arr [ 10 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 };
int * p = arr ;
int sz = sizeof ( arr ) / sizeof ( arr [ 0 ]);
// 一级指针 p ,传给函数
print ( p , sz );
return 0 ;
}
10.4二级指针传参
void test ( char ** p )
{
}
int main ()
{
char c = 'b' ;
char* pc = & c ;
char** ppc = & pc ;
char* arr [ 10 ];
test ( & pc );
test ( ppc );
test ( arr ); //Ok?
return 0 ;
}

11.函数指针

 void (*pfun1)(); //存储函数的地址

=&add

=add

12.函数指针数组 

把函数的地址存到一个数组中,那这个数组就叫函数指针数组。

#include<stdio.h>

int my_strlen(const char* str) {
	return 0;
}

int main() {
	//函数指针数组
	int(*pf[5])(const char*) = { &my_strlen };//数组内部存放的是函数的地址

	return 0;
}
 函数指针数组的用途:转移表-------例子:(计算器)
#include <stdio.h>
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;
}
void meau() {
	printf("*************************\n");
	printf("     1:add    2:sub      \n");
	printf("     3:mul    4:div      \n");
	printf("*************************\n");
}
int main() {
	int a, b, input, ret;
	input = 1;
	int (*p[5])(int x, int y) = { 0,add,sub,mul,div };
	do {
		meau();
		printf("请选择操作:");
		scanf_s("%d",&input);
		if ((input >= 1) && (input <= 4)) {
			printf("请输入数:");
			scanf_s("%d %d", &a, &b);
			ret = (*p[input])(a, b);
		}
		else
			printf("输入有误\n");
		printf("ret = %d\n", ret);
	} while (input);
	
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值