一、我们由一个引用交换字符串函数开场:
void Swap(char* &str1, char* &str2)
{
char *temp;
temp = str1;
str1 = str2;
str2 = temp;
}
int main()
{
char ap[] = "hello";
char bp[] = "how are you";
char *ap1 = "hello";
char *bp1 = "how are you";
//swap(ap,bp); //这样是错误的?
swap(ap1, bp1); //这样能够引用?两者不是一样的吗?
system("pause");
return 0;
}
经验:
1.如果用ap和bp的话,是无法引用的,因为它不是指向一个常量的。
2.如果用ap1和bp1的话,可以引用,但是交换的其实是地址,因为常量区是无法被修改的。
3.而如果把函数改为字符的引用,就是交换的是内容。想想这是为什么?上面的为什么指向的是常量区?
二、为了解决这个疑问,我们来看看实质的差别:
int main()
{
char a[] = { "I like C" };
char b[9] = { "I like C" };
char *c = "I like C";
//执行到这里我们来看看地址截图1
strcpy_s(a, strlen("hello") + 1, "hello");
strcpy_s(b, strlen("hello") + 1, "hello");
//strcpy_s(c,strlen("hello") + 1, "hello");//这样不行哦
c = "hello";//这样为什么可以?
//执行到这里我们来看看地址截图2
printf("%s\n%s\n%s\n", a, b, c);
system("pause");
return 0;
}
地址截图:
地址1:
地址2:
看看实际地址和变量类型,有什么不同,那么现在明白了吗?
没错:a,b是可以在原地址改变内容的,而c原来是改变地址指向某个常量的。最后看看地址的范围,是不是有些差别?
三、我们再来看看这几种
int main()
{
char *str1 = "hello 15pb";
char *str2 = (char*)malloc(strlen("hello 15pb") + 1);
char *str3 = new char[strlen("hello 15pb") + 1];
char str4[] = "hello 15pb";
char str5[11] = "hello 15pb";
//走到这里,我们来看看地址截图1
//strcpy_s(str1, strlen("15pb good") + 1, "15pb good");//无法赋值,因为str1是指向的常量
str1 = "15pb good";
str2 = "15pb good";//str2变成指向常量的指针,同样再次就无法用strcpy赋值了
strcpy_s(str3, strlen("15pb good") + 1, "15pb good");
strcpy_s(str4, strlen("15pb good") + 1, "15pb good");
strcpy_s(str5, strlen("15pb good") + 1, "15pb good");
//走到这里,我们来看看地址截图2
system("pause");
return 0;
}
地址截图:
地址1:
地址2:
看图后面的解释,发现内存分为很多区域了,最后我来解释下原因,
计算机在内存中分为以下区域:
1.栈区(函数参数值、局部变量):
程序运行时由编译器自动分配,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈,程序结束时编译器自动释放。
2.堆区(动态分配的):
在内存开辟另一块存储区域,一般由程序员分配、释放。若未被释放,则在程序结束时系统回收。注意它与数据结构中的堆是两回事,类似于链表。
3.静态区(全局变量和静态变量):
编译器编译时即分配空间,全局变量和静态变量的存储是放在一起的。
4.文字常量区(常量字符串)
常量字符串存储的地方。
5.程序代码区(函数体的二进制代码)
存放函数体的二进制代码。
上面的内存概念很重要哦,对你以后的程序构思是很有帮助的,希望大家都记一下啦!
好了,朋友们,今天的知识学到了吗?我们下次再会!