View previous topic :: View next topic |
Author |
Message |
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
CCS 5.026 - strcmp / strncmp returns 255 [SOLVED] |
Posted: Fri Feb 16, 2018 2:30 pm |
|
|
Device: PIC24EP512GP806
Compiler: 5.026 w/ 5.071 IDE
Hello all,
I've noticed that strcmp and strcnmp on some particular situations don't return "result is -1 (less than), 0 (equal) or 1 (greater than)" like the manual states and like it should.
At the moment, I am comparing two strings and regardless if I use strcmp or strncmp, they both return 255.
I realize the strings aren't the same but I'd expect to have -1, 0 or 1 depending on the comparison. This screws-up my code big times. I don't understand because the function is used many other places in the code and this one particular place, fail.
This code worked up to like *now* without me changing anything in that area. I changed the data in the strings and stuff but not the function which worked for the last era.
Thanks.
Any idea?
Ben
Last edited by benoitstjean on Mon Feb 19, 2018 1:37 pm; edited 1 time in total |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Fri Feb 16, 2018 2:43 pm |
|
|
Get this.... so inverting the strings in the function now returns the correct value.
It is **similar** to the idea below... I have two global variables, one of them is known (string1) and the other is filled in the function. String1 gets passed to the function. Insinde the function, string2 is filled and compared with string1 filled outside the function.
Code: |
// Global variable
unsigned char string1[10] = "MyString1";
unsigned char string2[10] = "";
MyFunction( string1 );
void MyFunction( unsigned char *FuncString )
{
int8 RetVal;
sprintf( string2, "MyString2" );
RetVal = strncmp( FuncString, MyString1 );
--> FAIL: RetVal returns 255
RetVal = strncmp( MyString1, FuncString );
--> SUCCESS: RetVal returns 1
} |
Why does swapping the strings works??
Ben |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Fri Feb 16, 2018 2:57 pm |
|
|
OK, I don't use them 24 PICs but... can you roll back the compiler version and test ? Maybe 'something' changed in the compiler..one of those 'fixed A, broke B' situations.
I was thinking about variable default types... but if it worked 'last week', that shouldn't be the problem unless....CCS changed something...
sigh...I really hate stuff like this now..the 'used to work' problem
hopefully someone familair with 24s will chime in soon
At least it's sunny here in Ontario !
Jay |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 303
|
|
Posted: Fri Feb 16, 2018 3:11 pm |
|
|
If you want a signed return (-1, 0, 1) then you need to make sure your variable is signed.
A signed int8 cannot hold 255. It can only hold -128 - 127.
An unsigned in8 value of 255 is stored the same as a signed int8 value of -1.
The problem may be either how the variable is declared or how the value in the variable is being viewed. |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Fri Feb 16, 2018 3:38 pm |
|
|
To Gaugeguy:
I'm comparing strings and they are all declared as <unsigned char> so this is basically 0-255.
To Temtronic:
It's not a compiler thing, I mean, I've used the same 'everything' for ages.
Yes, I *did* change *some* code over the last few days but it's not code that should have affected how strncmp works. I mean, a string is a string. I'm comparing two strings of 9 bytes + end-of-string NULL (strings are 10-bytes long).
Note regarding my previous "ah-ha!" moment: It's still not working and this time, it's always returning 1.
The funny thing is that it doesn't make any sense that swapping the same strings yields different results... 1 vs 255?? I would have expected 1, -1 or 0... but not 1 then 255.
I know that it will be something very stupid when I realize what it is... but I've encountered this problem in the past and was not able to figure-out what it was and the problem disappeared all of a sudden.
I'll post results when I find something but in the meantime, any ideas are welcomed.
Thanks guys.
Ben |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Fri Feb 16, 2018 3:46 pm |
|
|
The point is the return from the function is a signed value.
If you are putting it into an unsigned value, you will see 255, for the -1 return.
So you get -1 and 1 as the two returns (A<B or A>B), when you reverse the strings.
Try a little test:
Code: |
int8 Retval;
signed int8 gtr=1, less=-1;
Retval=gtr; //What is Retval?.
Retval=less; //what is Retval?.
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Fri Feb 16, 2018 3:51 pm |
|
|
hmm any chance 255 is the undocumented result from comparing when 1 string has zero length ?
in you ah-ha string2 has zero characters in it.
yeah, I know pulling at straws....it's just that '255' is unique or special.
hopefully you'll still have some hair left when you discover the reason.
I still ahve no idea where Windows 'put' 20,000+ PIC files....
Jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Feb 16, 2018 3:52 pm |
|
|
Quote: |
void MyFunction( unsigned char *FuncString )
{
int8 RetVal;
sprintf( string2, "MyString2" );
RetVal = strncmp( FuncString, MyString1 );
RetVal = strncmp( MyString1, FuncString );
} |
How do you get this to compile ? If I try to compile it, I get these errors:
Quote: | *** Error 102 "PCH_Test.c" Line 21(34,41): Expect comma
*** Error 102 "PCH_Test.c" Line 27(31,41): Expect comma |
The CCS manual says that strncmp() has a 3rd parameter, which is the
number of bytes to compare:
Quote: | iresult=strncmp (s1, s2, n) // Compare s1 to s2 (n bytes) |
You're missing the byte count. |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Fri Feb 16, 2018 3:53 pm |
|
|
BOOM. Nailed it.
And I mis-read / mis-understood gaugeguy's explanation. I thought *somehow* he was referring to the strings in the function as opposed to the returned code. So his explanation was right.
I'll confirm this monday but it all makes sense. Yes, I am declaring the returned value for the strncmp as unsigned int8 rather than int8.
Doesn't explain why the code always worked up until now but anyhow, monday I will test all of this.
Arghhh.... Hey, it's friday...
Thanks all.
Ben |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Fri Feb 16, 2018 4:28 pm |
|
|
Tp PCM programmer:
My mistake, I wrote the code in this forum as if I was "programming", it's not an excerpt from my code. Yes, there should have been a length value as third parameter.
Anyhow, I strongly believe that the problem is what TTelmah and Gaugeguy have said - I am storing the returned value in an unsigned int8 rather than an int8.
Will confirm monday.
Thanks all.
Ben |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Mon Feb 19, 2018 8:58 am |
|
|
All right, results are in...
This is pretty much what my code does except I changed the variable names to make it easy to read and understand and I stripped the irrelevant stuff from the function.
Global variables:
Code: |
unsigned char *S1;
unsigned char *S2;
unsigned char *L1;
unsigned char *L2;
|
L1 and L2 are loaded from an EEPROM. These don't change.
S1 and S2 change based on events.
S1 and S2 get passed to the function:
Code: | IsDataValid( 0, S1, S2 );
bool IsDataValid( unsigned int8 ID, unsigned char *TestS1, unsigned char *TestS2 )
{
int8 Top = 0;
int8 Left = 0;
int8 Bottom = 0;
int8 Right = 0;
Top = strcmp( L1, TestS1 );
Left = strcmp( L2, TestS2 );
Bottom = strcmp( L1, TestS1 );
Right = strcmp( L2, TestS2 );
// Check some stuff here and return TRUE or FALSE
}
|
In the above test, strcmp returns 255. Swapping the strings from the function, strcmp always returns 1.
There are some instances where I *know* that strcmp should return -1 or 0 but it's always 1 or 255.
Still investigating... really does not make sense.
Ben |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Mon Feb 19, 2018 10:02 am |
|
|
It makes total sense, depending on how you are testing 'strcmp returns 255'.
Whatever you are putting it into to test, is being told to display the value as an unsigned int8.
For instance:
Code: |
int8 fred=-1; //fred is now a signed int8
printf("%3u\n", fred); //prints 255
printf("%3d\n",fred); //printf -1
|
C, and debuggers will 'believe what you tell them' about the size and type of variables. Somewhere something in your code or debugger settings is treating the variable as unsigned.
For instance if you have #type UNSIGNED, then an 'int8' will be unsigned. Or if (as a I show), you treat the variable as unsigned (passing it to something that only accepts an unsigned value), it'll be treated as 255.
If you have your debugger setup to assume unsigned, then it'll display the byte as 255. |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Mon Feb 19, 2018 10:32 am |
|
|
Yeah, I realized that like a minute ago that I was printing using %u rather than %d...
It's monday morning...
Ben |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Mon Feb 19, 2018 1:37 pm |
|
|
There were a few other things in my code but wrong returned value was my fault because I was using an unsigned int8.
I really missed that one.
Thanks all.
Ben |
|
|
|