Weird - strncpy won't copy the first char!

OK, this is weird.

For some reason, when I use strncpy to load a string into a char array:

char textArray[64];

(later on the code)

strncpy(textArray, “NEW TEXT”, 63);
Serial.println(textArray);

I get this returned:

EW TEXT

(there is a space in front of the ‘E’ and I assume it’s null? or is it something else?)

I can write to the first element in the array using

textArray[0] = ‘N’;

just fine. So why can’t strncpy do it??? A google search isn’t turning up anything useful.

Thanks again, folks…

If textArray[0] == 0, the strlen(textArray) would == 0 too. and no text should print.

It sounds more like you are appending 1 to the textArray pointer somewhere.

http://www.cplusplus.com/reference/clibrary/cstring/strncpy/

HTH

useless link, sorry for the noise. Note to self: next time read before replying :-)

@jeff-o

there is a space in front of the 'E' and I assume it's null?

No. If it were the null character nothing would be printed, because Serial.println stops when it sees a null character. All C-style "string" functions stop when they see a null character, so Serial.println would stop before it started.

If there is a space before the 'E' in the output of your sketch, then there is some character in textArrayy[0] that shows up as a space when you print it. (Maybe it's a space char, 0x20, or maybe it's some other (non-ASCII or non-printing) char that "just happens" to print out as a space...)

@jeff-o

So why can't strncpy do it?

It can. Really.

Try the following all by itself. Then put a print statement in your sketch immediately after your strncpy statement.

void setup()
{
    Serial.begin(9600);
}

void loop()
{
    char textArray[64];
    strncpy(textArray, "NEW TEXT", 63);
    Serial.print("1: ");
    Serial.println(textArray);

    //(later on the code)

    Serial.print("2: ");
    Serial.println(textArray);
    
    delay(1000);
}

Then: Look carefully in your sketch and see if there is a place where your program could have changed textArray[0].

If you didn't store something there intentionally, it's possible that writing outside the range of some other array could corrupt the contents of this array. (Or there could be bad behavior due to some misuse of a pointer variable somewhere. It's hard to say without seeing your sketch.)

@leppie:

It sounds more like you are appending 1 to the textArray pointer somewhere.

What do you mean "appending 1" to textArray? Do you mean adding 1? Or what?

Anyhow: textArray is the name of an array. As far as the compiler is concerned, it is a const pointer whose value is the address of the first element of the array. You couldn't increment textArray or change its value in any other way if you wanted to (or even if you didn't want to). The compiler simply won't let you.

Regards,

Dave

What do you mean "appending 1" to textArray? Do you mean adding 1? Or what?

Yes, textArray++

@leppie

textArray++

textArray in this sketch is the name of an array, right? Have you ever done this in a sketch (accidentally or on purpose)? And the compiler let you? Really?

Well...

This simply can't happen, for the reason that I put forth on my previous post: The compiler won't let you.

No standard C or C++ compiler will let you. So: It can't happen accidentally. It can't happen on purpose. Period. Full stop.

Regards,

Dave

This simply can't happen, for the reason that I put forth on my previous post: The compiler won't let you.

No standard C or C++ compiler will let you.

Unless:

char textArray [] = "The quick brown fox";

void whoops (char* textArray)
{
  textArray++;
  Serial.println (textArrray);
}

void setup()
{
  Serial.begin (9600);
  whoops (textArray);
}

void loop () {}

@Groove

Unless: . . .

But try this:

char textArray [] = "The quick brown fox";

void whoops (char* textArray)
{
  textArray++;
  Serial.print("In whoops: ");
  Serial.println(textArray);
}

void setup()
{
  Serial.begin (9600);
  whoops(textArray);
  Serial.print("In setup : ");
  Serial.println(textArray);
}

void loop () {}

Output


On whoops: he quick brown fox
In setup : The quick brown fox

The (global) identifier textArray is the name of an array. I hate to repeat myself, but: You can not change it. As far as C and C++ are concerned, it is a const pointer whose value is the address first element of the array. Period.

Now...

You have passed a copy of that pointer value to the function. The function is working on its own private copy of that pointer and can do anything it dang well pleases with its copy. Dereference it, increment it, decrement it, add 42 to it, whatever.

However...

The value of the global identifier textArray is not changed, as you can see when you use it in a Serial.print statement back in the calling function after whoops() has done its thing.

The fact that you used textArray as the name of the function parameter might mislead some of us mere humans into the wrongful thinking that something else happens, but the compiler is not fooled.

Never is. Never has been. Never will be.

I mean, there are certain program bugs that the compiler can't find for you. Accidentally (or intentionally) incrementing the name of an array is one of those things that it simply won't let you do.

I stand by my original statement.

Regards,

Dave

I don't (cannot) dispute what you're saying, but since we haven't seen any of the source of the problem code, I was simply pointing out one possible mechanism for the observation. All the OP says is '(later on the code)', which does not preclude my 'solution'.

@Groove: Since you started your post with “Unless:”, I inferred that you were offering a rebuttal to my flat statement that you can’t increment the name of an array.

I couldn’t let that stand, since some people reading this thread might not be as knowledgeable of C and C++ as you are, and they might run your sketch and somehow think that you can, somehow, increment a variable that is the name of an array.

Well, if there are any such people out there, here’s a flat statement: You can’t do it. Period. Full stop.

Regards,

Dave

strncpy expects char* not char[], hence things like the following can be valid.

char* Moo()
{
  static char bar[] = "Hello world";
  return bar + 1;
}

Edit: I think this is what I initially had in mind.

Edit2: @ the OP, where are you printing this or seeing the output? It could be something completely different is wrong.

@leppie

strncpy expects char* not char

In C and C++, if you define a function with a parameter that has “char * whatever” data type, it is treated exactly the same if you specify the parameter’s data type to be “char whatever[]”. Exactly.

Not “pretty much the same as.” Not “essentially the same as…” Not “effectively the same as.” Exactly.

Furthermore…

Regardless of which way you declare the function you can call it with the name of an array of char as the argument or with a variable that was declared “pointer to char.” The code is exactly the same.

Note that I am not (that’s not) saying that a pointer and an array are the same. They are not. My point is that when you use an array name in a function call, it is treated as a const pointer whose value is the address of the first element of the array. The function receives a copy of the pointer (the value of that pointer), and works on that value.

Bottom line: strncpy works just the same whether you give it the value of a pointer (where the pointer points to some memory locations that are going to be involved in the copy operation) or whether you give it the name of an array that is going to be involved in the copy operation.

So, I don’t understand what you mean by (or what conclusions we are supposed to draw from) your statement, “strncpy expects char* not char

Regards,

Dave

Of course, we wouldn't have to speculate if the OP simply posted the offending code.

(HINT)

We have moved far beyond speculating what really was the original problem.

These threads tend to take on a life of their own, especially when different contributors have different opinions about the facts of life in the wonderful world of C and C++ (modulo Arduino).

I personally feel that if anything here helped the Original Poster to understand anything, let alone actually fix a problem, it might be polite to let us know. But it's just possible that the exposition of slightly advanced concepts with give-and-take that strays from the original topic just might intimidate some people into not posting again. I sincerely hope that isn't the case.

Anyhow...

Since people other than "experts" and other than the Original Poster read these threads to pick up information, I think they (and we who offer our opinions) can still learn from ongoing discussions, regardless of whether or not the Original Poster has taken up a new hobby by now.

I mean, if people just put forth comments that I think don't have anything to do with solving the original problem, I might let them ride, but if the topic seems to be confusing to me or to be misleading to people who don't know much C or C++, I'll respond.

I'm funny that way. Sometimes I just can't help myself. It's a curse.

Regards,

Dave