What's wrong with this example with string literal?











up vote
2
down vote

favorite












I'm reading an answer from this site which says the following is undefined



char *fubar = "hello world";
*fubar++; // SQUARELY UNDEFINED BEHAVIOUR!


but isn't that fubar++ is done first, which means moving the pointer to e, and *() is then done, which means extract the e out. I know this is supposed to be asked on chat (I'm a kind person) but no one is there so I ask here to attract notice.










share|improve this question




















  • 1




    Do you want to increment the address or the content, for content: (*fubar)++; For the address fubar++;
    – SPlatten
    yesterday








  • 1




    @SPlatten: I want neither, I just want to know whether it would lead to undefined behaviour as the answer said...
    – ptr_user7813604
    yesterday






  • 1




    You have no assignment so there is no point in the '*'.
    – SPlatten
    yesterday






  • 1




    Oops. I was not aware about this. ;-)
    – Scheff
    yesterday






  • 1




    Lesson learned: adhere to the rule of never mixing ++ with other operators in the same expression. It is a bad thing to do for multiple reasons: readability, maintainability, potentially undefined behavior,
    – Lundin
    yesterday

















up vote
2
down vote

favorite












I'm reading an answer from this site which says the following is undefined



char *fubar = "hello world";
*fubar++; // SQUARELY UNDEFINED BEHAVIOUR!


but isn't that fubar++ is done first, which means moving the pointer to e, and *() is then done, which means extract the e out. I know this is supposed to be asked on chat (I'm a kind person) but no one is there so I ask here to attract notice.










share|improve this question




















  • 1




    Do you want to increment the address or the content, for content: (*fubar)++; For the address fubar++;
    – SPlatten
    yesterday








  • 1




    @SPlatten: I want neither, I just want to know whether it would lead to undefined behaviour as the answer said...
    – ptr_user7813604
    yesterday






  • 1




    You have no assignment so there is no point in the '*'.
    – SPlatten
    yesterday






  • 1




    Oops. I was not aware about this. ;-)
    – Scheff
    yesterday






  • 1




    Lesson learned: adhere to the rule of never mixing ++ with other operators in the same expression. It is a bad thing to do for multiple reasons: readability, maintainability, potentially undefined behavior,
    – Lundin
    yesterday















up vote
2
down vote

favorite









up vote
2
down vote

favorite











I'm reading an answer from this site which says the following is undefined



char *fubar = "hello world";
*fubar++; // SQUARELY UNDEFINED BEHAVIOUR!


but isn't that fubar++ is done first, which means moving the pointer to e, and *() is then done, which means extract the e out. I know this is supposed to be asked on chat (I'm a kind person) but no one is there so I ask here to attract notice.










share|improve this question















I'm reading an answer from this site which says the following is undefined



char *fubar = "hello world";
*fubar++; // SQUARELY UNDEFINED BEHAVIOUR!


but isn't that fubar++ is done first, which means moving the pointer to e, and *() is then done, which means extract the e out. I know this is supposed to be asked on chat (I'm a kind person) but no one is there so I ask here to attract notice.







c string increment






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 5 hours ago

























asked yesterday









ptr_user7813604

371118




371118








  • 1




    Do you want to increment the address or the content, for content: (*fubar)++; For the address fubar++;
    – SPlatten
    yesterday








  • 1




    @SPlatten: I want neither, I just want to know whether it would lead to undefined behaviour as the answer said...
    – ptr_user7813604
    yesterday






  • 1




    You have no assignment so there is no point in the '*'.
    – SPlatten
    yesterday






  • 1




    Oops. I was not aware about this. ;-)
    – Scheff
    yesterday






  • 1




    Lesson learned: adhere to the rule of never mixing ++ with other operators in the same expression. It is a bad thing to do for multiple reasons: readability, maintainability, potentially undefined behavior,
    – Lundin
    yesterday
















  • 1




    Do you want to increment the address or the content, for content: (*fubar)++; For the address fubar++;
    – SPlatten
    yesterday








  • 1




    @SPlatten: I want neither, I just want to know whether it would lead to undefined behaviour as the answer said...
    – ptr_user7813604
    yesterday






  • 1




    You have no assignment so there is no point in the '*'.
    – SPlatten
    yesterday






  • 1




    Oops. I was not aware about this. ;-)
    – Scheff
    yesterday






  • 1




    Lesson learned: adhere to the rule of never mixing ++ with other operators in the same expression. It is a bad thing to do for multiple reasons: readability, maintainability, potentially undefined behavior,
    – Lundin
    yesterday










