3

The API provides a function signed char getDirection();, that returns 1 for "forward", 0 for "motionless", -1 for "backward."

And of course, as explained in these questions, a simple comparison:

    if(getDirection() == -1) { ... }

fails. Okay, I understand why it fails. But I just can't find how to make it work! I tried casting the left side to (int), the right side to (signed char), still nada...

edit:

 signed char a = getDirection();
 printf("%d\n",(int) a);
 printf("%d\n",(int) getDirection());

Results:

 -1
 255

edit2: per request:

const signed char getDirection(uchar d)
{
    if(d >= config.directional_inputs.channelCount) return -2;

    return shm->input_state.directional_inputs[d].direction;
}
Community
  • 1
  • 1
SF.
  • 13,549
  • 14
  • 71
  • 107
  • @AlexD: I wish. Well, actually the test statement is in format `printf("val: %d, comparison: %d", getDirection(), (getDirection() == DIRECTION_BACK) );` where the constant is `#define DIRECTION_BACK -1` – SF. Jul 20 '15 at 15:31
  • 3
    Your code is correct. Check if `getDirection()` actually returns -1. Show the output of your `printf`. Also show your actual code, maybe there is just a stray ';' somewhere. – Jabberwocky Jul 20 '15 at 15:32
  • @MichaelWalz: Output: "val: -1, comparison: 0". A colleague suspects a compiler error. – SF. Jul 20 '15 at 15:33
  • Try this: `printf("DIRECTION_BACK: %d, val: %d, comparison: %d", DIRECTION_BACK, getDirection(), (getDirection() == DIRECTION_BACK) );` just to be sure your macros are defined correctly. – Jabberwocky Jul 20 '15 at 15:37
  • @MichaelWalz: The values are okay. DIRECTION_BACK is -1. Moreover, as you see in the edit, if I compare `a` to DIRECTION_BACK it returns true. – SF. Jul 20 '15 at 15:41
  • 1
    @SF what compiler are you using ? Quite strange indeed. – Jabberwocky Jul 20 '15 at 15:42
  • @Michale Waltz: The API (getDirection() and family) is compiled through MinGW GCC. The code that links against that API (the problem statements) is compiled with TCC (Tiny C Compiler). – SF. Jul 20 '15 at 15:47
  • 1
    Hmm, didn't you forget to include a .h or to explicitely declare `const signed char getDirection(uchar d);` in your compilation unit ? – Serge Ballesta Jul 20 '15 at 15:49
  • @SergeBallesta: Don't you think that would fail to compile? (but not to sound snide - the header is included, the linking works fine, the function reacts to physical inputs correctly and returns the correct value (once we manage to squeeze a signed value out of it. Otherwise it returns 0,1,255); the same header file is used for compiling the api and for linking it against the problem code.) – SF. Jul 20 '15 at 15:53
  • Some compilers assume *any parameters returning int* for an undeclared function for compatibility with 1970s K&R C. But I you have checked anything, I would suspect a non conformant compiler (I do not know TCC, except for the ooold Turbo C Compiler ) – Serge Ballesta Jul 20 '15 at 16:01
  • If the function really is declared as `signed char getDirection();` you shouldn't get -1 and 255 in your example, are you sure there't nothing else going on ? (i.e. can you create a complete compilable example that shows that behavior , and what platform/compiler are you using) ? – nos Jul 20 '15 at 17:32
  • You're printing `getDirection()` but the function definition is `getDirection(uchar d)` – phuclv Jul 21 '15 at 01:55

3 Answers3

0

If you are sure that getDirection() really returns a signed char, it should work, since a signed char of 0xff should correctly be promoted to a -1 integer.

If unsure, you could try to write

int dir = getDirection();
// optionnally for extensive tests : fprintf(stderr, "getDirection : %d\n", dir);
if ((dir == -1) || (dir == 255)) { ... }

