Re: Type casting- a larger type to a smaller type

Discussion in 'C Programming' started by pete, Apr 1, 2004.

  1. pete

    pete Guest

    Colin MacDougall wrote:
    >
    > Can anyone advise on the following please ?
    > I am writing some code for use on an 8 bit micro (AVR).
    > The problem is that I use an unsigned int ( in this case
    > 16 bit ints ) as an address locator to some memory that
    > I wish to read from. To read from the memory I have to send
    > out the address in two writes of 8 bit chars - high part
    > of address and then low part of address. Looking at the
    > code below shows that I shift my int 8 bits to the right
    > and then squeeze it in to a char. To obtain the low part
    > of the address I just mask out the high byte of my int and
    > again force the result in to a char. The code seems to work
    > fine, but I want to know if there is a 'proper' way to do
    > this. I know that C supports type casting. But the examples
    > I have seen show a smaller data type being casted to a
    > larger data type and not the other way round. I guess my
    > method would be far from portable.
    >
    > unsigned char eeprom_read(unsigned int address)
    > {
    > unsigned char h_add;
    > h_add = address>>8; //get high part of address locator
    > mem_write(h_add); //send the high part of the address
    > mem_write(address & 0xff ); //send the low part of the address
    > .
    > .
    > .


    You can read the two bytes of the unsigned type, directly.
    But you have to find out which byte is high and which is low.

    mem_write((unsigned char *)&address); //send one byte
    mem_write(((unsigned char *)&address) + 1); //send the other

    --
    pete
     
    pete, Apr 1, 2004
    #1
    1. Advertising

  2. pete

    pete Guest

    pete wrote:
    >
    > Colin MacDougall wrote:
    > >
    > > Can anyone advise on the following please ?
    > > I am writing some code for use on an 8 bit micro (AVR).
    > > The problem is that I use an unsigned int ( in this case
    > > 16 bit ints ) as an address locator to some memory that
    > > I wish to read from. To read from the memory I have to send
    > > out the address in two writes of 8 bit chars - high part
    > > of address and then low part of address. Looking at the
    > > code below shows that I shift my int 8 bits to the right
    > > and then squeeze it in to a char. To obtain the low part
    > > of the address I just mask out the high byte of my int and
    > > again force the result in to a char. The code seems to work
    > > fine, but I want to know if there is a 'proper' way to do
    > > this. I know that C supports type casting. But the examples
    > > I have seen show a smaller data type being casted to a
    > > larger data type and not the other way round. I guess my
    > > method would be far from portable.
    > >
    > > unsigned char eeprom_read(unsigned int address)
    > > {
    > > unsigned char h_add;
    > > h_add = address>>8; //get high part of address locator
    > > mem_write(h_add); //send the high part of the address
    > > mem_write(address & 0xff ); //send the low part of the address
    > > .
    > > .
    > > .

    >
    > You can read the two bytes of the unsigned type, directly.
    > But you have to find out which byte is high and which is low.
    >
    > mem_write((unsigned char *)&address); //send one byte
    > mem_write(((unsigned char *)&address) + 1); //send the other


    mem_write(((unsigned char *)&address)[0]); //send one byte
    mem_write(((unsigned char *)&address)[1]); //send the other

    --
    pete
     
    pete, Apr 2, 2004
    #2
    1. Advertising

  3. pete

    Dan Pop Guest

    Re: Type casting- a larger type to a smaller type

    In <> pete <> writes:

    >pete wrote:
    >>
    >> Colin MacDougall wrote:
    >> >
    >> > Can anyone advise on the following please ?
    >> > I am writing some code for use on an 8 bit micro (AVR).
    >> > The problem is that I use an unsigned int ( in this case
    >> > 16 bit ints ) as an address locator to some memory that
    >> > I wish to read from. To read from the memory I have to send
    >> > out the address in two writes of 8 bit chars - high part
    >> > of address and then low part of address. Looking at the
    >> > code below shows that I shift my int 8 bits to the right
    >> > and then squeeze it in to a char. To obtain the low part
    >> > of the address I just mask out the high byte of my int and
    >> > again force the result in to a char. The code seems to work
    >> > fine, but I want to know if there is a 'proper' way to do
    >> > this. I know that C supports type casting. But the examples
    >> > I have seen show a smaller data type being casted to a
    >> > larger data type and not the other way round. I guess my
    >> > method would be far from portable.
    >> >
    >> > unsigned char eeprom_read(unsigned int address)
    >> > {
    >> > unsigned char h_add;
    >> > h_add = address>>8; //get high part of address locator
    >> > mem_write(h_add); //send the high part of the address
    >> > mem_write(address & 0xff ); //send the low part of the address
    >> > .
    >> > .
    >> > .

    >>
    >> You can read the two bytes of the unsigned type, directly.
    >> But you have to find out which byte is high and which is low.
    >>
    >> mem_write((unsigned char *)&address); //send one byte
    >> mem_write(((unsigned char *)&address) + 1); //send the other

    >
    >mem_write(((unsigned char *)&address)[0]); //send one byte
    >mem_write(((unsigned char *)&address)[1]); //send the other


    Wrong! The OP's code is correct. Your code introduces gratuitous
    byte order dependencies: you're assuming big endian.

    Dan
    --
    Dan Pop
    DESY Zeuthen, RZ group
    Email:
     
    Dan Pop, Apr 2, 2004
    #3
  4. pete

    Eric Sosman Guest

    [heavily snipped]

    pete wrote:
    >
    > pete wrote:
    > >
    > > Colin MacDougall wrote:
    > > >
    > > >
    > > > unsigned char eeprom_read(unsigned int address)
    > > > {
    > > > unsigned char h_add;
    > > > h_add = address>>8; //get high part of address locator
    > > > mem_write(h_add); //send the high part of the address
    > > > mem_write(address & 0xff ); //send the low part of the address

    > >
    > > You can read the two bytes of the unsigned type, directly.
    > > But you have to find out which byte is high and which is low.
    > >
    > > mem_write((unsigned char *)&address); //send one byte
    > > mem_write(((unsigned char *)&address) + 1); //send the other

    >
    > mem_write(((unsigned char *)&address)[0]); //send one byte
    > mem_write(((unsigned char *)&address)[1]); //send the other


    ... with the net effect of transforming a portable
    construct into a non-portable construct. This is an
    improvement?

    For some reason, C programmers seem easily seduced into
    thinking about representations of values instead of thinking
    about the values. pete's "improvements" are a cautionary
    illustration of the regrettable consequences: The first
    attempt was flat-out wrong, and the second is representation-
    dependent while the original code was wrong. (Off-topic:
    It is also likely to be slower than the original. This is
    less important than many C programmers appear to believe,
    but I'm willing to appeal to their baser instincts if it's
    in a good cause.)

    If you focus on the values your program manipulates and
    not upon the particular way the computer at hand happens to
    represent those values, you will be a more successful, less
    traumatized, and altogether happier programmer, producing
    simpler, better, and faster code than your "C is a glorified
    assembler" colleagues. There are a few situations in which
    the representations must be considered, usually when you're
    mediating between values inside a program and formats imposed
    by the external world. But even then it is sometimes possible
    (and preferable) to work with the values -- as in the case at
    hand, where external considerations demand that the two bytes
    of the address be presented in a particular order.

    When you find yourself writing #ifdef BIG_ENDIAN or
    #define SWAP32(x) ... or relying on the exact size of some
    data type, consider it a danger sign. Re-examine the need;
    more often than not it is illusory.

    --
     
    Eric Sosman, Apr 2, 2004
    #4
  5. pete

    Dan Pop Guest

    Re: Type casting- a larger type to a smaller type

    In <> Eric Sosman <> writes:

    >[heavily snipped]
    >
    >pete wrote:
    >>
    >> pete wrote:
    >> >
    >> > Colin MacDougall wrote:
    >> > >
    >> > >
    >> > > unsigned char eeprom_read(unsigned int address)
    >> > > {
    >> > > unsigned char h_add;
    >> > > h_add = address>>8; //get high part of address locator
    >> > > mem_write(h_add); //send the high part of the address
    >> > > mem_write(address & 0xff ); //send the low part of the address
    >> >
    >> > You can read the two bytes of the unsigned type, directly.
    >> > But you have to find out which byte is high and which is low.
    >> >
    >> > mem_write((unsigned char *)&address); //send one byte
    >> > mem_write(((unsigned char *)&address) + 1); //send the other

    >>
    >> mem_write(((unsigned char *)&address)[0]); //send one byte
    >> mem_write(((unsigned char *)&address)[1]); //send the other

    >
    > ... with the net effect of transforming a portable
    >construct into a non-portable construct. This is an
    >improvement?
    >
    > For some reason, C programmers seem easily seduced into
    >thinking about representations of values instead of thinking
    >about the values. pete's "improvements" are a cautionary
    >illustration of the regrettable consequences: The first
    >attempt was flat-out wrong, and the second is representation-
    >dependent while the original code was wrong.

    ^^^^^
    s/wrong/right

    Dan
    --
    Dan Pop
    DESY Zeuthen, RZ group
    Email:
     
    Dan Pop, Apr 2, 2004
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Peter Williams
    Replies:
    1
    Views:
    1,442
    Dylan Parry
    Jun 3, 2005
  2. heyo
    Replies:
    3
    Views:
    948
    Dan Pop
    Apr 1, 2004
  3. korean_dave
    Replies:
    3
    Views:
    263
    Gary Herron
    Nov 14, 2008
  4. Matjaz Bezovnik
    Replies:
    4
    Views:
    324
    Robert Kern
    Aug 25, 2009
  5. Replies:
    5
    Views:
    154
    David Dorward
    Feb 9, 2005
Loading...

Share This Page