char *c = abc和char c[]=abc

转自:http://blog.csdn.net/wallwind/article/details/7210474

char *c = "abc"和char c[]="abc",前者改变其内

容程序是会崩溃的,而后者完全正确。
程序演示:
测试环境Devc++
代码
运行结果
2293628 4199056 abc
2293624 2293624 abc
2293620 4199056 abc

#include <iostream>
using namespace std;

main()
{
   char *c1 = "abc";
   char c2[] = "abc";
   char *c3 = ( char* )malloc(3);
   c3 = "abc";
   printf("%d %d %s\n",&c1,c1,c1);
   printf("%d %d %s\n",&c2,c2,c2);
   printf("%d %d %s\n",&c3,c3,c3);
   getchar();
}   

参考资料:
首先要搞清楚编译程序占用的内存的分区形式:
一、预备知识—程序的内存分配
一个由c/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于

数据结构中的栈。
2、堆区(heap)—一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据

结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
3、全局区(静态区)(static)—全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态

变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统

释放。
4、文字常量区—常量字符串就是放在这里的。程序结束后由系统释放。
5、程序代码区
这是一个前辈写的,非常详细
//main.cpp
  int a=0;    //全局初始化区
  char *p1;   //全局未初始化区
  main()
  {
   int b;栈
   char s[]="abc";   //栈
   char *p2;         //栈
   char *p3="123456";   //123456\0在常量区,p3在栈上。
   static int c=0;   //全局(静态)初始化区
   p1 = (char*)malloc(10);
   p2 = (char*)malloc(20);   //分配得来得10和20字节的区域就在堆区。
   strcpy(p1,"123456");   //123456\0放在常量区,编译器可能会将它与p3所向"123456"优化成一个
地方。
}
二、堆和栈的理论知识
2.1申请方式
stack:
由系统自动分配。例如,声明在函数中一个局部变量int b;系统自动在栈中为b开辟空间
heap:
需要程序员自己申请,并指明大小,在c中malloc函数
如p1=(char*)malloc(10);
在C++中用new运算符
如p2=(char*)malloc(10);
但是注意p1、p2本身是在栈中的。
2.2
申请后系统的响应
栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。
堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,
会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将

该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大

小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正

好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。
2.3申请大小的限制
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地

址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译

时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间

较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地

址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的

虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
2.4申请效率的比较:
栈:由系统自动分配,速度较快。但程序员是无法控制的。
堆:是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.
另外,在WINDOWS下,最好的方式是用Virtual Alloc分配内存,他不是在堆,也不是在栈,而是直接在进

程的地址空间中保留一块内存,虽然用起来最不方便。但是速度快,也最灵活。
2.5堆和栈中的存储内容
栈:在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的

地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变

量。注意静态变量是不入栈的。
当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主

函数中的下一条指令,程序由该点继续运行。
堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容由程序员安排。
2.6存取效率的比较
char s1[]="aaaaaaaaaaaaaaa";
char *s2="bbbbbbbbbbbbbbbbb";
aaaaaaaaaaa是在运行时刻赋值的;
而bbbbbbbbbbb是在编译时就确定的;
但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。
比如:
#include
voidmain()
{
char a=1;
char c[]="1234567890";
char *p="1234567890";
a = c[1];
a = p[1];
return;
}
对应的汇编代码
10:a=c[1];
004010678A4DF1movcl,byteptr[ebp-0Fh]
0040106A884DFCmovbyteptr[ebp-4],cl
11:a=p[1];
0040106D8B55ECmovedx,dwordptr[ebp-14h]
004010708A4201moval,byteptr[edx+1]
004010738845FCmovbyteptr[ebp-4],al
第一种在读取时直接就把字符串中的元素读到寄存器cl中,而第二种则要先把指针值读到edx中,在根据

edx读取字符,显然慢了。
2.7小结:
堆和栈的区别可以用如下的比喻来看出:
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会

切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。
使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。

自我总结:
char *c1 = "abc";实际上先是在文字常量区分配了一块内存放"abc",然后在栈上分配一地址给c1并指向

这块地址,然后改变常量"abc"自然会崩溃