The 255 would catch any conversion problem, for example getDirection() returning a signed char ... what your last edit suggests ...

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • @MichaelWalz : It is. But I once had to use something like that for a library that returned a `char` and I had to use it on 2 platforms where char was signed on one and unsigned on the other. I've already seen (badly written) code where doc said `signed char` and code contained only `char` because a programmer thought that what he had on his system (char = signed char) was the standard, whereas standard says it is implementation dependant. – Serge Ballesta Jul 20 '15 at 15:46
  • @SergeBallesta: My personal take is that 'char' alone always means an ASCII letter. If it's to be a number, it must be denoted as 'signed' or 'unsigned'. – SF. Jul 20 '15 at 15:54
  • @sf a `char` is not an ASCII letter, it is an 8 bit value. `char` alone is `unsigned char` or (most of the time) `signed char` depending on your compiler. – Jabberwocky Jul 20 '15 at 16:02
  • @MichaelWalz: That depends on context. Is the literal `'A'` signed or unsigned? I denote the content of a variable by choosing the type prefix - if it's plain `char`, the correct format to printf() it to make sense is not %hhd or %hhu but %c. – SF. Jul 20 '15 at 16:07
  • @SF. : For recent or decent compilers, the standard is clear 6.2.5 §15 : *The three types char, signed char, and unsigned char are collectively called the character types. The implementation shall define char to have the same range, representation, and behavior as either signed char or unsigned char* – Serge Ballesta Jul 20 '15 at 16:26
  • Assuming `CHAR_BIT==8`, a "signed char of `0xff`" does not exist. The range of `signed char` is from `-128` to `+127` (assuming 2's-complement). `0xff` is simply another way of writing `255`. A `signed char` whose *representation* is the same as that of an `unsigned char` with the value `0xff` does have the value `-1` (again, assuming CHAR_BIT==8 and 2's-complement). – Keith Thompson Jul 20 '15 at 17:35
  • @KeithThompson : I would say that the operation `signed char c = 0xFF;` is explicitely implementation defined, and could even raise a signal for `CHAR_BIT==8`: 6.3.1.3 §3 *[when] the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.* - but common 2-complement implementations give `-1`. – Serge Ballesta Jul 20 '15 at 18:00
  • @SergeBallesta: Yes, it's implementation-defined -- but one thing it *can't* do is store the value `0xFF` in `c` (again, given the assumptions stated above). – Keith Thompson Jul 20 '15 at 18:04
0

It seems that in GetDirection the part return shm->input_state.directional_inputs[d].direction; is performed. What is the type of that direction element? I am not sure about promotions here, but if it is unsigned char, it might just be copied into the return register ax and returned. That is, no sign extension is performed and ax is 0x000000ff. The ff is assigned to signed char a, which is correct, and when a is used in the printf call, it gets properly sign extended. So the sign extension must be done in the return statement of GetDirection where it is apparently not done.

Try changing it to return (signed char)shm->input_state.directional_inputs[d].direction;

Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41
  • `direction` is `signed char` all the same, and it's the first in chain of assignments, getting a literal `-1` once input ports combine into 'backwards' configuration. – SF. Jul 20 '15 at 16:03
  • It still looks as if `GetDirection` does not do a sign extension. Check it with the debugger. – Paul Ogilvie Jul 20 '15 at 16:05
0

This is very strange.

First, using different compilers might make a difference. They might have different rules how a signed char is supposed to be returned. Let's say the compiler for compiling the function assumes that signed char is returned as 8 bit in a 32 bit register, with the other bits zero or undefined - -1 is returned as 00000000 00000000 00000000 11111111. The compiler for the call assumes that signed char is returned as 8 bit in a 32 bit register, sign extended, and therefore all 32 bits can be assumed to contain the correct value. So that compiler thinks the result is 255.

Second, I have seen problems where prototypes and functions didn't match. If there is a prototype for the function somewhere that says "char" instead of signed char, that would explain everything. Since the problem is strange, I'd ask the compiler for preprocessor output and check if anything strange is going on.

gnasher729
  • 51,477
  • 5
  • 75
  • 98
  • For recent or decent compilers, the standard is clear 6.3.1.1 §2-3 : *If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions* and *The integer promotions preserve value including sign. As discussed earlier, whether a ‘‘plain’’ char is treated as signed is implementation-defined* . But is TCC conformant ? and what version of standard ? – Serge Ballesta Jul 20 '15 at 16:19