LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   read/write in block device driver (https://www.linuxquestions.org/questions/programming-9/read-write-in-block-device-driver-942672/)

zali 05-01-2012 02:41 AM

read/write in block device driver
 
Hi
In block device driver, for reading the device I read my device and then copy to buffer array of request structure, but this buffer is defined as char*, what should I do when readed bytes are unsigned char. Is there any way other than request structure for transferring readed bytes to the driver?
Thanks

Aquarius_Girl 05-04-2012 06:19 AM

Size of unsigned char is 1 byte. So, can you pick up
one byte and put in the char*.

Code:

#include <iostream>
int main ()
{
        char          *p    = new char [10];
        unsigned char j [2] = {'1', '2'};
       
        p[0] = j[0];
        p[1] = j[1];
       
        std :: cout << p[0];
        std :: cout << p[1];
}

memcpy etc. would obviously not work here.

zali 05-04-2012 11:52 PM

Thanks for your reply, but if we have an unsigned value upper than 128 and cast it to a char variable, then char variable would be corrupted, try below code in linux:

void main(){
char i;
unsigned char j = 0xf1;
i = j;
printf("j=%X,i=%X",j,i);
}

it would print j=f1,i=fffffff1, may be the printed value is corrupted, I don't have any editor to trace it and watch the values in memory.

Nominal Animal 05-05-2012 03:01 AM

Quote:

Originally Posted by zali (Post 4670792)
Thanks for your reply, but if we have an unsigned value upper than 128 and cast it to a char variable, then char variable would be corrupted

No, it is not corrupted.

While the C99 standard (section 6.3.1.3) states that casting an unsigned value to signed results in implementation-defined behaviour, all current architectures use two's complement to represent signed integers, so casts between integer types do not modify the bit pattern at all. Conversion to larger type replicates the high bit to new bits, and conversion to smaller type uses only the low bits. Signedness or unsignedness does not affect integer casts at all. In other words, all architectures running Linux have the same behaviour: use the same actual bit pattern. Thus, no corruption.

(As far as I know, this actually extends to all currently mass-produced CPU architectures. There are some historical ones that used one's complement, and thus have +0 and -0 with differing bit patterns, but they have a lot of other weirdnesses too. You can safely assume all architectures use two's complement signed integers, and that casting between signed and unsigned integer types of the same size does not modify the bit patterns.)

Your example code has a fatal flaw: both i and j are converted to int first. Because usually i is a signed type, for it the new high bits will be duplicates of the old highest bit (the sign bit, in two's complement format). Because j is unsigned, the new high bits will be zero.

Try this code instead:
Code:

#include <stdio.h>
#include <limits.h>

int main(void)
{
    char          c1;
    signed char  s1;
    unsigned char u1, u2;

    u1 = 0xF1; /* 241 in decimal */
    s1 = u1;
    c1 = u1;
    u2 = s1;

    printf("u1 = %d (0x%x)\n", u1, u1);
    printf("c1 = %d (0x%x) when converted to int\n", c1, c1);
    printf("s1 = %d (0x%x) when converted to int\n", s1, s1);
    printf("s1 = %d (0x%x) actual bits\n", s1 & ((1 << CHAR_BIT)-1), s1 & ((1 << CHAR_BIT)-1));
    printf("u2 = %d (0x%x)\n", u2, u2);

    return 0;
}

The output will be
Code:

u1 = 241 (0xf1)
c1 = -15 (0xfffffff1) when converted to int
s1 = -15 (0xfffffff1) when converted to int
s1 = 241 (0xf1) actual bits
u2 = 241 (0xf1)

except that the number of consecutive f's in the c1 and s1 lines depends on the size of int on the architecture (32 bits in Linux, always, as far as I know).

This output will show you that casting does not affect the bit pattern, and that the bit pattern in the signed char is exactly the same as the bit pattern in the unsigned char. Thus, casting between signed and unsigned types in Linux, never changes the actual bits. Only their interpretation.

zali 05-05-2012 03:14 AM

Thanks for your complete fully-described reply:) I got it


All times are GMT -5. The time now is 06:21 AM.