C语言作业3

24c039657c9d4c6182234407b6307c3d.jpg

第八章:指针

1.指针是什么

*指针就是变量,用来存放地址的变量

*&:取地址运算符(可以获取一个数据对象的首地址和存储空间大小)

*声明一个指针

目标类型*(有无空格均可)变量名
*定义:设一个数据对象为x,设另一个数据对象为p。p存储了x的首地址和空间大小。那么, p称之为x的指针,或者说p指向x
*指针类型的值就是目标数据对象的首地址
*C语言中通过不同的指针类型来标记目标数据对象的空间大小

*取值运算符   可以根据指针中存储的首地址和空间大小找到目标数据对象
*占位符
%p 是指针类型专用的占位符(通常以16进制显示)
*若指针类型为
4 个字节,使用 %u 为占用符是合适的。但指针类型为 8 个字节时,最好使用 %llu

 

(可以看出pn,*pn表示的是什么) 

*char可以占用小一点的空间,而int会占用大一点的空间
*但是char*与int*存储均为数据对象的地址,因此他们占用空间是相同的
eg.下方若改成*64则结果指针类型占用8个字节

#include<stdio.h>
int main()
{
	//定义指针变量储存变量地址
	int a = 10;
	//指针类型->数据类型*
	int* p;
	p = &a;
	//通过指针间接改变变量的值
	*p = 100;
	printf("%p\n", &a);
	printf("%p\n", p);
	printf("%d\n", a);
	printf("%d\n", *p);
	return 0;

}

964e9f98663840cb872596ec718b794b.png

2.指针运算

规律

sizeof(目标数据对象)被称为步长

指针类型加n后,其首地址向后移动n*步长 字节
指针类型减n后,其首地址向前移动n*步长 字节
指针类型与指针类型相减后,其结果为两首地址差值除以步长

*步长为指针所指向的类型所占空间大小

eg.

int*p=(int*)100

p+1,结果为首地址向移动sizeof(int)字节,即104

p+1,结果为首地址向移动sizeof(int)字节,即96

*1.指针类型与整形加减

*2.同类型的指针相减

(这两种运算都有意义,其他运算没有实际意义)

3.指针与数组

 规则:(设数组元素为T)

T arr[5];//以T为元素数组arr
T *P;//指向T的指针

当数组名arr出现在一个表达式中,数组名arr将会被转换为指向数组第一个元素的指针

但有两个例外:

  1.对数组名arr使用sizeof 时

  2.对数组名arr使用&时

使用指针访问数组等价于下标访问,有两种方法:

1.数组名【下标】

2.*(数组名+偏移量)      注:取值运算符 * 优先级高于算术运算符,所以要加括号

(偏移量是指指针指向的地址和数组首地址之间相差几个元素)

*这两种形式是等价的,中括号【】,被称作下标运算符,它的优先级高于一切其他运算符

通常形式为  A[k]

而表达式运算时,最终会将下标运算符展开为

*(A+k)

#include <stdio.h>
int main()
{
	int arr[5] = { 111,222,333,444,555 };
	printf("arr[2]=%d\n", arr[2]);
	printf("2[arr]=%d\n", 2[arr]);
	printf("*(arr+2)=%d\n", *(arr + 2));
	return 0;
}

4.指针作为参数传递

#include<stdio.h>
void swap(int* x, int* y)
{
	int temp = *x;
	*x = *y;
	*y = temp;
}
int main()
{
	int a, b;
	int temp;
	a = 1;
	b = 2;
	printf("a=%d b=%d\n", a, b);
	swap(&a, &b);
	printf("a=%d b=%d\n",a, b);
	return 0;
}

 注意:不是交换指针x,y的值,而是交换目标数据对象a,b的值。所以,需要在指针前使用取值运算符 * 。 

由于指针类型定死了指针所指向的数据类型。为了让函数可以交换更多数据类型,我们仅需要指针类型中保存的首地址,目标数据大小通过额外的参数传入。

int n;
void *p=&n; //int*赋值给void*,类型信息丢弃,仅保存首地址
*p; //仅有首地址,未保存目标数据对象大小,无法取值
p+1; //仅有首地址,没有步长,无法进行加减运算

但void*有个好处,就是任意类型指针都可以直接赋值给它。而其他类型的指针是不能相互赋值的,由于赋值会改变目标数据对象的类型。

规律:

1.不同指针类型不能相互赋值,相互赋值后会造成目标数据对象类型的改变,无法通过编译。

2.void*类型为特例,它可以接受任意指针类型的赋值,也可以赋值给任意类型的指针

void swap(void* x, void* y, int size)
{
	//指针转为char*,单个字节操作内存
	char* pX = (char*)x;
	char* pY = (char*)y;
	char temp;
	for (int i = 0; i < size; i++)
	{
		temp = pX[i];
		pX[i] = pY[i];
		pY[i] = temp;
	}
}

 由于void*不能取值和加减,所以将其转换成char*.

char*可以提供单个操作内存的能力

C语言中void*类型不但可以接受任意类型的指针,也可以自动转换为任意类型指针

而c++中仅能接受任意类型指针,不能自动转换

5.多级指针和指针数组

*指针的指针

形式: int * *p(中间*的空格没有固定要求) 

*多级指针

  和普通指针一样通过取值运算符*,获取目标数据对象

#include<stdio.h>
int main()
{
	int n = 123;
	int* p = &n;
	int** pn = &p;
	int*** pnn = &pn;
	printf("n=%d", ***pnn);
	return 0;
}

*指针数组

#include<stdio.h>
int main()
{
	int arr1[5] = { 1,2,3,4,5 };
	int arr2[5] = { 11,22,33,44,55 };
	int arr3[5] = { 111,222,333,444,555 };
	int* pToArr[3];
	pToArr[0] = arr1;
	pToArr[1] = arr2;
	pToArr[2] = arr3;
	for (int i = 0; i < 3; i++)
	{
		int** p = pToArr + i;
		for (int j = 0; j < 5; j++)
		{
			printf(" %d", *(*p + j));
		}
		printf("\n");
	}
	return 0;
}

 

分析:

 p,指向pToArr的第一个元素,类型为int**

*p,指向arr1的第一个元素,类型为int*

*p+j,指向arr1中的第j个元素,类型为int*

*(*p+j),为arr1中的第j个元素​​​​​​​

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值