teky 的 blog
在vck中学习,在vck中进步~
<2005年12月>
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567
公告

留言簿(11)

随笔档案

文章分类

文章档案

相册

Windows Mobile

我的好友

朋友创业,其路漫漫

搜索

最新评论

阅读排行榜

评论排行榜

 
VC知识库BLOG   首页  新随笔  联系  聚合  登录 
  随笔-30 文章-17 评论-94 Trackbacks-4

看完后.明白**讲的为什么char** 不能自动转化为 const char**,(原文)但对我影响最深的是下面的话:

==================================================================
char *p="abc" 能不能编译通过要看你使用的编译器。鉴于大量遗留代码的存在,大部分编译器允许其通过,或者给个警告。当然,程序员自己必须保证绝不去修改其值。

程序员不应该在代码中出现*p='A'这样的语句。这是当初约定好了的:编译器允许char *p="abc"通过,而程序员保证不去修改它。
b. *p='A'编译时应该允许通过,因为单就这条语句而言,它完全合法。
c. 运行时*p='A'能不能通过要看实际的运行环境,包括你使用的操作系统、编译器、编译器选项 等等,一句话,其运行结果由不得你,且不应该由你去关心,因为这种行为本身已经违反约定了。
==================================================================

工作关系吧,用CString 和string用的太多了,很少这样定义字符串 char *p=“abcde“了
匝一看,还不适应,:(,渐渐的回想才想起一些来(哎,还是太生疏,赶快写下来,以后别忘了)

这样定义的字符串char *p=“abcde“ ; char *p1=“123445667“;

正如上面提到的是不能再 *p='A',运行的时候会出错,同样,strcpy(p,p1)也会出错哟,

"abcde"字符串可以看做是个常量字符串了,是不能被修改的,

但如果 char p[]=“abcde“ 这样定义,就没有问题,你可以修改*p='A',只要不越界就ok.

并且发现这样两种定义
char *p=“abcde“

char p[]=“abcde“

在运行的时候,p指向的地址也不是一样的,可见char *p=“abcde“还是有特殊的处理 :),具体怎么处理就不知道了,高手请指教:)


随着测试,又发现个问题,可能是个老问题了吧:


int main(int argc, char* argv[])

 int t[10];
 char p1[7]="123456";
 const char *p2="1234567890123213123";
 
 int len(0);
 
  //*p1='C';  err

 len=strlen(p1);
 printf("%d\n",len);
 
 strcpy(p1,p2);   ///??????????
 
 printf("%s\n",p1);
 
 len=strlen(p1);
 
 printf("%d\n",len);
 return 0;
}

我定义的是7个字符数组, 但用strcpy把p2拷到p1中,p1是放不下的,但程序却正常执行,warning ,err都没有,运行也正常?


输出

6
1234567890123213123
19

应该是使用内存越界了阿??怎么会正常运行呢?

难道对于内存越界的使用,运气好才崩溃表现出来,运气不好就正常运行??