1




1




Do you want to increment the address or the content, for content: (*fubar)++; For the address fubar++;
– SPlatten
yesterday






Do you want to increment the address or the content, for content: (*fubar)++; For the address fubar++;
– SPlatten
yesterday






1




1




@SPlatten: I want neither, I just want to know whether it would lead to undefined behaviour as the answer said...
– ptr_user7813604
yesterday




@SPlatten: I want neither, I just want to know whether it would lead to undefined behaviour as the answer said...
– ptr_user7813604
yesterday




1




1




You have no assignment so there is no point in the '*'.
– SPlatten
yesterday




You have no assignment so there is no point in the '*'.
– SPlatten
yesterday




1




1




Oops. I was not aware about this. ;-)
– Scheff
yesterday




Oops. I was not aware about this. ;-)
– Scheff
yesterday




1




1




Lesson learned: adhere to the rule of never mixing ++ with other operators in the same expression. It is a bad thing to do for multiple reasons: readability, maintainability, potentially undefined behavior,
– Lundin
yesterday






Lesson learned: adhere to the rule of never mixing ++ with other operators in the same expression. It is a bad thing to do for multiple reasons: readability, maintainability, potentially undefined behavior,
– Lundin
yesterday














2 Answers
2






active

oldest

votes

















up vote
6
down vote













The location of the ++ is the key: If it's a suffix (like in this case) then the increment happens after.



Also due to operator precedence you increment the pointer.



So what happens is that the pointer fubar is dereference (resulting in 'h' which is then ignored), and then the pointer variable fubar is incremented to point to the 'e'.



In short: *fubar++ is fine and valid.



If it was (*fubar)++ then it would be undefined behavior, since then it would attempt to increase the first characters of the string. And literal strings in C are arrays of read-only characters, so attempting to modify a character in a literal string would be undefined behavior.





The expression *fubar++ is essentially equal to



char *temporary_variable = fubar;
fubar = fubar + 1;
*temporary_variable; // the result of the whole expression





share|improve this answer



















  • 1




    but wait ++(postfix) has the highest precedence while * not...
    – ptr_user7813604
    yesterday








  • 1




    @ptr_user7813604 *fubar++ is equal to *(fubar++). That is also explained in the answer. Note that since it is a postfix operator the pointer is dereferenced before the increment and then the pointer is incremented.
    – Osiris
    yesterday








  • 1




    @Osiris: but he says after or what's the truth...
    – ptr_user7813604
    yesterday






  • 1




    @ptr_user7813604, ++(postfix) is meaningless and means nothing since you have no additional operand in the brackets.
    – SPlatten
    yesterday






  • 1




    *fubar++ is equal to *(fubar++) which is (mostly) equal to *fubar; fubar++;.
    – Osiris
    yesterday


















up vote
5
down vote













The code shown is clearly not undefined behaviour, since *fubar++ is somewhat equal to char result; (result = *fubar, fubar++, result), i.e. it increments the pointer, and not the dereferenced value, and the result of the expression is the (dereferenced) value *fubar before the pointer got incremented. *fubar++ actually gives you the character value to which fubar originally points, but you simply make no use of this "result" and ignore it.



Note, however, that the following code does introduce undefined behaviour:



char *fubar = "hello world";
(*fubar)++;


