C++字符串数组的越界问题

凤梨头头 2015-07-22 10:27:55
#include<iostream>
#include<string>
using namespace std;
int main()
{

char s[]="123456789";
char d[]="123";
strcpy(d,s);
cout<<d<<endl;
cout<<s<<endl;
return 0;
}

这段代码的输出是123456789,56789;
此处我不理解为什么d没有出现溢出呢,他不应该只能存在三个字符加一个空字符吗?可是此处他的第4个字符处不是空字符,而是字符4,为什么没有出错呢?
...全文
447 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
paschen 版主 2015-07-22
  • 打赏
  • 举报
回复
他确实越界了,只是看似正确,他把不属于他的地方给定了数据,这可能在某些时候才出现灾难,而通常这种错误一般很难发现,新版的VS都有strcpy_s来确保安全地复制
二班的码农 2015-07-22
  • 打赏
  • 举报
回复
引用 7 楼 u010810428 的回复:
[quote=引用 4 楼 ant2012 的回复:] 由于楼主你的字符串越界操作修改的是自己进程中的内存数据,而非其它进程内存数据,因此运行不会报错
我又细细考虑了你的说法,难道这种情况的越界是只在编译时期才会提示吗?运行阶段
char d[3]="12";
	strcpy(d,"123");
	cout<<d<<endl;
我尝试了这段代码,结果也没出错。[/quote] C++中越界操作在编译时期是不检测的,只有在运行中才能检测出,你上面的那段代码进行strcpy拷贝时,的确发生了越界,但并没有超出该进程中的内存地址空间,所以不会报错。最好不要这样操作,因为不同编译器对程序的优化方式不一样,同时,变量内存的分配也跟操作系统有关,你无法确定其是否会超出进程地址空间,而且会影响各变量数据的独立性
二班的码农 2015-07-22
  • 打赏
  • 举报
回复
引用 5 楼 u010810428 的回复:
[quote=引用 3 楼 ant2012 的回复:] 那是因为变量s的地址比变量d的地址高,且两个变量的地址空间是相邻的 当d的长度小于s时,在用strcpy时,由于d的大小为4个字节(加'\0'),函数只将s中的前4个字节拷入到s中,但由于函数没有检测到s中的'\0',还会继续将数据拷贝到d变量后面的地址空间中,而s变量的地址s = d + 4, 因此函数接着将剩下的“56789”拷入到s自己的内存空间中(从首地址开始),直到找到s中的'\0',结束拷贝。 当输出两个变量时,cout在输出字符串变量时,也是通过‘\0’来判定字符串的结尾,因此在输出d变量时,会将s中的变量的前面6个字节一块输出(”56789“加'\0'),加上d变量那部分,输出结果就成123456789,。同理,由于s中的第6个字节数据被改成‘\0’,所以输出s的结果是56789
我知道输出结果按道理应该是这样,我只是不理解d的字符串大小是4,他的第四位本应是‘\0’的,可是这里却是4,为什么没有提示越界错误[/quote] 由于你没有开始对d数组设定大小,编译器会根据右边的字符串常量来确定其大小,其大小为字符串长度加1(‘\0’),即初始化后,d[3] = '\0',在进行strcpy时,字符串挨个拷贝,当然把第4个字节拷贝成‘4'了
凤梨头头 2015-07-22
  • 打赏
  • 举报
回复
引用 4 楼 ant2012 的回复:
由于楼主你的字符串越界操作修改的是自己进程中的内存数据,而非其它进程内存数据,因此运行不会报错
我又细细考虑了你的说法,难道这种情况的越界是只在编译时期才会提示吗?运行阶段
char d[3]="12";
	strcpy(d,"123");
	cout<<d<<endl;
我尝试了这段代码,结果也没出错。
凤梨头头 2015-07-22
  • 打赏
  • 举报
回复
引用 4 楼 ant2012 的回复:
由于楼主你的字符串越界操作修改的是自己进程中的内存数据,而非其它进程内存数据,因此运行不会报错
额,菜鸟不太理解你说的意思,能再详细一点吗?谢谢!
凤梨头头 2015-07-22
  • 打赏
  • 举报
回复
引用 3 楼 ant2012 的回复:
那是因为变量s的地址比变量d的地址高,且两个变量的地址空间是相邻的 当d的长度小于s时,在用strcpy时,由于d的大小为4个字节(加'\0'),函数只将s中的前4个字节拷入到s中,但由于函数没有检测到s中的'\0',还会继续将数据拷贝到d变量后面的地址空间中,而s变量的地址s = d + 4, 因此函数接着将剩下的“56789”拷入到s自己的内存空间中(从首地址开始),直到找到s中的'\0',结束拷贝。 当输出两个变量时,cout在输出字符串变量时,也是通过‘\0’来判定字符串的结尾,因此在输出d变量时,会将s中的变量的前面6个字节一块输出(”56789“加'\0'),加上d变量那部分,输出结果就成123456789,。同理,由于s中的第6个字节数据被改成‘\0’,所以输出s的结果是56789
我知道输出结果按道理应该是这样,我只是不理解d的字符串大小是4,他的第四位本应是‘\0’的,可是这里却是4,为什么没有提示越界错误
二班的码农 2015-07-22
  • 打赏
  • 举报
回复
由于楼主你的字符串越界操作修改的是自己进程中的内存数据,而非其它进程内存数据,因此运行不会报错
二班的码农 2015-07-22
  • 打赏
  • 举报
回复
那是因为变量s的地址比变量d的地址高,且两个变量的地址空间是相邻的 当d的长度小于s时,在用strcpy时,由于d的大小为4个字节(加'\0'),函数只将s中的前4个字节拷入到s中,但由于函数没有检测到s中的'\0',还会继续将数据拷贝到d变量后面的地址空间中,而s变量的地址s = d + 4, 因此函数接着将剩下的“56789”拷入到s自己的内存空间中(从首地址开始),直到找到s中的'\0',结束拷贝。 当输出两个变量时,cout在输出字符串变量时,也是通过‘\0’来判定字符串的结尾,因此在输出d变量时,会将s中的变量的前面6个字节一块输出(”56789“加'\0'),加上d变量那部分,输出结果就成123456789,。同理,由于s中的第6个字节数据被改成‘\0’,所以输出s的结果是56789
赵4老师 2015-07-22
  • 打赏
  • 举报
回复
其实电脑开机后物理内存的每个字节都是可读写的,从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页,一页通常为4KB。
cobra_chen 2015-07-22
  • 打赏
  • 举报
回复
操作非法内存,什么情况都可能出现的。 也可能崩溃,也可能不崩溃。 这样写,可以确定的是其他数据被破坏了,不幸其他地方要用这段内存,那就悲剧了。
xiaohuh421 2015-07-22
  • 打赏
  • 举报
回复
C++程序在编译期和运行期都是不对数据越界做任何检查的. 只有当内存错误了, 才会通知程序崩溃. 楼主的内存操作是在栈中, 并且越界不多, 正好都是自己申请的临时变量内, 虽然程序没有报错, 但是执行效果已经不正确了. 实际上已经是错了. 如果你越界多一点, 比如char d[3]="12"; strcpy(d,"这里填充1000个字符"); // 填充多点, 即让越界更远. 影响了调用栈, 这时程序估计立马闪退或者崩溃. 还有就是new申请的堆空间, 越界一般都会造成崩溃, 提示堆被破坏.

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