posted on 2005-12-29 19:37 teky 阅读(2203) 评论(15)  编辑 收藏
Comments
  • # re: 看了 **的 想到的
    lostpencil
    Posted @ 2005-12-29 20:14
    感觉:
    char *p="abcd";
    *p='a';
    是一个执行期的毛病,编译期不违背任何原则吧,和语言的设计有关.
    至于后面的东西,本来编译器都允许指针访问越界的,这个和运气无关,这个是语言的蹩脚特色吧,灵活高效当然要放弃一些东西.不在于安全不安全,而在于值得不值得.
    有几本c的书对这个讲的比较详细,可惜我都记混了,不知道是哪一本了,:)
    新年快乐!
  • # re: 看了 **的 想到的
    lostpencil
    Posted @ 2005-12-29 20:23
    谁叫你明明是常量不加const呢,呵呵
  • # re: 一出门就看到一个错误
    清风雨
    Posted @ 2005-12-30 09:03
    一直,犹豫着,会是有所内容呢,还是只是就事论事?
    发现,有两个评论,那么,我想肯定是有内容了。

    结果一看开头就有一个错误。所以,也就不继续往下看了。希望作者还要先弄清楚哦!—— 可不是表面那么回事。
  • # re: 看了 **的 想到的
    teky
    Posted @ 2005-12-30 09:11
    清风雨,我就是不太清楚,才贴上来问问,有什么问题,麻烦你指导一下:)
  • # re: 看了 **的 想到的
    小明
    Posted @ 2005-12-30 10:03
    char *p="abcde"

    char p[]="abcde"
    有很大不同的

    简单来说,"abcde"是分配在程序常量堆的一个变量
    char *p="abcde"
    是声明一个指针,指向了那个常量
    char p[]="abcde"
    是声明在堆栈上的一个数组,它的内容拷贝那个常量

    举个例子来说
    char * foo()
    {
        char *p="abcde";
        return p;
    }
    是可以work的
    char * foo()
    {
        char p[]="abcde";
        return p;
    }
    就是不对的,函数执行完,这段内存就释放了

  • # re: 看了 **的 想到的
    小明
    Posted @ 2005-12-30 10:09
    还有你的strcpy为什么没有问题,是因为你声明了int t[10];

    进入函数后,堆栈是这样的
    p2
    p1[7]
    t[10]
    地址由低到高
    所以你strcpy超出的部分都到t[10]里面去了
    你要去掉这个,程序一定报错!

  • # re: 看了 **的 想到的
    teky
    Posted @ 2005-12-30 10:13
    to 小明,讲的很清楚了,谢谢
    再问一下
    char * foo() 

        char *p="abcde"; 
        return p; 


    这样分配的"abcde"在程序常量堆中,那启不就是个全局的了?在程序退出的时候它才释放?
  • # re: 看了 **的 想到的
    小明
    Posted @ 2005-12-30 10:18
    对,程序退出才释放。
  • # re: 看了 **的 想到的
    teky
    Posted @ 2005-12-30 10:18
    to 小明:
    一开始程序并没有定义t[10] ,strcpy越界并没有报错,

    后来,我发现这个问题以后,想看看p1,p2的地址怎么分配的,才加了个
    t[10] 试试,但还是没有找到原因,t,p1,p2的地址分配也没有看懂 :(
  • # re: 看了 **的 想到的
    周星星
    Posted @ 2005-12-30 10:19
    我定义的是7个字符数组, 但用strcpy把p2拷到p1中,p1是放不下的,但程序却正常执行,warning ,err都没有,运行也正常?
    --- 编译没错这很好理解,因为你这里没有任何一句有语法错误。
    运行时有没有错误就不是由你决定的喽。

    内存越界也很容易看出来,打印出 strcpy(p1,p2) 执行前后的 t 数组内容就可以看出来了。
    顺便说一下,这个错误很隐蔽的,因为它本身从现象上似乎没有错,但它却暗暗的修改了一个不相干的变量,出现这样的错误后,调试者一般只从 t 相关的语句上去寻找,当然是找不到。

    还有一种越界,但却没有运行时错误的情况,这是由内存对齐造成的,比如你想分配一个5字节的空间,系统有可能分配给你8个字节的空间,这时当你越界这5个字节,但仍在8个字节内的时候,一切都是正常的。这个错误更难发现。
  • # re: 看了 **的 想到的
    小明
    Posted @ 2005-12-30 10:22
    不会吧,去掉t[10]应该报错。你有没有测试阿?

    如果你还没有懂,看看我写的这篇文章
    http://www.cppblog.com/sandy/archive/2005/12/14/1745.html
  • # re: 看了 **的 想到的
    teky
    Posted @ 2005-12-30 10:31
    to 星星 谢谢,

    运行时有没有错误就不是由你决定的喽。

    和和,也就是看运气了?
  • # re: 看了 **的 想到的
    teky
    Posted @ 2005-12-30 10:32
    to 小明:

    去掉的确没有错误,我测试过的
    恩,我去看看 :)



  • # :)给你一个内存示意图
    周星星
    Posted @ 2005-12-30 10:34
    #include <cstdio>
    #include <cstring>
    int main( void )

     char t[2];
     char p[2];
    // 一种可能的内存分配(X代表因为字节对齐而留空的空间)
    // p[0] p[1] X X X X X X X X X X t[0] t[1] X X X X X X X X X X
     strcpy( p, "123456789ABCDEF" );
    // 拷贝后的内存值
    // p[0] p[1] X X X X X X X X X X t[0] t[1] X X X X X X X X X X
    //    1    2 3 4 5 6 7 8 9 A B C   D    E   F                   
     return 0;
    }
  • # re: 看了 **的 想到的
    suomynona
    Posted @ 2005-12-30 10:46
    提一个
    char* p="abc";
    "abc"==p; // 这个是true哦.
标题  
姓名  
主页
验证码 *
内容   
  登录  使用高级评论  Top
[使用Ctrl+Enter键可以直接提交]