This is because this increments the value to which fubar points and thereby manipulates a string literal -> undefined behaviour.



When replacing the string literal with an character array, then everything is OK again:



int main() {

char test = "hello world";
char* fubar = test;
(*fubar)++;
printf("%sn",fubar);
}


Output:



iello world





share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














     

    draft saved


    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53409238%2fwhats-wrong-with-this-example-with-string-literal%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    6
    down vote













    The location of the ++ is the key: If it's a suffix (like in this case) then the increment happens after.



    Also due to operator precedence you increment the pointer.



    So what happens is that the pointer fubar is dereference (resulting in 'h' which is then ignored), and then the pointer variable fubar is incremented to point to the 'e'.



    In short: *fubar++ is fine and valid.



    If it was (*fubar)++ then it would be undefined behavior, since then it would attempt to increase the first characters of the string. And literal strings in C are arrays of read-only characters, so attempting to modify a character in a literal string would be undefined behavior.





    The expression *fubar++ is essentially equal to



    char *temporary_variable = fubar;
    fubar = fubar + 1;
    *temporary_variable; // the result of the whole expression





    share|improve this answer



















    • 1




      but wait ++(postfix) has the highest precedence while * not...
      – ptr_user7813604
      yesterday








    • 1




      @ptr_user7813604 *fubar++ is equal to *(fubar++). That is also explained in the answer. Note that since it is a postfix operator the pointer is dereferenced before the increment and then the pointer is incremented.
      – Osiris
      yesterday








    • 1




      @Osiris: but he says after or what's the truth...
      – ptr_user7813604
      yesterday






    • 1




      @ptr_user7813604, ++(postfix) is meaningless and means nothing since you have no additional operand in the brackets.
      – SPlatten
      yesterday






    • 1




      *fubar++ is equal to *(fubar++) which is (mostly) equal to *fubar; fubar++;.
      – Osiris
      yesterday















    up vote
    6
    down vote













    The location of the ++ is the key: If it's a suffix (like in this case) then the increment happens after.



    Also due to operator precedence you increment the pointer.



    So what happens is that the pointer fubar is dereference (resulting in 'h' which is then ignored), and then the pointer variable fubar is incremented to point to the 'e'.



    In short: *fubar++ is fine and valid.



    If it was (*fubar)++ then it would be undefined behavior, since then it would attempt to increase the first characters of the string. And literal strings in C are arrays of read-only characters, so attempting to modify a character in a literal string would be undefined behavior.





    The expression *fubar++ is essentially equal to



    char *temporary_variable = fubar;
    fubar = fubar + 1;
    *temporary_variable; // the result of the whole expression





    share|improve this answer



















    • 1




      but wait ++(postfix) has the highest precedence while * not...
      – ptr_user7813604
      yesterday








    • 1




      @ptr_user7813604 *fubar++ is equal to *(fubar++). That is also explained in the answer. Note that since it is a postfix operator the pointer is dereferenced before the increment and then the pointer is incremented.
      – Osiris
      yesterday








    • 1




      @Osiris: but he says after or what's the truth...
      – ptr_user7813604
      yesterday






    • 1




      @ptr_user7813604, ++(postfix) is meaningless and means nothing since you have no additional operand in the brackets.
      – SPlatten
      yesterday






    • 1




      *fubar++ is equal to *(fubar++) which is (mostly) equal to *fubar; fubar++;.
      – Osiris
      yesterday













    up vote
    6
    down vote










    up vote
    6
    down vote









    The location of the ++ is the key: If it's a suffix (like in this case) then the increment happens after.



    Also due to operator precedence you increment the pointer.



    So what happens is that the pointer fubar is dereference (resulting in 'h' which is then ignored), and then the pointer variable fubar is incremented to point to the 'e'.



    In short: *fubar++ is fine and valid.



    If it was (*fubar)++ then it would be undefined behavior, since then it would attempt to increase the first characters of the string. And literal strings in C are arrays of read-only characters, so attempting to modify a character in a literal string would be undefined behavior.





    The expression *fubar++ is essentially equal to



    char *temporary_variable = fubar;
    fubar = fubar + 1;
    *temporary_variable; // the result of the whole expression





    share|improve this answer














    The location of the ++ is the key: If it's a suffix (like in this case) then the increment happens after.



    Also due to operator precedence you increment the pointer.



    So what happens is that the pointer fubar is dereference (resulting in 'h' which is then ignored), and then the pointer variable fubar is incremented to point to the 'e'.



    In short: *fubar++ is fine and valid.



    If it was (*fubar)++ then it would be undefined behavior, since then it would attempt to increase the first characters of the string. And literal strings in C are arrays of read-only characters, so attempting to modify a character in a literal string would be undefined behavior.





    The expression *fubar++ is essentially equal to



    char *temporary_variable = fubar;
    fubar = fubar + 1;
    *temporary_variable; // the result of the whole expression






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited yesterday

























    answered yesterday









    Some programmer dude

    291k24241400




    291k24241400








    • 1




      but wait ++(postfix) has the highest precedence while * not...
      – ptr_user7813604
      yesterday








    • 1




      @ptr_user7813604 *fubar++ is equal to *(fubar++). That is also explained in the answer. Note that since it is a postfix operator the pointer is dereferenced before the increment and then the pointer is incremented.
      – Osiris
      yesterday








    • 1




      @Osiris: but he says after or what's the truth...
      – ptr_user7813604
      yesterday






    • 1




      @ptr_user7813604, ++(postfix) is meaningless and means nothing since you have no additional operand in the brackets.
      – SPlatten
      yesterday






    • 1




      *fubar++ is equal to *(fubar++) which is (mostly) equal to *fubar; fubar++;.
      – Osiris
      yesterday














    • 1




      but wait ++(postfix) has the highest precedence while * not...
      – ptr_user7813604
      yesterday








    • 1




      @ptr_user7813604 *fubar++ is equal to *(fubar++). That is also explained in the answer. Note that since it is a postfix operator the pointer is dereferenced before the increment and then the pointer is incremented.
      – Osiris
      yesterday








    • 1




      @Osiris: but he says after or what's the truth...
      – ptr_user7813604
      yesterday






    • 1




      @ptr_user7813604, ++(postfix) is meaningless and means nothing since you have no additional operand in the brackets.
      – SPlatten
      yesterday






    • 1




      *fubar++ is equal to *(fubar++) which is (mostly) equal to *fubar; fubar++;.
      – Osiris
      yesterday








    1




    1




    but wait ++(postfix) has the highest precedence while * not...
    – ptr_user7813604
    yesterday






    but wait ++(postfix) has the highest precedence while * not...
    – ptr_user7813604
    yesterday






    1




    1




    @ptr_user7813604 *fubar++ is equal to *(fubar++). That is also explained in the answer. Note that since it is a postfix operator the pointer is dereferenced before the increment and then the pointer is incremented.
    – Osiris
    yesterday






    @ptr_user7813604 *fubar++ is equal to *(fubar++). That is also explained in the answer. Note that since it is a postfix operator the pointer is dereferenced before the increment and then the pointer is incremented.
    – Osiris
    yesterday






    1




    1




    @Osiris: but he says after or what's the truth...
    – ptr_user7813604
    yesterday




    @Osiris: but he says after or what's the truth...
    – ptr_user7813604
    yesterday




    1




    1




    @ptr_user7813604, ++(postfix) is meaningless and means nothing since you have no additional operand in the brackets.
    – SPlatten
    yesterday




    @ptr_user7813604, ++(postfix) is meaningless and means nothing since you have no additional operand in the brackets.
    – SPlatten
    yesterday




    1




    1




    *fubar++ is equal to *(fubar++) which is (mostly) equal to *fubar; fubar++;.
    – Osiris
    yesterday




    *fubar++ is equal to *(fubar++) which is (mostly) equal to *fubar; fubar++;.
    – Osiris
    yesterday












    up vote
    5
    down vote













    The code shown is clearly not undefined behaviour, since *fubar++ is somewhat equal to char result; (result = *fubar, fubar++, result), i.e. it increments the pointer, and not the dereferenced value, and the result of the expression is the (dereferenced) value *fubar before the pointer got incremented. *fubar++ actually gives you the character value to which fubar originally points, but you simply make no use of this "result" and ignore it.



    Note, however, that the following code does introduce undefined behaviour:



    char *fubar = "hello world";
    (*fubar)++;


    This is because this increments the value to which fubar points and thereby manipulates a string literal -> undefined behaviour.



    When replacing the string literal with an character array, then everything is OK again:



    int main() {

    char test = "hello world";
    char* fubar = test;
    (*fubar)++;
    printf("%sn",fubar);
    }


    Output:



    iello world





    share|improve this answer



























      up vote
      5
      down vote













      The code shown is clearly not undefined behaviour, since *fubar++ is somewhat equal to char result; (result = *fubar, fubar++, result), i.e. it increments the pointer, and not the dereferenced value, and the result of the expression is the (dereferenced) value *fubar before the pointer got incremented. *fubar++ actually gives you the character value to which fubar originally points, but you simply make no use of this "result" and ignore it.



      Note, however, that the following code does introduce undefined behaviour:



      char *fubar = "hello world";
      (*fubar)++;


      This is because this increments the value to which fubar points and thereby manipulates a string literal -> undefined behaviour.



      When replacing the string literal with an character array, then everything is OK again:



      int main() {

      char test = "hello world";
      char* fubar = test;
      (*fubar)++;
      printf("%sn",fubar);
      }


      Output:



      iello world





      share|improve this answer

























        up vote
        5
        down vote










        up vote
        5
        down vote









        The code shown is clearly not undefined behaviour, since *fubar++ is somewhat equal to char result; (result = *fubar, fubar++, result), i.e. it increments the pointer, and not the dereferenced value, and the result of the expression is the (dereferenced) value *fubar before the pointer got incremented. *fubar++ actually gives you the character value to which fubar originally points, but you simply make no use of this "result" and ignore it.



        Note, however, that the following code does introduce undefined behaviour:



        char *fubar = "hello world";
        (*fubar)++;


        This is because this increments the value to which fubar points and thereby manipulates a string literal -> undefined behaviour.



        When replacing the string literal with an character array, then everything is OK again:



        int main() {

        char test = "hello world";
        char* fubar = test;
        (*fubar)++;
        printf("%sn",fubar);
        }


        Output:



        iello world





        share|improve this answer














        The code shown is clearly not undefined behaviour, since *fubar++ is somewhat equal to char result; (result = *fubar, fubar++, result), i.e. it increments the pointer, and not the dereferenced value, and the result of the expression is the (dereferenced) value *fubar before the pointer got incremented. *fubar++ actually gives you the character value to which fubar originally points, but you simply make no use of this "result" and ignore it.



        Note, however, that the following code does introduce undefined behaviour:



        char *fubar = "hello world";
        (*fubar)++;


        This is because this increments the value to which fubar points and thereby manipulates a string literal -> undefined behaviour.



        When replacing the string literal with an character array, then everything is OK again:



        int main() {

        char test = "hello world";
        char* fubar = test;
        (*fubar)++;
        printf("%sn",fubar);
        }


        Output:



        iello world






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited yesterday

























        answered yesterday









        Stephan Lechner

        24.4k21738




        24.4k21738






























             

            draft saved


            draft discarded



















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53409238%2fwhats-wrong-with-this-example-with-string-literal%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks

            Calculate evaluation metrics using cross_val_predict sklearn

            Insert data from modal to MySQL (multiple modal on website)