免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2041 | 回复: 8
打印 上一主题 下一主题

【请问】关于字符串指针和字符数组的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-12-13 16:13 |只看该作者 |倒序浏览
今天在编程时发现这样一个现象
char str1[]="abcd";
char str2[]="efgh";
*str1=*str2;
这个操作是合法的,结果也是正确的;

但是如果用字符串指针声明:
char *str1="abcd";
char *str2="efgh";
*str1=*str2;
运行时会出现内存错误

编译的平台:gcc 3.2.2 以及dev-c++都试验过

比较疑惑,感谢大家的指教^^

论坛徽章:
0
2 [报告]
发表于 2008-12-13 19:10 |只看该作者
简单一点说, “abc”是const char *型的,数据放在只读的内存区。
而char[]在栈,可写。

评分

参与人数 1可用积分 +1 收起 理由
samon_fu + 1 我很赞同

查看全部评分

论坛徽章:
0
3 [报告]
发表于 2008-12-13 19:14 |只看该作者
这个在《c专家编程》上面好像是说的未定义呀~

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
4 [报告]
发表于 2008-12-13 20:18 |只看该作者
今天在编程时发现这样一个现象
char str1[]="abcd";
char str2[]="efgh";
*str1=*str2;
这个操作是合法的,结果也是正确的;

这两个字符串都是保存在栈上,可以修改其中的内容。其中,*str1=*str2相当于把str2字符串的第一个字符'e'赋给了str1的第一个字符,因此,str1就变成了"ebcd"
但是如果用字符串指针声明:
char *str1="abcd";
char *str2="efgh";
*str1=*str2;
运行时会出现内存错误

编译的平台:gcc 3.2.2 以及dev-c++都试验过

以上两个字符串都是存在于静态内存区域。对于该区域可以进行读操作,但是赋值的行为是不确定的。也就是成功与否未定义,不同的编译器可能结果不一样。
所以,不要进行这样的操作,因为你不知道这样操作的确定性结果。

评分

参与人数 1可用积分 +1 收起 理由
samon_fu + 1 我很赞同

查看全部评分

论坛徽章:
0
5 [报告]
发表于 2008-12-13 21:38 |只看该作者
高人的见解!

论坛徽章:
0
6 [报告]
发表于 2008-12-13 21:47 |只看该作者
原帖由 Fixend 于 2008-12-13 19:10 发表
简单一点说, “abc”是const char *型的,数据放在只读的内存区。
而char[]在栈,可写。

大哥,你搞笑呢

论坛徽章:
0
7 [报告]
发表于 2008-12-13 22:20 |只看该作者
原帖由 Fixend 于 2008-12-13 19:10 发表
简单一点说, “abc”是const char *型的,数据放在只读的内存区。
而char[]在栈,可写。

我为刚才的发帖感到脸红~~,你是对的,

        char str1[]="abcd";
        char str2[]="efgh";
        *str1=*str2;


的汇编代码是:
        .file   "2x.c"
        .section        .rodata
.LC0:
        .string "abcd"
.LC1:
        .string "efgh"
        .text
.globl main
        .type   main, @function
main:
        leal    4(%esp), %ecx
        andl    $-16, %esp
        pushl   -4(%ecx)
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %ecx
        subl    $16, %esp
        #put .LC0 in -9(%ebp) to -5(%ebp)
        movl    .LC0, %eax
        movl    %eax, -9(%ebp)
        movzbl  .LC0+4, %eax
        movb    %al, -5(%ebp)
        #put .LC1 in -14(%ebp) to -10(%ebp)
        movl    .LC1, %eax
        movl    %eax, -14(%ebp)
        movzbl  .LC1+4, %eax
        movb    %al, -10(%ebp)
        #*str1 = *str2
        #not arrange address ,but arrange the first char;
        movzbl  -14(%ebp), %eax
        movb    %al, -9(%ebp)
        # all done
        addl    $16, %esp
        popl    %ecx
        popl    %ebp
        leal    -4(%ecx), %esp
        ret
        .size   main, .-main
        .ident  "GCC: (GNU) 4.2.3 (Debian 4.2.3-5)"
        .section        .note.GNU-stack,"",@progbits



        char *str1="abcd";
        char *str2="efgh";
        *str1=*str2;

的汇编代码如下:
        .file   "3x.c"
        .section        .rodata
.LC0:
        .string "abcd"
.LC1:
        .string "efgh"
        .text
.globl main
        .type   main, @function
main:
        leal    4(%esp), %ecx
        andl    $-16, %esp
        pushl   -4(%ecx)
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %ecx
        subl    $16, %esp
        movl    $.LC0, -12(%ebp)
        movl    $.LC1, -8(%ebp)
        movl    -8(%ebp), %eax
        movzbl  (%eax), %edx
        movl    -12(%ebp), %eax
        movb    %dl, (%eax)
        addl    $16, %esp
        popl    %ecx
        popl    %ebp
        leal    -4(%ecx), %esp
        ret
        .size   main, .-main
        .ident  "GCC: (GNU) 4.2.3 (Debian 4.2.3-5)"
        .section        .note.GNU-stack,"",@progbits



声明为指针的时候,在栈上保存的是str的存储地址,而str是声明在.rodata区的,

所以最后
                movl    -12(%ebp), %eax
                movb    %dl, (%eax)
相当于尝试把str2的首字符写入 .rodata区,所以就SIGSEGV了,

而声明为char []的时候,其实就是把字符在栈上操作,因此能正常执行,
虽然这种操作没啥意义~~

评分

参与人数 1可用积分 +3 信誉积分 +2 收起 理由
samon_fu + 3 + 2 我很赞同,坦诚交流

查看全部评分

论坛徽章:
0
8 [报告]
发表于 2008-12-13 22:20 |只看该作者
原帖由 Godbach 于 2008-12-13 20:18 发表

这两个字符串都是保存在栈上,可以修改其中的内容。其中,*str1=*str2相当于把str2字符串的第一个字符'e'赋给了str1的第一个字符,因此,str1就变成了"ebcd"

以上两个字符串都是存在于静态内存区域。对于该 ...





赞成!!

论坛徽章:
0
9 [报告]
发表于 2008-12-15 22:45 |只看该作者

回复 #1 lqseu 的帖子

非常感谢大家^^
懂了
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP