• Why am I able to change the contents of const char *ptr?


    http://stackoverflow.com/questions/3228664/why-am-i-able-to-change-the-contents-of-const-char-ptr

    I passed a pointer ptr to a function whose prototype takes it as const.

    foo( const char  *str );

    Which according to my understanding means that it will not be able to change the contents of ptrpassed. Like in the case of foo( const int i ). If foo() tries to chnage the value of i, compiler gives error. 
    But here I see that it can change the contents of ptr easily. 
    Please have a look at the following code

    foo( const char  *str )
    {
            strcpy( str, "ABC" ) ;
            printf( "%s(): %s
    " , __func__ , str ) ;
    }
    
    main()
    {
            char ptr[  ] = "Its just to fill the space" ;
            printf( "%s(): %s
    " , __func__ , ptr ) ;
            foo( const ptr ) ;
            printf( "%s(): %s
    " , __func__ , ptr ) ;
            return;
    }

    On compilation, I only get a warning, no error:

    warning: passing argument 1 of ‘strcpy’ discards qualifiers from pointer target type

    and when I run it, I get an output instead of Segmentation Fault

    main(): Its just to fill the space
    foo(): ABC
    main(): ABC

    Now, my questions is
    1- What does const char *str in prototype actually means? 
    Does this mean that function cannot change the contents of str? If that is so then how come the above program changes the value?
    2- How can I make sure that the contents of the pointer I have passed will not be changed?

    From "contents of the pointer" in the above stated question, I mean "contents of the memory pointed at by the pointer", not "address contained in the pointer".

    Edit

    Most replies say that this is because of strcpy and C implicit type conversion. But now I tried this

    foo( const char  *str )
    {
            str = "Tim" ;
    //      strcpy( str, "ABC" ) ;
            printf( "%s(): %s
    " , __func__ , str ) ;
    }

    This time the output is, with no warning from compiler

    main(): Its just to fill the space
    foo(): Tim
    main(): Its just to fill the space

    So apparently, memory pointed to by str is changed to the memory location containing "Tim" while its in foo(). Although I didn't use strcpy() this time.
    Is not const supposed to stop this? or my understanding is wrong?

    To me it seems that even with const, I can change the memory reference and the contents of memory reference too. Then what is the use?

    Can you give me an example where complier will give me error that I am trying to change a const pointer?

    Thanks to all of you for your time and effort.

    Your understanding is correct, const char* is a contract that means you can't change memory through this particular pointer.

    The problem is that C is very lax with type conversions. strcpy takes a pointer to non-const char, and it is implicitly converted from const char* to char* (as compiler helpfully tells you). You could as easily pass an integer instead of pointer. As a result, your function can't change content pointed by ptr, but strcpy can, because it sees a non-const pointer. You don't get a crash, because in your case, the pointer points to an actual buffer of sufficient size, not a read-only string literal.

    To avoid this, look for compiler warnings, or compile, for example, with -Wall -Werror (if you are using gcc).

    This behaviour is specific to C. C++, for example, does not allow that, and requires an explicit cast (C-style cast or a const_cast) to strip const qualifier, as you would reasonably expect.

    Answer to the extended question

    You are assigning a string literal into a non-const char, which, unfortunately, is legal in C and even C++! It is implicitly converted to char*, even though writing through this pointer will now result in undefined behaviour. It is a deprecated feature, and only C++0x so far does not allow this to happen.

    With that said, In order to stop changing the pointer itself, you have to declare it as const pointer to char (char *const). Or, if you want to make it that both the contents pointed by it and the pointer itself don't change, use a const pointer to const char (const char * const).

    Examples:

    void foo (
            char *a,
            const char *b,
            char *const c,
            const char *const d)
        {
        char buf[10];
        a = buf; /* OK, changing the pointer */
        *a = 'a'; /* OK, changing contents pointed by pointer */
    
        b = buf; /* OK, changing the pointer */
        *b = 'b'; /* error, changing contents pointed by pointer */
    
        c = buf; /* error, changing pointer */
        *c = 'c'; /* OK, changing contents pointed by pointer */
    
        d = buf; /* error, changing pointer */
        *d = 'd'; /* error, changing contents pointed by pointer */
    }

    For all error lines GCC gives me "error: assignment of read-only location".

  • 相关阅读:
    微信小程序支付完整示例
    二分查找,冒泡排序, 快速排序
    JQuery放大镜效果
    js瀑布流
    linux安装字体
    使用phantomjs截图【php】
    安装supervisor
    mysql报错:BIGINT UNSIGNED value is out of range
    curl https报错: curl: (35) SSL connect error
    给www用户添加登录权限
  • 原文地址:https://www.cnblogs.com/diegodu/p/4481125.html
Copyright © 2020-2023  润新知