简体   繁体   English

尝试编写低级位库,但在尝试将字节结构转换为 char 类型时出现错误或垃圾

[英]Trying to write low-level bit library, but I get an error, or garbage when trying to cast byte struct to char type

I'm trying to write functions to access individual bits in a byte, word, dword, or qword with an object-oriented style in ANSI C, but I'm not getting the results I imagine I should be.我正在尝试编写函数以在 ANSI C 中以面向对象的样式访问字节、字、dword 或 qword 中的各个位,但我没有得到我想像的结果。 The bit type is declared like this:位类型声明如下:

typedef enum {F=0,T=1} bit;

The byte type is declared as a struct:字节类型被声明为结构:

typedef struct {
    bit b0:1;
    bit b1:1;
    bit b2:1;
    bit b3:1;
    bit b4:1;
    bit b5:1;
    bit b6:1;
    bit b7:1;
} byte;

I then use the function makebyte to create the byte.然后我使用 function makebyte 创建字节。 This is defined like so:这是这样定义的:

byte makebyte(bit b7, bit b6, bit b5, bit b4, bit b3, bit b2, bit b1, bit b0){
    byte out;
    out.b0=b0;
    out.b1=b1;
    out.b2=b2;
    out.b3=b3;
    out.b4=b4;
    out.b5=b5;
    out.b6=b6;
    out.b7=b7;
    return out;
}

Then I'm trying to convert this struct to a single byte char type, like this:然后我试图将此结构转换为单字节字符类型,如下所示:

char byteval(byte b){
    char *out=(char)&b;
    return out;
}

Then here I call it in my main function:然后在这里我在我的主要 function 中调用它:

int main(int argc, char **argv){
    byte k;
    k=makebyte(0,0,1,0,0,1,0,0);
    printf("%c\n\n", byteval(k));
}

Now, my problem is that I'm basically getting garbage printed to the terminal instead of the ASCII character I'm looking for, '$'现在,我的问题是我基本上将垃圾打印到终端而不是我正在寻找的 ASCII 字符,'$'

I'm trying To Make the code Clean and Readable, since I plan on releasing it in the Public Domain.我正在尝试使代码清晰可读,因为我计划在公共领域发布它。 Thanks in advance提前致谢

I would remove all the pointer punning and convert the function to macro.我将删除所有指针双关并将 function 转换为宏。 I would also use union for this purpose我也会为此目的使用联合

typedef union 
{
    struct 
    {
        unsigned char b0:1;
        unsigned char b1:1;
        unsigned char b2:1;
        unsigned char b3:1;
        unsigned char b4:1;
        unsigned char b5:1;
        unsigned char b6:1;
        unsigned char b7:1;
    };
    unsigned char uc;
} byte;

#define makebyte(b7, b6, b5, b4, b3, b2, b1, b0) \
    (byte){b0,b1,b2,b3,b4,b5,b6,b7}

int main(int argc, char **argv){
    byte k;
    k=makebyte(0,0,1,0,0,1,0,0);
    printf("%c\n\n", k.uc);
}

https://godbolt.org/z/8WEezYdWa https://godbolt.org/z/8WEezYdWa

You need to know that standard does not define order of bits in the bitfield struct.您需要知道标准没有定义位域结构中的位顺序。 gcc is consistent and does it your way. gcc是一致的,并按照您的方式行事。

This:这个:

char byteval(byte b){
    char *out=(char)&b;
    return out;
}

Is invalid for two reasons, actually the same reason twice.无效有两个原因,实际上是同一个原因两次。

On the first line, you're converting an address to a char type, then converting it back to a pointer type.在第一行,您将地址转换为char类型,然后将其转换回指针类型。 Converting a pointer to an integer type and back is only valid if the integer type is large enough to hold the pointer value, which in this case it's not.将指针转换为 integer 类型并返回仅在 integer 类型足够大以容纳指针值时才有效,在这种情况下它不是。

You should be converting to a char * :您应该转换为char *

char *out = (char *)&b;

On the second line, you're converting a pointer to a char again and returning it from the function.在第二行,您再次将指针转换为char并从 function 返回它。 You don't actually want to return the pointer, but what the pointer points to:您实际上并不想返回指针,而是指针指向的内容:

return *out;
char byteval(byte b){
    char *out=(char)&b;
    return out;
}

In this function you actually convert the ADDRESS of b to a 8-bit value, and then return this casted adress, but not the value.在这个 function 中,您实际上将 b 的 ADDRESS 转换为 8 位值,然后返回这个转换后的地址,但不返回值。 You should write:你应该写:

char byteval(byte b){
    char *out=(char *)&b;
    return *out;
}

And if you get problems of wrong value later on, you can refer to my kernel code:如果你以后遇到错误值的问题,你可以参考我的 kernel 代码:

typedef struct __attribute__((packed)) {
    uint64_t            : 16, // unused
                        : 24, // unused
                Type    : 4,
                S       : 1, // 0=system seg, 1=common seg
                DPL     : 2,
                P       : 1, // segment present
                        : 5, // unused
                L       : 1, // 0=dataseg, 1=codeseg
                        : 10; // unused
} segdesc64_T;

This structure takes up 64-bit and used by cpu, since my kernel works well, I think it is a valid declaration.这个结构占用 64 位并被 cpu 使用,因为我的 kernel 运行良好,我认为这是一个有效的声明。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM