basic question from c pointer

Discussion in 'Programmer's Corner' started by ep.hobbyiest, Dec 27, 2015.

  1. ep.hobbyiest

    Thread Starter Member

    Aug 26, 2014
    91
    0
    Hi,
    i m confused in following question.

    Code (Text):
    1.  
    2. unsigned char *str="circuit";
    3. *(str) = 'k';
    4.  
    this code gives error. please i cant understand how it is giving error.
     
  2. Papabravo

    Expert

    Feb 24, 2006
    10,144
    1,791
    What are you trying to do and what is the error you are getting? A little bit of useful information goes a long way to getting an accurate and useable answer.
     
  3. WBahn

    Moderator

    Mar 31, 2012
    17,748
    4,796
    The problem is almost certainly because your compiler is making str a constant pointer, since it points to a string literal which is probably located somewhere within the body of the code itself.

    So when you try to change the value stored there, the compiler knows that you shouldn't be doing that (you are stepping into the black world of self-modifying code).
     
  4. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,887
    1,012

    You cannot create stings this way in C. You must allocate the space. You can do something like this:

    unsigned char buffer[] = "circuit";
    unsigned char *str = buffer;


    I highly suggest you read up on strings and pointers in C. This is one of the most difficult concepts for new C programmers to understand.
     
  5. WBahn

    Moderator

    Mar 31, 2012
    17,748
    4,796
    Oh, you can create them that way, but they are string literals and can't (shouldn't) be changed.

    For instance

    Code (C):
    1.  
    2. #include <stdio.h>
    3.  
    4. int main(void)
    5. {
    6.    unsigned char *str = "Hello World!";
    7.  
    8.    printf("%s\n", str);
    9.  
    10.    return 0;
    11. }
    12.  
    runs just fine. However,

    Code (C):
    1.  
    2. #include <stdio.h>
    3.  
    4. int main(void)
    5. {
    6.    unsigned char *str = "Hello World!";
    7.  
    8.    printf("%s\n", str);
    9.  
    10.    *str = 'J';
    11.    printf("%s\n", str);
    12.  
    13.    return 0;
    14. }
    15.  
    compiles and runs but throws a runtime error (using my compiler -- many compiler/OS combinations won't and will appear to work fine, but there are evil demons lurking in those waters).

    Using array notation, as Spinnaker suggests, has slightly different semantics. So

    Code (C):
    1.  
    2. #include <stdio.h>
    3.  
    4. int main(void)
    5. {
    6.    unsigned char str[] = "Hello World!";
    7.  
    8.    printf("%s\n", str);
    9.  
    10.    *str = 'J';
    11.    printf("%s\n", str);
    12.  
    13.    return 0;
    14. }
    15.  
    Works just fine. This is one of the few places where the subtle distinction between str[] and *str is important. Note that there's no need for a separate variable -- the name of the array IS a pointer to the first element of the array. However, it is a constant and so trying to change the address it points to can cause problems.
     
  6. ep.hobbyiest

    Thread Starter Member

    Aug 26, 2014
    91
    0
    Ok. Thanks every one.
    Means compiler treating string as constant. And i m trying to change the constant data field.
     
  7. WBahn

    Moderator

    Mar 31, 2012
    17,748
    4,796
    Possibly. It depends on how the problem is manifesting itself. If it won't compile, then this is the likely cause. If it compiles and crashes, then it is because you are writing to memory outside your data segment. As PapaBravo indicated, we need more information to tell you much else.
     
  8. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,887
    1,012

    If you know you want it to be a constant then declare it as constant and the compiler should catch your mistake.

    const unsigned char *c = "hello";
    *c = 'A';

    That throws an error.
     
  9. WBahn

    Moderator

    Mar 31, 2012
    17,748
    4,796
    I definitely agree that anytime a value in a variable is not intended to be changed that it should be declared as a const. This, and several other practices, allow the compiler to enforce your design decisions which can catch a lot of logic errors that would otherwise go uncaught.

    The deeper issue with strings (that Spinnaker alluded to) is that you can't just assign a string to a pointer variable and expect it to behave the same way that it does in many other languages. C operates at a much lower level than those other languages and forces you to deal with memory issues more directly.
     
  10. nsaspook

    AAC Fanatic!

    Aug 27, 2009
    2,908
    2,169
  11. WBahn

    Moderator

    Mar 31, 2012
    17,748
    4,796
    Yep. Because they can pretty much be used interchangeably in the function parameter list, people think they are interchangeable in all places. Not so.

    Just try to use

    fred[] = 3;

    instead of

    *fred = 3;

    The semantics of fred[expression] are such that this can be replaced with

    *(fred + (expression))

    and, because pointer arithmetic is commutative, this means that

    fred[5] = value;

    is identical to

    5[fred] = value;
     
    ErnieM likes this.
  12. John P

    AAC Fanatic!

    Oct 14, 2008
    1,634
    224
    A foolproof way to deal with this is to declare the string first, and then load it, IF you make sure that it's declared as the largest size that you'll ever need. So
    Code (Text):
    1.  
    2.     unsigned char str[8];            // 7 characters for the word "circuit" plus 1 for the terminating /0
    3.     strcpy(str, "circuit");            // Now write the word into it
    4.     *(str) = 'k';                         // This would make it hold "kircuit" by loading 'k' to location 0
    5.     str[0] = 'k';                         // This does the same as the previous line
    6.     strcpy(str, "k");                      // Now it's 'k' in location 0 and \0 in location 1
    7.     printf("%s %s\n", str, str+2);     // Not tested, but this should print "k rcuit". There are now 2 sub-strings in str,
    8.     // one with k at location 0, and \0 at
    9.     // location 1. But the original contents of the string is unchanged from location 2 onward, and could be accessed
    10.     // if you ever wanted to do it.
    11.  
    But do be sure that you never try to load more text into a string than your declaration stated! Mysterious errors will inevitably result.
     
    Last edited: Dec 27, 2015
  13. WBahn

    Moderator

    Mar 31, 2012
    17,748
    4,796
    How does "str = buffer" allocate space?
     
Loading...