【FAQ】配列とポインタの違いについて、文字配列と文字ポインタを例に

この記事では主に文字配列と文字ポインタの比較を行っていますが、その他の比較についてはご自身で試してみてください~

配列とポインタの定義方法

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

おすすめ

転載: blog.csdn.net/guggle15/article/details/124836443