basic question from c pointer

Thread Starter

ep.hobbyiest

Joined Aug 26, 2014
201
Hi,
i m confused in following question.

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

Papabravo

Joined Feb 24, 2006
21,159
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.
 

WBahn

Joined Mar 31, 2012
29,978
Hi,
i m confused in following question.

Code:
unsigned char *str="circuit";
*(str) = 'k';
this code gives error. please i cant understand how it is giving error.
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).
 

spinnaker

Joined Oct 29, 2009
7,830
Hi,
i m confused in following question.

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

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.
 

WBahn

Joined Mar 31, 2012
29,978
Oh, you can create them that way, but they are string literals and can't (shouldn't) be changed.

For instance

C:
#include <stdio.h>

int main(void)
{
   unsigned char *str = "Hello World!";

   printf("%s\n", str);

   return 0;
}
runs just fine. However,

C:
#include <stdio.h>

int main(void)
{
   unsigned char *str = "Hello World!";

   printf("%s\n", str);

   *str = 'J';
   printf("%s\n", str);

   return 0;
}
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

C:
#include <stdio.h>

int main(void)
{
   unsigned char str[] = "Hello World!";

   printf("%s\n", str);

   *str = 'J';
   printf("%s\n", str);

   return 0;
}
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.
 

WBahn

Joined Mar 31, 2012
29,978
Ok. Thanks every one.
Means compiler treating string as constant. And i m trying to change the constant data field.
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.
 

spinnaker

Joined Oct 29, 2009
7,830
Ok. Thanks every one.
Means compiler treating string as constant. And i m trying to change the constant data field.

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.
 

WBahn

Joined Mar 31, 2012
29,978
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.
 

WBahn

Joined Mar 31, 2012
29,978
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;
 

John P

Joined Oct 14, 2008
2,025
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:
    unsigned char str[8];            // 7 characters for the word "circuit" plus 1 for the terminating /0
    strcpy(str, "circuit");            // Now write the word into it
    *(str) = 'k';                         // This would make it hold "kircuit" by loading 'k' to location 0
    str[0] = 'k';                         // This does the same as the previous line
    strcpy(str, "k");                      // Now it's 'k' in location 0 and \0 in location 1
    printf("%s %s\n", str, str+2);     // Not tested, but this should print "k rcuit". There are now 2 sub-strings in str, 
    // one with k at location 0, and \0 at
    // location 1. But the original contents of the string is unchanged from location 2 onward, and could be accessed
    // if you ever wanted to do it.
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:
Top