-1

You are given a getTemps() function returns an integer composed of: the daily high temperature in bits 20-29, the daily low temperature in bits 10-19, and the current temperature in bits 0-9, all as 2's complement 10-bit integers. Write a C program which extracts the high, low, and current temperature and prints the values.

I am given this situation. So my question is how do I get the specific segments of an integer.

So far I have:

#include <stdio.h>
unsigned createMask(unsigned a, unsigned b){
    unsigned r = 0;
    unsigned i;
    for (i=a; i<=b; i++){
        r |= 1 << i;

    }
    return r;
}
int main(int argc, char *argv[])
{
  unsigned r = createMask(29,31);
  int i = 23415;
  unsigned result = r & i;
  printf("%d\n", i);
  printf("%u\n", result);
}

The integer 23415 for example would have the binary 00000000 00000000 01011011 01110111

Then bits 29 through 31 for example should be 111 or integer -1 since its 2's complement.

Ilya
  • 4,583
  • 4
  • 26
  • 51
jimbob
  • 461
  • 2
  • 8
  • 17
  • possible duplicate of [How do I extract specific 'n' bits of a 32-bit unsigned integer in C?](http://stackoverflow.com/questions/8011700/how-do-i-extract-specific-n-bits-of-a-32-bit-unsigned-integer-in-c) – phuclv Apr 30 '15 at 05:08
  • I changed the question a bit. – jimbob Apr 30 '15 at 05:15
  • 1
    Well... that's a bit disingenuous. What you did is take part of the solution from the listed link and added it to your question. Is there any reason the solutions there won't solve your issue? Please explain? That's is what will, or won't, make your questions distinct. – David C. Rankin Apr 30 '15 at 05:28
  • Well I tried to use the help given, but it seems to only return 0? instead of 3 or -1. – jimbob Apr 30 '15 at 05:34

3 Answers3

3

There are three basic approaches for extracting encoded information from a bitfield. The first two are related and differ only in the manner the bitfield struct is initialized. The first and shortest is to simply create a bitfield struct defining the bits associated with each member of the struct. The sum of the bits cannot exceed sizeof type * CHAR_BIT bits for the type used to create the bitfield. A simple example is:

#include <stdio.h>

typedef struct {
    unsigned cur  : 10,
             low  : 10,
             high : 10;
} temps;

int main (void) {

    unsigned n = 0;                 /* encoded number of temps  */

    n = 58;                         /* fill number (58, 46, 73) */
    n |= (46 << 10);
    n |= (73 << 20);

    temps t = *(temps *)&n;         /* initialize struct t      */

    /* output value and temps */
    printf ("\n number entered : %u\n\n", n);

    printf ("   %2hhu - %2hhu  value : %u (deg. F)\n", 0, 9, t.cur);    
    printf ("   %2hhu - %2hhu  value : %u (deg. F)\n", 10, 19, t.low);    
    printf ("   %2hhu - %2hhu  value : %u (deg. F)\n\n", 20, 29, t.high);    

    return 0;
}

Note: memcpy can also be used to initialize the value for the structure to avoid casting the address of n. (that was done intentionally here to avoid inclusion of string.h).

The next method involves creation of a union between the data type represented and the exact same struct discussed above. The benefit of using the union is that you avoid having to typecast, or memcpy a value to initialize the struct. You simply assign the encoded value to the numeric type within the union. The same example using this method is:

#include <stdio.h>

typedef struct {
    unsigned cur  : 10,
             low  : 10,
             high : 10;
} temps;

typedef union {
    temps t;
    unsigned n;
} utemps;

int main (void) {

    unsigned n = 0;                 /* encoded number of temps  */

    n = 58;                         /* fill number (58, 46, 73) */
    n |= (46 << 10);
    n |= (73 << 20);

    utemps u;                       /* declare/initialize union */
    u.n = n;

    /* output value and temps */
    printf ("\n number entered : %u\n\n", n);

    printf ("   %2hhu - %2hhu  value : %u (deg. F)\n", 0, 9, u.t.cur);    
    printf ("   %2hhu - %2hhu  value : %u (deg. F)\n", 10, 19, u.t.low);    
    printf ("   %2hhu - %2hhu  value : %u (deg. F)\n\n", 20, 29, u.t.high);    

    return 0;
}

Finally, the third method uses neither a struct or union and simply relies on bit shift operations to accomplish the same purpose. A quick example is:

#include <stdio.h>
#include <limits.h>     /* for CHAR_BIT */

int main (void) {

    unsigned n = 0;                 /* encoded number of temps  */
    unsigned char i = 0;            /* loop counter             */
    unsigned char r = 10;           /* number of bits in temps  */
    unsigned char s = 0;            /* shift accumulator        */
    unsigned v = 0;                 /* extracted value          */

    n = 58;                         /* fill number (58, 46, 73) */
    n |= (46 << 10);
    n |= (73 << 20);

    printf ("\n number entered : %u\n\n", n);

    /* extract and output temps from n */
    for (i = 0; i < (sizeof n * CHAR_BIT)/r; i++)
    {
        v = (n >> i * r) & 0x3ff;
        printf ("   %2hhu - %2hhu  value : %u (deg. F)\n", s, s + r - 1, v);
        s += r;
    }

    printf ("\n");

    return 0;
}

Note: you can automate the creation of the mask with the createMask function. While longer, the shift method is not computationally intensive as shift operations take little to accomplish. While negligible, the multiplication could also be replaced with a shift and addition to further tweak performance. The only costly instruction is the division to set the loop test clause, but again it is negligible and all of these cases are likely to be optimized by the compiler.

All of the examples above produce exactly the same output:

$ ./bin/bit_extract_shift

 number entered : 76593210

    0 -  9  value : 58 (deg. F)
   10 - 19  value : 46 (deg. F)
   20 - 29  value : 73 (deg. F)
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
1

You can use union and bit field to do it. Try something like this:

struct TEM_BITS {
    unsigned int tem_high :10;
    unsigned int tem_low  :10;
    unsigned int tem_cur  :10;
};

union TEM_U {
    int tem_values;
    struct TEM_BITS bits;
}

TEM_U t;
t.tem_values = 12345;

printf("tem_high : 0x%X\n", t.bits.tem_high);
printf("tem_low  : 0x%X\n", t.bits.tem_low);
printf("tem_cur  : 0x%X\n", t.bits.tem_cur);
Ilya
  • 4,583
  • 4
  • 26
  • 51
0

I might have my bits backwards, but the following should be close.

int current=x&0x3ff;

int low = (x>>10)&0x3ff;

int high = (x>>20)&0x3ff;
Joe Gibbs
  • 144
  • 1
  • 12
  • I'm confused as to what x is and what 0x3ff is – jimbob Apr 30 '15 at 05:31
  • 2
    x is the variable and things begin with 0x is a [hexadecimal constant](http://en.wikipedia.org/wiki/Hexadecimal) you need to read some basic C book first – phuclv Apr 30 '15 at 08:09