指针进阶( 上 )

发布于:2025-04-09 ⋅ 阅读:(30) ⋅ 点赞:(0)

内容大纲

一.字符指针

二.指针数组

三.数组指针

四. 数组传参和指针传参

引言

指针是什么呢?指针是用来干什么的呢?指针的大小是多少呢?指针的大小具有什么属性呢?

解答:指针是个变量,用来存放变量地址的,指针的大小是4/8个字节(32位平台/64位平台),指针的大小是固定的。

一.字符指针

字符指针:char*

书写形式:

char ch = 'a';
char* pc = &ch;

那么只可以这样写吗?

当然不是,我们还可以这样写

const char* pa = "abcdef";

首先,观察代码片段 char* pa = "abcdef",我们注意到等号右侧是一个字符串常量。然而,这并不意味着该表达式将整个字符串赋值给指针 pa。实际上,它将字符串的首字母 'a' 的地址赋给了 pa

其次,我们如何看const呢?

因为“abcdef”是常量字符串,其值是不可以改变的,加上const更加严谨、准确。

如何理解 const 关键字及其在常量字符串中的应用

在编程中,const 关键字是一个非常重要的工具,它用于声明常量或只读变量。当一个变量被 const 修饰时,意味着该变量的值在初始化之后不能被改变。这种特性在处理常量字符串时尤为重要,因为它确保了字符串的值在整个程序运行期间保持不变,从而增加了程序的健壮性和安全性。

const 关键字的作用和优点

const 关键字的主要作用是保护被修饰的对象,防止意外的修改。在C语言中,const 可以用来修饰变量、函数参数、返回值等,使得这些被修饰的对象成为只读的。这样做不仅增强了代码的可读性,还能够在编译期捕获潜在的错误,比如试图修改常量的行为,从而避免了运行时的错误31

此外,const 关键字还有助于提高程序的效率。编译器通常不会为普通的 const 常量分配存储空间,而是将它们保存在符号表中,这使得 const 常量成为编译期间的常量,没有了存储与读内存的操作,因此效率也很高4

const 关键字在常量字符串中的应用

对于常量字符串,如 "abcdef",使用 const 关键字进行修饰是一种良好的编程实践。这是因为常量字符串本质上是不可变的,不应该被修改。通过在声明时加上 const,可以明确地表达这一意图,并且在编译时就能够捕捉到任何试图修改字符串的行为,从而避免了可能的错误。

接下来,我们来看一下这道题

#define  _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	char str1[] = "hello world";
	char str2[] = "hello world";

	const char* str3 = "hello world";
	const char* str4 = "hello world";

	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;
}

输出结果:

解答:

首先,我们来看

char str1[] = "hello world";

char str2[] = "hello world";

这相当于个字符数组str1[]和str2[]进行初始化,在后续操作中我们可以分别对数组str1[]和str2[]的值进行改变,所以在创建这两个数组时,占用了两个不同的空间

str1==str2

这个表达式不是比较两个数组的内容而是比较两个数组元素的首地址

故:

str1 and str2 are not same.

其次,我们来看

const char* str3 = "hello world";

const char* str4 = "hello world";

在这两行代码中 "hello world"都是常量字符串,且内容均相同,没必要存储在两个不同的内存中

故:str3 and str4 are same.

二.指针数组

整型数组——存放整型变量的数组

字符数组——存放字符变量的数组

那么

指针数组——存放指针变量的数组

当我们想连续打印一组字符串时,我们就可以使用指针数组

#define  _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	const char* ch[4] = { "abc","def","hello","yes" };
	int i = 0;
	for (i = 0;i < 4;i++)
	{
		printf("%s\n", ch[i]);
	}
	return 0;
}

当然也可以通过指针数组将多个一位数组组合在一起,形成类似二级数组的东西

	int a1[4] = { 1,2,3,4 };
	int a2[4] = { 2,3,4,5 };
	int a3[4] = { 3,4,5,6 };
	int* a[3] = {a1,a2,a3};
	int j = 0;
	for (i = 0;i < 3;i++)
	{
		for (j = 0;j < 3;j++)
		{
			printf("%d ", a[i][j]);
		}
		printf("\n");
	}

输出结果:

三.数组指针

字符指针——存放字符地址的指针——指向字符的指针 char*

整型指针——存放整形地址的指针——指向整型的指针 int*

那么,数组指针顾名思义

数组指针——存放数组地址的指针——指向数组的指针

书写形式:

	int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
	int (*p)[10] = &arr;

&arr与arr

那么可以&arr可以写成arr吗?

我们通过代码来看一下二者到底有无区别

#define  _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int arr[3] = { 0 };
	printf("%p\n", arr);
	printf("%p\n", &arr);
	return 0;
}

输出结果:

这样一看没有区别,arr,&arr都表示了数组元素的首地址,但是真的如此吗?我们接着来看

#define  _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int arr[3] = { 0 };
	printf("%p\n", arr);
	printf("%p\n", arr + 1);

	printf("%p\n", &arr);
	printf("%p\n", &arr+1);
	return 0;
}

输出结果:

可见从arr 到arr+1相当于在地址上+4,而从&arr到&arr+1却加上了40,那么这表示,arr和&arr并不相同

数组指针的使用( 一般用于二维数组)

#define  _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

void Print(int (*p)[4], int n, int m)
{
	int i = 0;
	for (i = 0;i < n;i++)
	{
		int j = 0;
		for (j = 0;j < m;j++)
		{
			printf("%d ", ((*p + i)[j]));
		}
		printf("\n");
	}
}

int main()
{
	int arr[3][4] = { {1,2,3,4},{2,3,4,5},{3,4,5,6} };
	Print(arr, 3, 4);
	return 0;
}

其中int (*p)[4],就是将二维数组拆分成多个一维数组,4表示一维数组的元素个数

四. 数组传参和指针传参

对于一个数组,我们只能够做两件事1.确定数组大小;2.获得指向该数组下标为0的元素的指针,其他操作,虽然看上去我们是通过数组下标来进行操作的,但实际上是通过指针进行运算的

一维数组传参

主要有以下几个形式

void test(int arr[]);
void test(int arr[10]);
void test(int *arr);

二维数组传参

主要有以下几个形式

void test(int arr[3][4]);
void test(int arr[][4]);
void test(int (*arr)[4]);

一级指针传参

#define  _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

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

int main()
{
	int arr[4] = { 1,2,3,4 };
	int* p = arr;
	int sz = sizeof(arr) / sizeof(arr[0]);
	Print(p, sz);
	return 0;
}

输出结果:

二级指针传参

#define  _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

void test(int** p)
{
 printf("num = %d\n", **p); 
}
int main()
{
 int n = 10;
 int*p = &n;
 int **pp = &p;
 test(pp);
 test(&p);
 return 0;
}

网站公告

今日签到

点亮在社区的每一天
去签到