当前位置: 首页 > article >正文

【重生之我要苦学C语言】深入理解指针3

深入理解指针3

数组

数组名是数组首元素的地址,但有两个例外

  • sizeof(数组名)//sizeof的括号中单独放一个数组名的时候,数组名表示整个数组,计算出但是整个数组的大小,单位是字节
  • &数组名 //这里的数组名也表示整个数组,取出的是这个数组的地址
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("&arr[0]   =%p\n", &arr[0]);//首元素的地址
	printf("&arr[0]+1 =%p\n", &arr[0]+1);//首元素的地址+1
	printf("arr       =%p\n", arr);//首元素的地址
	printf("arr+1     =%p\n", arr+1);//首元素的地址+1
	printf("&arr      =%p\n", &arr);//数组的地址
	printf("&arr+1    =%p\n", &arr+1);//数组的地址+1
	return 0;
}

在这里插入图片描述
&arr+1比&arr大了40,即跳过了整个arr数组

     &arr[0]——>int*
     arr      ——>int*
     &arr  ——>类型不是int*(数组指针)

使用指针访问数组

按顺序输出数组元素:

方法一:p不变

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
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]);
	int i = 0;
	for (i = 0;i < sz;i++) {
		printf("%d ", *(p + i));
	}
	return 0;
}

方法二:p改变

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
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]);
	int i = 0;
	for (i = 0;i < sz;i++) {
		printf("%d ", *p);
		p++;
	}
	return 0;
}

输入数组的内容

方法一:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
	int arr[10] = { 0 };
	int* p = arr;
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	for (i = 0;i < sz;i++) {
		scanf("%d", p + i);
	}
	for (i = 0;i < sz;i++) {
		printf("%d ", *p);
		p++;
	}
	return 0;
}

方法二:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
	int arr[10] = { 0};
	int* p = arr;
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	for (i = 0;i < sz;i++) {
		scanf("%d", p);
		p++;
	}
	p = arr;//p回归首元素地址
	for (i = 0;i < sz;i++) {
		printf("%d ", *p);
		p++;
	}
	return 0;
}
int* p = arr;

arr-数组名,是数组首元素的地址,类型是:int*
p里面存放的也是首元素的地址,类型也是int*
arr等价于p

当不用指针输出的时候,应写为:

for (i = 0;i < sz;i++) {
	printf("%d ", arr[i]);
	p++;
}

那么因为arr等价于p,可以写成p[i]:

for (i = 0;i < sz;i++) {
	printf("%d ", p[i]);
	p++;
}

又因为可以写成

for (i = 0;i < sz;i++) {
		printf("%d ", *(p + i));
	}

可以得出:

p[i] =* (p+i) =*(i+p)

那么是否可以写成 i[p] 或 i[arr] 呢?

答案是可以的

    arr[i] ——> *(arr+i)
    []就是一个操作符

数组传参的本质

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void print_arr(int arr[], int sz) {
	int i = 0;
	for (i = 0;i < sz;i++) {
		printf("%d ", arr[i]);
	}
}
int main() {
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	print_arr(arr, sz);
	return 0;
}

在这里插入图片描述

如果改为:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void print_arr(int arr[]){
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (i = 0;i < sz;i++) {
		printf("%d ", arr[i]);
	} 
}
int main() {
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	print_arr(arr);
	return 0;
}

X86环境下:

在这里插入图片描述

X64环境下:

在这里插入图片描述

是因为:

数组在传参的时候,不会将整个数组传递过去

print_arr(arr);//arr数组名表示数组首元素的地址

所以传过去的是数组首元素的地址,在函数内没办法计算数组的元素个数,

void print_arr(int arr[]){//实际上为int* arr

所以可以写为:

void print_arr(int* arr, int sz) {

形参的数组和实参的数组是同一个数组
函数的形参可以写成数组,也可以写成指针

冒泡排序

复习一下冒泡排序

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void bubble_sort(int arr[], int sz) {
	int i = 0;
	int j = 0;
	for (i = 0;i < sz - 1;i++) {
		int flag = 0;//假设已经有序
		for (j = 0;j < sz - 1 - i;j++) {
			if (arr[j] > arr[j + 1]) {
				flag = 1;
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
		if (flag == 0) {
			break;
		}
	}
}
void print_arr(int arr[], int sz) {
	int i = 0;
	for (i = 0;i < sz;i++) {
		printf("%d ", arr[i]);
	}
	printf("\n");
}
int main() {
	//排成升序
	int arr[10] = {9,8,7,6,5,4,3,2,1,0};
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr,sz);
	print_arr(arr, sz);
	return 0;
}

二级指针

int a = 10;
int* p = &a;
int** pp=&p;//pp就叫二级指针

理解:int* *pp: * pp是说pp是指针变量,int * 是说pp指向的p是 int *类型的
二级指针变量是用来存放一级指针的地址

printf("%d\n", **pp);

等同于

printf("%d\n", *p);

const修饰:

const int** p;//const限制**p
int* const * p;//const限制*p
int** const p;//const限制p

指针数组

存放指针(地址)的数组

int* arr[3] = { &a,&b,&c };

例:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
	int a=10, b=20, c=30;
	int* arr[3] = { &a,&b,&c };
	int i = 0;
	for (i = 0;i < 3;i++) {
		printf("%d ", *(arr[i]));
	}
	return 0;
}

在这里插入图片描述

指针数组模拟二维数组

在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 2,3,4,5,6 };
	int arr3[] = { 3,4,5,6,7 };
	int* arr[3] = { arr1,arr2,arr3 };//arr指针数组
	int i = 0;
	for (i = 0;i < 3;i++) {
		int j = 0;
		for (j = 0;j < 5;j++) {
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

结果为:

在这里插入图片描述

 arr[i]=*(arr+i)
 arr[j]=x[j]
 x[j]= *(x+j) = *(*(arr+i)+j)

END……

做一个积极向上的人,读温柔的句子,见阳光的人,眼里全是温柔与笑意~🌻


http://www.kler.cn/a/376847.html

相关文章:

  • kafka里的consumer 是推还是拉?
  • [RootersCTF2019]ImgXweb
  • python实现了对一个数据集(从csv文件读取)的数据预处理、异常值检测、数据重构以及使用多种机器学习模型进行评估和调优的功能
  • selenium 点击元素报错element not interactable
  • 处理非结构化数据:Python中的BeautifulSoup库解析HTML
  • 扫描项目中存在高危风险依赖包升级处理。
  • 【016C】基于51单片机电子秤(LCD1602显示)
  • crc16 with word byte--查表法
  • 自动驾驶---理想汽车智驾进展
  • 计算机网络:网络层 —— IP 多播技术
  • 机器学习与数学公式
  • flutter报错‘/Users/xxx/.gradle/caches/journal-1/file-access.bin‘.
  • 【rust实战】rust博客系统4_连接数据库及查询数据
  • 重构响应对象
  • Dockerfile文件编写
  • linux perf 环境部署和基本测试(基于Ubuntu20.04)
  • 探讨Java深搜算法的学习笔记
  • unreal engine5动画重定向
  • 域渗透-域环境部署
  • Spring Boot集成Milvus和deeplearning4j实现图搜图功能