near * vs generic * as parameter

Help
micro_joe
2012-05-04
2013-03-12
  • micro_joe
    micro_joe
    2012-05-04

    Hi All,
    I've had to go back to some code I wrote about 5/6 years ago using and earlier version of SDCC. I don't remember which one. The compiler I'm using now is 3.1.0 #066 (Nov 22 2011) (MINGW32).

    I tried  to re-compile the original code but  I'm getting problems compiling it. The orignal code has been working succesfully for many years.

    The error I get is
    error 78 incompatable types
    from type 'unsigned-char  near* fixed'
    to type 'unsigned-char generic* fixed'

    The error is in passsing parameters to a function.
    The protoype is

    extern unsigned char FlashWrite(unsigned int address, unsigned char * dat, char DataSize);
    

    and there are two types of call

        flashok = FlashWrite(address, &ReceivedDataBuffer, (char) sizeof(ReceivedDataBuffer));
    

    where ReceivedDataBuffer is declared as

     unsigned char ReceivedDataBuffer[16]
    

    and

    flashok = FlashWrite(address, &dummy, (char) sizeof(dummy));
    

    where dummy is declared as

    unsigned char dummy ;
    

    locally ie in the same function.

    The error is thrown on the passing of "ReceivedDataBuffer".  I think the problem is that the pointers are a different size for the two variables.

    Can any one tell me how to declare the function so that I may pass either. I it requires wrinting two functions thats not a problem although I'd rather write one and have a better understanding

    Many thank in advance

    Joe

     
  • micro_joe
    micro_joe
    2012-05-04

    Hi Again,

    I may have answered my own quest by casting the call

    flashok = FlashWrite(address, &ReceivedDataBuffer, (char) sizeof(ReceivedDataBuffer));
    to
    flashok = FlashWrite(address, )(unsigned char *)&ReceivedDataBuffer, (char) sizeof(ReceivedDataBuffer));

    It compiles but I don't know if it produces the correcct code at the moment.
    Can anyone comment.

    Cheers
    Joe

     
  • Raphael Neider
    Raphael Neider
    2012-05-04

    The cast seems to be somewhat dangerous, I'd recommend using

    &ReceiveBuffer[0]
    

    instead.

    Rationale: Arrays in C are somewhat magical. ReceiveBuffer should behave like a pointer to the first element most of the time. Probably, you can even do *ReceiveBuffer to obtain the first element from the array … Conversely, &ReceiveBuffer is taking the address of that pointer - which is ok for arrays as the symbol ReceiveBuffer refers to the start of the array (and not a separate pointer variable as suggested above), but which is also somewhat duplicate (ReceiveBuffer is the same as &ReceiveBuffer …). SDCC warns a bit clumsily about this, most (other) compilers probably just do The Right Thing ™, and this might even be enforced by the standard, but I recommend not using this.

    Summing up:

    &ReceiveBuffer[0]
    

    is clear and "obvious" and my recommendation,

    ReceiveBuffer
    

    should also work, is less verbose and arguably clear enough,

    &ReceiveBuffer
    

    should be avoided.

    I did not check if using

    &ReceiveBuffer[0]
    

    compiles without warning - if it does not, I'd consider that a bug ;-)

     
  • Raphael Neider
    Raphael Neider
    2012-05-04

    Of course, ReceiveBuffer was meant to be ReceivedDataBuffer throughout my previous post, and all my examples refer to its occurrence as the second argument of FlashWrite().

     
  • Maarten Brock
    Maarten Brock
    2012-05-05

    Conversely, &ReceiveBuffer is taking the address of that pointer - which is ok for arrays as the symbol ReceiveBuffer refers to the start of the array (and not a separate pointer variable as suggested above), but which is also somewhat duplicate (ReceiveBuffer is the same as &ReceiveBuffer …)

    No, ReceiveBuffer is not the same as &ReceiveBuffer even though they point to the same address in memory. The first points to the whole array and the second only to the first element. It's like taking the address of a struct variable or that of it's first element. If you're going to do arithmetic with them (like ++ or ) you'll find the difference is very important.

    I agree with the solutions. Use &ReceivedDataBuffer or just ReceivedDataBuffer to get the unsigned-char* although casting should work too.

    Maarten

     
  • micro_joe
    micro_joe
    2012-05-10

    Many thanks for you replies.
    What concerned me the most was whether near and generic pointers were different sizes but noting that neither variables were declared in a specific memory space I guess they would both have the same pointer size.

    You've ( Martin) have also explained something that's always puzzled my but I never looked into ie the difference between ReceivedDataBuffer and &ReceivedDataBuffer. I've never suffered from this difference luckily.

    Personally I'd prefer casting so the call type is explicitly the same as the function parameter. To make it more safe I could declare a typedef to ensure consistancy.

    Thanks again

     
  • micro_joe
    micro_joe
    2012-05-10

    I've just done a comparison and
    &ReceivedDataBuffer
    ReceivedDataBuffer
    (unsigned char *)&ReceivedDataBuffer
    all produce the same code.
    Bu