Go Down

Topic: string doesn't change (Read 939 times) previous topic - next topic

If I compile the following program

Code: [Select]

void setup() {
  Serial.begin(115200);
  printOnDisplay("This is a test");
}
void printOnDisplay(char *string) {
  string[4] = 0;
  Serial.println(string);
}

on an ARDUINO DUE (and maybe on other ARDUINOS, too) the output is not as expected "This", but "This is a test"!? Why is the character-array "This is a test" not changeable. - Is it located in flash-memory?
Thanks for the answers in advance!

waski


PaulS

Code: [Select]
Why is the character-array "This is a test" not changeable.
What are you expecting to see, when the function outputs the data? I expect to see "This" followed by a carriage return and line feed.

What are you actually seeing?
The art of getting good answers lies in asking good questions.

waski

So i think this

Code: [Select]
string[4] = 0;

should be :

Code: [Select]
string[4] = '\0';

Code: [Select]
Why is the character-array "This is a test" not changeable.
What are you expecting to see, when the function outputs the data? I expect to see "This" followed by a carriage return and line feed.

What are you actually seeing?
As strings are "0"-terminated and I added a "0" after "This", I would expect "This" as output!?

PaulS

Both '\0' and 0 store the same value in the array.

OP, when I uploaded your code, after adding a loop() function, to my Arduino (Duemilanove), I get Test as the only output.

What do YOU actually get? On which Arduino, using which version of the IDE?
The art of getting good answers lies in asking good questions.

I'm using an ARDUINO DUE (IDE version 1.6.3)!
The following code
Code: [Select]

void setup() {
  Serial.begin(115200);
}
void loop() {
  printOnDisplay("This is a test");
  while(1);
}
void printOnDisplay(char *string)
{
  string[4] = 0;
  Serial.println(string);
  if (string[4]) Serial.println("String hasn't changed!");
  else Serial.println("String has changed!");
}

leads to the output:
"This is a test"
"String hasn't changed!"

When I compile it for an ARDUINO UNO it works as expected with the output:
"This"
"String has changed!"

PaulS

If you change:
Code: [Select]
void loop() {
  printOnDisplay("This is a test");
  while(1);
}

to
Code: [Select]
void loop()
{
   char test[] = "This is a test";
  printOnDisplay(test);
  while(1);
}

do you get the same (apparently incorrect) output?
The art of getting good answers lies in asking good questions.

If you change:
Code: [Select]
void loop() {
  printOnDisplay("This is a test");
  while(1);
}

to
Code: [Select]
void loop()
{
   char test[] = "This is a test";
  printOnDisplay(test);
  while(1);
}

do you get the same (apparently incorrect) output?
With your change it now works as expected!

PaulS

Quote
With your change it now works as expected!
So, apparently, on the DUE, literals are stored in a read-only portion of memory. I'd expect an attempt to alter a read-only portion of memory to generate an error at compile time - or at least a warning. But, since we are to be "protected" from our mistakes, warnings are disabled, so we never see them. Pretty stupid, in my opinion.
The art of getting good answers lies in asking good questions.

So, apparently, on the DUE, literals are stored in a read-only portion of memory. I'd expect an attempt to alter a read-only portion of memory to generate an error at compile time - or at least a warning. But, since we are to be "protected" from our mistakes, warnings are disabled, so we never see them. Pretty stupid, in my opinion.
So, apparently, on the DUE, literals are stored in a read-only portion of memory. I'd expect an attempt to alter a read-only portion of memory to generate an error at compile time - or at least a warning. But, since we are to be "protected" from our mistakes, warnings are disabled, so we never see them. Pretty stupid, in my opinion.
...I added the "problem" to the bug-report list on GitHub. Maybe it is not a bug, but at least surprising inconsistency!

christop

This is a known "gotcha" with C/C++. Back in the day before C had the "const" keyword, a read-only string literal was passed around as a pointer to char. You weren't allowed to modify the string, but that couldn't be enforced by the compiler--it had no way to differentiate a string that could be modified from one that couldn't when all you had was a pointer to char.

So now we have a language that still permits you to pass a read-only string literal to a function that takes a pointer to char without throwing a compiler error for the sake of backwards compatibility.

In any case, modifying a string literal is undefined behavior. It's not a bug as it's perfectly legal for the Uno to have different behavior than the Due. It would also be legal for the program to crash, if the implementation happened to work that way.

Go Up