• AVR Freaks

Hot!Probably me, but WHY?

Page: 123 > Showing page 1 of 3
Author
Too Old For This
New Member
  • Total Posts : 5
  • Reward points : 0
  • Joined: 2020/10/08 03:55:16
  • Location: 0
  • Status: offline
2020/10/22 04:01:22 (permalink)
0

Probably me, but WHY?


#include <xc.h>
volatile char x, y, z;

void main(void) {
    x = 0x55;
    y = ~x;
    z = ~x;
    if (y == ~x) // false
        y = 0;
    if (y == (~x)) // false
        y = 0;
    if (y == z) // true
        y = 0;
}

 
I don't understand why. Does anyone? XC8, PIC16F15345.
 
#1

52 Replies Related Threads

    1and0
    Access is Denied
    • Total Posts : 11501
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Probably me, but WHY? 2020/10/22 04:15:47 (permalink)
    +5 (5)
    Too Old For This
    I don't understand why. Does anyone? XC8, PIC16F15345.

    Integer promotion!
        x = 0x55;       // x = 0x55
        y = ~x;         // y = 0xAA
        z = ~x;         // z = 0xAA
        if (y == ~x)    // false cuz (0x00AA != 0xFFAA)
            y = 0;
        if (y == (~x))  // false cuz (0x00AA != 0xFFAA)
            y = 0;
        if (y == z)     // true  cuz (0x00AA == 0x00AA)
            y = 0;

    #2
    Mysil
    Super Member
    • Total Posts : 3947
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: online
    Re: Probably me, but WHY? 2020/10/22 04:58:33 (permalink)
    0
    Hi,
    C language compiler may do integer promotion to default 16 bit int,
    for calculations to the right of the '=' assignment operator,
    only when all calculations are completed, is the result converted to the result variable type.
     
    So  you may try a explicit cast:
        if (y == (char)~x)
    or
        if (y == (char)(~x)) 

     
        Mysil
    #3
    Too Old For This
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2020/10/08 03:55:16
    • Location: 0
    • Status: offline
    Re: Probably me, but WHY? 2020/10/22 04:59:33 (permalink)
    0
    Good Lord so it is.
     
    Fancy imagining I want to compare a char to an integer. I forget how stupid C is!
     
    Thanks, 1and0 !
     
    #4
    NKurzman
    A Guy on the Net
    • Total Posts : 19023
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: offline
    Re: Probably me, but WHY? 2020/10/22 07:11:43 (permalink)
    +3 (3)
    It’s not smart or stupid, it’s simply the rules.
    It must do it that way. If it does it a “smarter“ way, then it won’t be standard compliant.
    #5
    NKurzman
    A Guy on the Net
    • Total Posts : 19023
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: offline
    Re: Probably me, but WHY? 2020/10/22 08:52:28 (permalink)
    0
    The Rules are the rules.
    As a C programmer you are expected to learn the rules, understand the rules, and apply the rules. The same as any other endeavor.

    When you run into “implementation defined behavior” you may find yourself complaining about the lack of rules.
    Like is char signed or unsigned?

    But in this particular case you’re asking what the correct action should be when someone tries to do math on a character.
    post edited by NKurzman - 2020/10/22 08:54:35
    #6
    1and0
    Access is Denied
    • Total Posts : 11501
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Probably me, but WHY? 2020/10/22 09:36:06 (permalink)
    0
    vexorg
    Rules like, declaring a variable as a char doesn't mean it's a char rules?

    A char is a char; however, the intermediate result of an operation on a char is not necessary a char.
     
    #7
    Mysil
    Super Member
    • Total Posts : 3947
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: online
    Re: Probably me, but WHY? 2020/10/22 12:38:01 (permalink)
    0
     
    But char data type is not only used for ASCII, there are a bunch of 8 bit character sets,
    Or a sequence of 1  up to 3 values of 8 bits each for each code point in Unicode.
     
        Mysil
    #8
    Antipodean
    Super Member
    • Total Posts : 1941
    • Reward points : 0
    • Joined: 2008/12/09 10:19:08
    • Location: Didcot, United Kingdom
    • Status: offline
    Re: Probably me, but WHY? 2020/10/22 14:49:48 (permalink)
    0
    vexorg
    NKurzman
    Like is char signed or unsigned?

    should be signed, since all unsigned types are explicitly declared.

     
    Umm, while I am not an expert on the definition of C, I believe that early on the signedness of char was implementation dependent, and any well versed C programmer would still treat it that way.
     
    And as has already been pointed out, the OPs problem was he was shifting a char value left 4 places,  which makes it value for any printable char larger than 255, so becomes an integer - until the compiler is told to do otherwise by casting or anding with 0xFF.
     

    Do not use my alias in your message body when replying, your message will disappear ...

    Alan
    #9
    NKurzman
    A Guy on the Net
    • Total Posts : 19023
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: offline
    Re: Probably me, but WHY? 2020/10/22 18:50:35 (permalink)
    0
    Since char could be signed or unsigned, code depending on One way or another may not work in a different compiler.
    In the end the rules are the rules.
    Each Standards release had a comment period.
    I am certainly not going to say that every rule makes perfect sense. But complaining about them is not going to really change them.
    #10
    1and0
    Access is Denied
    • Total Posts : 11501
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Probably me, but WHY? 2020/10/22 19:18:12 (permalink)
    0
    The data type char is implementation defined because of C historical reasons, which I'll not go into here.

    Section 3.1.2.5 of the ANSI C Rationale states:

    Three types of char are specified: signed, plain, and unsigned.  A plain char may be represented as either signed or unsigned, depending upon the implementation, as in prior practice.  The type signed char was introduced to make available a one-byte signed integer type on those systems which implement plain char as unsigned.  For reasons of symmetry, the keyword signed is allowed as part of the type name of other integral types.


    Each revision of the C standard has had to avoid breaking existing code and existing implementations. If C is being designed from scratch today, it probably would be different. ;)
     
    #11
    jtemples
    عُضْوٌ جَدِيد
    • Total Posts : 12032
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    Re: Probably me, but WHY? 2020/10/22 19:52:08 (permalink)
    +2 (2)
    Part of the rationale for this is that machines didn't necessarily have byte operations back in the day; word operations were more efficient.  And here we are using PICs that don't have word operations...
    #12
    NorthGuy
    Super Member
    • Total Posts : 6404
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: offline
    Re: Probably me, but WHY? 2020/10/22 20:02:58 (permalink)
    +1 (1)
    jtemples
    Part of the rationale for this is that machines didn't necessarily have byte operations back in the day



    Many still don't, even the newest ones, such as ARM64 or RISC-V.
    #13
    PStechPaul
    Super Member
    • Total Posts : 2973
    • Reward points : 0
    • Joined: 2006/06/27 16:11:32
    • Location: Cockeysville, MD, USA
    • Status: offline
    Re: Probably me, but WHY? 2020/10/22 20:34:35 (permalink)
    0
    Probably safest to use the int[n]_t convention, where n can be 8, 16, 24, 32, 64, and even possibly 128 and 256
     
    https://en.wikipedia.org/wiki/C_data_types#stdint.h
     
    SQL defines similar data types up to 256
     
    https://clickhouse.tech/docs/en/sql-reference/data-types/int-uint/
     
    I am unsure if this eliminates the necessity of typecasting when performing various operations on the integers.

     
    #14
    1and0
    Access is Denied
    • Total Posts : 11501
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Probably me, but WHY? 2020/10/22 22:07:11 (permalink)
    0
    PStechPaul
    Probably safest to use the int[n]_t convention, where n can be 8, 16, 24, 32, 64, and even possibly 128 and 256
     
    I am unsure if this eliminates the necessity of typecasting when performing various operations on the integers.

    These

    typedef signed char int8_t;
    typedef unsigned char uint8_t;

    are no different -- they are just aliases, subject to the same C rules; they will promote to type int.
    post edited by 1and0 - 2020/10/22 22:08:45
    #15
    jtemples
    عُضْوٌ جَدِيد
    • Total Posts : 12032
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    Re: Probably me, but WHY? 2020/10/23 00:19:37 (permalink)
    0
    Because plain char can be signed or unsigned, depending on the compiler and/or compiler options selected by the user.  This is why char should never be used as a small integer.
    #16
    Hen
    Super Member
    • Total Posts : 114
    • Reward points : 0
    • Joined: 2018/10/24 04:01:44
    • Location: 0
    • Status: offline
    Re: Probably me, but WHY? 2020/10/23 00:38:53 (permalink)
    0
    jtemples
    This is why char should never be used as a small integer.

    You probably mean char without a preceding signed/unsigned spec...
    #17
    oliverb
    Super Member
    • Total Posts : 342
    • Reward points : 0
    • Joined: 2009/02/16 13:12:38
    • Location: 0
    • Status: offline
    Re: Probably me, but WHY? 2020/10/23 00:48:45 (permalink)
    0
    What is the correct way to cast the result of a multiply, for example multiplying two ints to give a long?
    If I just cast the arguments to long then the result should be long but that might cause a really inefficient implementation?
    #18
    ric
    Super Member
    • Total Posts : 28943
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Probably me, but WHY? 2020/10/23 01:03:49 (permalink)
    0
    You only need to cast one of the arguments.
    You're just telling the compiler to treat it as a long, it still knows it is an int, so should do it as efficiently as possible.
     
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #19
    Too Old For This
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2020/10/08 03:55:16
    • Location: 0
    • Status: offline
    Re: Probably me, but WHY? 2020/10/23 01:34:25 (permalink)
    0
    I'm using char because it's a byte, coming in from a serial port. The OP is an excerpt from a routine which I've ported from Windows, where the ~checksum works fine.
     
    I've cast it (correctly) as an unsigned char now.
     
    It appears that the XC8 compiler is a better rule-follower than the Windows one grin: grin
    #20
    Page: 123 > Showing page 1 of 3
    Jump to:
    © 2020 APG vNext Commercial Version 4.5