【常见问题】数组和指针的区别,以字符数组和字符指针为例

本文主要针对字符数组和字符指针进行对比,其他类型的对比请大家自行试验~

数组和指针如何定义

char *p = "hello world";  // p为字符指针
char buf[] = "hello world"; // buf为字符数组

1.sizeof大小不同,strlen相同

printf("p的sizeof大小:%d\n", sizeof(p)); // 指针的sizeof大小为4(32位设备为4,64位设备为8)
printf("buf的sizeof大小:%d\n", sizeof(buf)); // 数组的大小要计算最后\0,大小为12

printf("p的strlen大小:%d\n", strlen(p)); // strlen的长度为11,到\0为止
printf("buf的strlen大小:%d\n", strlen(buf)); // strlen的长度为11,到\0为止

2.数组内容可修改,指针的内容不可修改

原则1:堆栈区的数据可修改,全局区内容不可修改
原则2:栈区数据在函数结束后会被释放

例1:

// 编译不报错,运行报错
// 原因:"hello world"字符串在字符常量区,栈上变量p存了字符串的地址,而字符常量区的内容是不可变的
p[0] = 'w';
printf("p: %s\n", p);```

// 成功运行,字符串修改为"wello world"
// 原因:"hello world"字符串拷贝到栈区,将首地址存在buf变量中,栈区内容可修改
buf[0] = 'w';
printf("buf: %s\n", buf);

例2:

char * func1() {
	char *a = "hello world";
	return a + 6;
}

char * func2() {
	char a[] = "hello world";
	return a + 6;
}

// 成功显示字符串world
// 原因:"hello world"在字符常量区,函数结束不会被释放,回的是常量区字符串首地址+6,可以找到字符串world
printf("指针a: %s\n", func1()); 

// 显示结果未知(Visual studio中)或程序崩溃(其他的可能结果)
// 原因:数组a在栈区,函数结束后空间被释放掉了,再读取之前返回的内存空间则是随机字符串或者内存不可访问,程序崩溃
printf("数组a: %s\n", func2());

3.函数传递,数组会退化成指针

数组作为形参传递会退化成指针
为什么会有这样的设计呢?
因为数组所占空间可能很大,如果形参用原数组传递的话,需要占用大量的栈空间,在最初的设备中,空间可是很宝贵的~

void  func_char(char *temp_p) {
	// sizeof为4, strlen为11
	printf("temp_p的sizeof大小:%d\n", sizeof(temp_p));
	printf("temp_p的strlen大小:%d\n", strlen(temp_p));
}

void func_arr(char temp_buf[]) {
	// sizeof为4, strlen为11
	// temp_buf已经退化成指针,如果仍然是数组传递的话,此处的sizeof应为12
	printf("temp_buf的sizeof大小:%d\n", sizeof(temp_buf));
	printf("temp_buf的strlen大小:%d\n", strlen(temp_buf));
}

func_char(p);
func_arr(buf);

附件:全代码

#include <stdio.h>

char * func1() {
	char *a = "hello world";
	return a + 6;
}

char * func2() {
	char a[] = "hello world";
	return a + 6;
}

void  func_char(char *temp_p) {
	// sizeof为4, strlen为11
	printf("temp_p的sizeof大小:%d\n", sizeof(temp_p));
	printf("temp_p的strlen大小:%d\n", strlen(temp_p));
}

void func_arr(char temp_buf[]) {
	// sizeof为4, strlen为11
	// temp_buf已经退化成指针,如果仍然是数组传递的话,此处的sizeof应为12
	printf("temp_buf的sizeof大小:%d\n", sizeof(temp_buf));
	printf("temp_buf的strlen大小:%d\n", strlen(temp_buf));
}

int main()
{
	char *p = "hello world";  // p为字符指针
	char buf[] = "hello world"; // buf为字符数组

	printf("p的sizeof大小:%d\n", sizeof(p)); // 指针的sizeof大小为4(32位设备,64位设备为8)
	printf("buf的sizeof大小:%d\n", sizeof(buf)); // 数组的大小要计算最后\0,大小为12

	printf("p的strlen大小:%d\n", strlen(p)); // strlen的长度为11,到\0为止
	printf("buf的strlen大小:%d\n", strlen(buf)); // strlen的长度为11,到\0为止

	// 编译不报错,运行报错
	// 原因:"hello world"字符串在字符常量区,栈上变量p存了字符串的地址,而字符常量区的内容是不可变的
	//p[0] = 'w';
	//printf("p: %s\n", p);
	
	// 成功运行,字符串修改为"wello world"
	// 原因:"hello world"字符串拷贝到栈区,将首地址存在buf变量中,栈区内容可修改
	buf[0] = 'w';
	printf("buf: %s\n", buf);

	// 成功显示字符串world
	// 原因:"hello world"在字符常量区,函数结束不会被释放,回的是常量区字符串首地址+6,可以找到字符串world
	printf("指针a: %s\n", func1()); 

	// 显示结果未知(Visual studio中)或程序崩溃(其他编译器,未尝试,运行的可能结果)
	// 原因:数组a在栈区,函数结束后空间被释放掉了,再读取之前返回的内存空间则是随机字符串或者内存不可访问,程序崩溃
	printf("数组a: %s\n", func2());
	
	func_char(p);
	func_arr(buf);

	system("pause");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值