然而char c2[] = "abc",实际上abc分配内存的地方和上者并不一样,可以从
4199056
2293624 看出,完全是两块地方,推断4199056处于常量区,而2293624处于栈区

2293628
2293624
2293620 这段输出看出三个指针分配的区域为栈区,而且是从高地址到低地址

2293620 4199056 abc 看出编译器将c3优化指向常量区的"abc"


继续思考:
代码:

输出:
2293628 4199056 abc
2293624 2293624 abc
2293620 4012976 gbc
写成注释那样,后面改动就会崩溃
可见strcpy(c3,"abc");abc是另一块地方分配的,而且可以改变,和上面的参考文档说法有些不一定,

#include <iostream>
using namespace std;

main()
{
   char *c1 = "abc";
   char c2[] = "abc";
   char *c3 = ( char* )malloc(3);
   //  *c3 = "abc" //error
   strcpy(c3,"abc");
   c3[0] = 'g';
   printf("%d %d %s\n",&c1,c1,c1);
   printf("%d %d %s\n",&c2,c2,c2);
   printf("%d %d %s\n",&c3,c3,c3);
   getchar();
}  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/313317.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

同构字符串

题目描述 给定两个字符串 s 和 t&#xff0c;判断它们是否是同构的。 如果 s 中的字符可以被替换得到 t &#xff0c;那么这两个字符串是同构的。 所有出现的字符都必须用另一个字符替换&#xff0c;同时保留字符的顺序。两个字符不能映射到同一个字符上&#xff0c;但字符可…

微软100题第11题

参照&#xff1a;http://blog.csdn.net/caryaliu/article/details/8107089 参照&#xff1a;http://blog.csdn.net/lalor/article/details/7626678 把二叉树看成一个图&#xff0c;父子节点之间的连线看成是双向的&#xff0c;我们姑且定义"距离"为两个节点之间的个…

.NET Core 3.0】框架之十三 || 部署攻略

本文有配套视频&#xff1a;https://www.bilibili.com/video/av58096866/?p9一、部署1、WIN_独立部署感谢群里&#xff08;白云&#xff09;小伙伴&#xff0c;博主 小淋科技 提出的方案(需要 netcore2.1 )&#xff0c;我竟然忽略了&#xff0c;该打该打&#xff0c;官档都读…

Python import以及os模块

转自&#xff1a;http://jianpx.iteye.com/blog/486466 http://blog.chinaunix.net/uid-27838438-id-4087978.html Import: 1. import 实际上是python虚拟机把当前的globals()和locals()传进__builtins__.__import__内置函数了&#xff0c;所以实际上干活的是那个__import__函…

移除元素

题目描述 给定一个数组 nums 和一个值 val&#xff0c;你需要原地移除所有数值等于 val 的元素&#xff0c;返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。 元素的顺序可以改变。你不需要考虑数…

.Net Core3.0 配置Configuration

准备.NET core和.NET项目配置上有了很大的改变&#xff0c;支持的也更加丰富了比如命令行&#xff0c;环境变量&#xff0c;内存中.NET对象&#xff0c;设置文件等等。.NET项目我们常常把配置信息放到webConfig 或者appConfig中。配置相关的源码https://github.com/aspnet/Exte…

Python os.makedirs try 以及 raise

转自&#xff1a;http://bookshadow.com/weblog/2014/10/02/python-mkdir-p/ http://blog.csdn.net/mr_jj_lian/article/details/6786052 mkdir为Linux操作系统中的创建目录命令&#xff0c;使用mkdir -p指令可以自动创建目标目录路径中尚不存在的上级目录&#xff08;Window…

asp.net core 3.0 中使用 swagger

asp.net core 3.0 中使用 swaggerIntro上次更新了 asp.net core 3.0 简单的记录了一下 swagger 的使用&#xff0c;那个项目的 api 比较简单&#xff0c;都是匿名接口不涉及到认证以及 api 版本控制&#xff0c;最近把另外一个 api 项目升级到了 3.0&#xff0c;还是遇到了一些…

由微软100题“求和不用for while”引出的static类成员的知识

