小编cro*_*oyd的帖子

将缓冲区解释为结构的正确,可移植的方法

我的问题的背景是网络编程.假设我想通过网络在两个程序之间发送消息.为简单起见,假设消息看起来像这样,字节顺序不是问题.我想找到一种正确,可移植且有效的方法来将这些消息定义为C结构.我知道有四种方法:显式铸造,通过联合铸造,复制和编组.

struct message {
    uint16_t logical_id;
    uint16_t command;
};
Run Code Online (Sandbox Code Playgroud)

显式铸造:

void send_message(struct message *msg) {
    uint8_t *bytes = (uint8_t *) msg;
    /* call to write/send/sendto here */
}

void receive_message(uint8_t *bytes, size_t len) {
    assert(len >= sizeof(struct message);
    struct message *msg = (struct message*) bytes;
    /* And now use the message */
    if (msg->command == SELF_DESTRUCT)
        /* ... */
}
Run Code Online (Sandbox Code Playgroud)

我的理解是send_message不违反别名规则,因为byte/char指针可以为任何类型设置别名.但是,相反的情况并非如此,因此receive_message违反了别名规则,因此具有未定义的行为.

通过联盟投射:

union message_u {
    struct message m;
    uint8_t bytes[sizeof(struct message)];
};

void receive_message_union(uint8_t *bytes, size_t …
Run Code Online (Sandbox Code Playgroud)

c networking portability strict-aliasing

24
推荐指数
2
解决办法
9395
查看次数

透明和预制结构有什么区别?

正如标题所暗示的,我不明白定义结构时使用#:transparent和使用之间的区别#:prefab.该参考文献提到预制件涉及某种全球共享.

他们之间有什么区别?我应该在哪种情况下使用另一种?

racket

8
推荐指数
4
解决办法
1281
查看次数

压缩结构的大小,在C中具有小于8位的位字段的并集

在C中是否可以将以下结构的大小设为2?

#include <stdio.h>

struct union_struct {
    char foo;
    char bar : 2;
    union {
        char foobar1 : 6;
        char foobar2 : 6;
    };
};

int main(void)
{
    printf("size of union struct: %d\n", sizeof(struct union_struct));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出,用gcc编译:

size of union struct: 3

c sizeof packed bit-fields

4
推荐指数
1
解决办法
1192
查看次数

使用递归以恒定空间和线性时间向后打印链接列表

在我看来,应该可以使用递归和尾调用优化在恒定空间和线性时间内向后打印循环链表.但是,由于在进行递归调用后尝试打印当前元素,我遇到了困难.通过检查反汇编,我看到函数被调用而不是跳转到.如果我将其更改为向前打印而不是向后打印,则可以正确消除函数调用.

我已经看到了这个相关的问题,但我特别感兴趣的是使用递归和TCO来解决它.

我正在使用的代码:

#include <stdio.h>

struct node {
    int data;
    struct node *next;
};


void bar(struct node *elem, struct node *sentinel)
{
    if (elem->next == sentinel) {
        printf("%d\n", elem->data);
        return;
    }
    bar(elem->next, sentinel), printf("%d\n", elem->data);
}

int main(void)
{
    struct node e1, e2;
    e1.data = 1;
    e2.data = 2;
    e1.next = &e2;
    e2.next = &e1;
    bar(&e1, &e1);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

和编译

    $ g++ -g -O3 -Wa,-alh test.cpp -o test.o
Run Code Online (Sandbox Code Playgroud)

更新:使用Joni的答案解决,略微修改循环列表

void bar(struct node *curr, struct node *prev, struct …
Run Code Online (Sandbox Code Playgroud)

c c++ recursion tail-call-optimization

1
推荐指数
1
解决办法
740
查看次数