转自&#xff1a;http://www.cnblogs.com/gysm/archive/2011/09/16/2179277.html C类中谈到static,我们可以在类中定义static成员&#xff0c;static成员函数&#xff01;Cprimer里面讲过&#xff1a;static成员它不像普通的数据成员&#xff0c;static数据成员独立于该类的任意…

MCN是啥?了解一下这5个互联网热词

骗子刷量&#xff0c;黑吃黑半斤八两前几天一件事火爆了互联网圈&#xff0c;一场搞笑的骗局&#xff0c;一场蜂群传媒导演的“僵尸舞台剧”&#xff1a;一条一夜爆红的视频 流量却为0&#xff01;。一个电商商家卖产品有投放需求&#xff0c;找到了微博上一家 MCN 机构的一个女…

Matlab出现On Startup: Error using eval undefined function 'workspacefunc' for input arguments of type

按照提示 Warning: MATLAB did not appear to successfully set the search path. To recover for this session of MATLAB, type "restoredefaultpath;matlabrc". To find out how to avoid this warning the next time you start MATLAB, type "docsearch pr…

为什么我不建议你去外包公司?

前言在我离开上家公司之前&#xff0c;我的直属领导找我聊了一番。除了问候我有没有找好下家之外&#xff0c;还千叮咛万嘱咐我千万不要去外包公司&#xff0c;否则会在简历上留下无法磨灭的污点。当时的我对于外包公司的了解并不深&#xff0c;只是道听途说外包公司很坑&#…

x 的平方根

题目描述 实现 int sqrt(int x) 函数。 计算并返回 x 的平方根&#xff0c;其中 x 是非负整数。 由于返回类型是整数&#xff0c;结果只保留整数的部分&#xff0c;小数部分将被舍去。 示例 1: 输入: 4 输出: 2示例 2: 输入: 8 输出: 2 说明: 8 的平方根是 2.82842..., 由…

Caffe编译代码的时候报各种未定义未声明

自己装的CUDNN是一个版本&#xff0c;而运行别人的code时可能人家对应CUDNN的另一个版本&#xff0c;此时需要修改关键字来兼容版本&#xff0c;参考 1. https://github.com/BVLC/caffe/issues/1792 https://github.com/BVLC/caffe/pull/1739 https://github.com/BVLC/ca…

友浩达优选上新,原生态农产品,买得安心,吃得放心

大闸蟹还在热卖&#xff0c;需要的同学可以访问 各位一直支持队长的朋友们友浩达优选上新了本着为大家推荐好东西的想法商城里上架的商品都是队长亲自挑选有质量保证的口碑好商品这次&#xff0c;来看看队长又给大家带了哪些好东西本次上新全是各地优选原生态农产品食品优质、安…

判别学习与生成学习的区别

参照http://blog.csdn.net/daijiguo/article/details/52218207 比如二类分类问题&#xff0c;不管是感知器算法还是逻辑斯蒂回归算法&#xff0c;都是在解空间中寻找一条直线从而把两种类别的样例分开&#xff0c;对于新的样例只要判断在直线的哪一侧即可&#xff1b;这种直接对…

树莓派4上跑 .NET Core 3.0,这次,真·64位!

导语前不久我写了一篇《Gentoo由于 Windows 10 IoT Core &#xff08;以及上面的UWP们&#xff09;暴尸荒野而苟且偷生使用 Linux 的我&#xff0c;已经彻底开荤了。最近我发现有个叫 Gentoo 的 Linux 系统&#xff0c;支持树莓派4的64位CPU。项目地址&#xff1a;https://gith…

微软100题第20题

http://blog.csdn.net/zwb8848happy/article/details/7340634 输入一个表示整数的字符串&#xff0c;把该字符串转换成整数并输出 //Analysis: //1. Whether it is a negative number //2. Whether there exist other characters that do not represent numbers //#includ…

asp.net core 使用 AccessControlHelper 控制访问权限

asp.net core 使用 AccessControlHelper 控制访问权限Intro由于项目需要&#xff0c;需要在基于 asp.net mvc 的 Web 项目框架中做权限的控制&#xff0c;于是才有了这个权限控制组件&#xff0c;最初只是支持 netframework&#xff0c;后来 dotnetcore 2.0 发布了之后添加了对…