AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 76921504
Accepted
Zoey Hewll
Zoey Hewll
Asked: 2023-08-17 20:24:33 +0800 CST2023-08-17 20:24:33 +0800 CST 2023-08-17 20:24:33 +0800 CST

enums de ferrugem em representações primitivas

  • 772

Recentemente, li Type Layout e fiquei surpreso com a descrição de repr primitivo em enums. Consulte Representação primitiva de enums com campos e Combinando representações primitivas de enums com campos e#[repr(C)] . Minha pergunta é: essas duas representações não são equivalentes?

Mais concretamente, considere esta enumeração:

enum WithFields {
    A(u16),
    B(u8, u16),
    C(u32, u32),
}

Se fosse anotado com repr(u8), teria a mesma representação UnionWithTagabaixo:

#[repr(C)]
union UnionWithTag {
    a: VariantA,
    b: VariantB,
    c: VariantC,
}

#[derive(Copy, Clone)]
#[repr(u8)]
pub enum Tag {
    A,
    B,
    C,
}

#[derive(Copy, Clone)]
#[repr(C)]
struct VariantA(Tag, u16);

#[derive(Copy, Clone)]
#[repr(C)]
struct VariantB(Tag, u8, u16);

#[derive(Copy, Clone)]
#[repr(C)]
struct VariantC(Tag, u32, u32);

Se fosse anotado com repr(C, u8), teria a mesma representação TaggedUnionabaixo:

#[repr(C)]
struct TaggedUnion {
    tag: Tag,
    payload: Union,
}

#[derive(Copy, Clone)]
#[repr(u8)]
pub enum Tag {
    A,
    B,
    C,
}

#[repr(C)]
pub union Union {
    a: PayloadA,
    b: PayloadB,
    c: PayloadC,
}

#[derive(Copy, Clone)]
#[repr(C)]
struct PayloadA(u16);

#[derive(Copy, Clone)]
#[repr(C)]
struct PayloadB(u8, u16);

#[derive(Copy, Clone)]
#[repr(C)]
struct PayloadC(u32, u32);

Não são TaggedUnione UnionWithTagidênticos no layout?

rust
  • 2 2 respostas
  • 37 Views

2 respostas

  • Voted
  1. Zoey Hewll
    2023-08-17T20:24:33+08:002023-08-17T20:24:33+08:00

    Pode parecer que eles seriam idênticos, mas a repr(C, u8)versão acabará com mais preenchimento do que a repr(u8)versão. Considere uma versão simplificada da enumeração, apenas com a Bvariante:

    enum WithFields {
        B(u8, u16),
    }
    

    como repr(u8):

    #[repr(C)]
    union UnionWithTag {
        b: VariantB,
    }
    
    #[derive(Copy, Clone)]
    #[repr(u8)]
    pub enum Tag {
        B,
    }
    
    #[derive(Copy, Clone)]
    #[repr(C)]
    struct VariantB(Tag, u8, u16);
    

    e como repr(C, u8):

    #[repr(C)]
    struct TaggedUnion {
        tag: Tag,
        payload: Union,
    }
    
    #[derive(Copy, Clone)]
    #[repr(u8)]
    pub enum Tag {
        B,
    }
    
    #[repr(C)]
    pub union Union {
        b: PayloadB,
    }
    
    #[derive(Copy, Clone)]
    #[repr(C)]
    struct PayloadB(u8, u16);
    

    Trabalharemos de baixo para cima para calcular os tamanhos gerais de TaggedUnione UnionWithTag.

    • PayloadBrequer um byte de preenchimento após o u8campo para alinhar corretamente o u16campo.
    • VariantBtodos os campos se encaixam sem preenchimento (a u8tag e o u8campo alinham perfeitamente o u16campo)
    • TaggedUnioné uma u8tag seguida por (uma união, contendo apenas) PayloadB, que tem align 2. Isso força um byte de preenchimento após a tag, para alinhá-la corretamente. No geral, tamanho 6, alinhamento 2. 2 bytes de preenchimento no geral.
    • UnionWithTagis (uma união, contendo apenas) VariantB, que tem tamanho 4, align 2. Nenhum preenchimento é usado.

    Esta não é realmente uma grande exploração de por que os layouts não são equivalentes, mas é uma prova por contradição eficaz de que eles realmente não são equivalentes.

    • 2
  2. Best Answer
    Colonel Thirty Two
    2023-08-18T00:55:38+08:002023-08-18T00:55:38+08:00

    Em ambos os exemplos, VariantC/ PayloadCtem um alinhamento de 4, enquanto o restante dos Variant/ Payloads tem um alinhamento de 2.

    No TaggedUnionexemplo, Uniontem alinhamento 4, que é o alinhamento máximo de seus membros. Portanto, TaggedUniondeve-se colocar três bytes de preenchimento entre a tag u8 e a união, em todos os casos, para satisfazer o pior caso de PayloadC.

    No entanto, os Variants têm mais flexibilidade permitida a eles. VariantAO membro u16 de precisa apenas de um alinhamento de 2, portanto, precisa apenas de um byte de preenchimento entre a tag e seus dados. VariantBpode empacotar firmemente seus dados sem qualquer preenchimento. VariantCainda precisa de 3 bytes de preenchimento. O padding extra, porém, volta quando eles são colocados no Union, mas está localizado no final da união.

    Portanto, como os s marcados internamente Variantsabem que incluirão uma tag, eles podem mover seus dados para mais perto da tag, mas como Payloados s podem existir como uma estrutura separada fora de sua tag, eles precisam ser alinhados, tornando o layout de duas abordagens -incompatível.

    • 1

relate perguntas

  • Existe uma maneira de simplificar a correspondência diretamente para Ok("VAL") em Result<String, VarError>

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    destaque o código em HTML usando <font color="#xxx">

    • 2 respostas
  • Marko Smith

    Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}?

    • 1 respostas
  • Marko Smith

    Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)?

    • 2 respostas
  • Marko Smith

    Por que as compreensões de lista criam uma função internamente?

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Marko Smith

    java.lang.NoSuchMethodError: 'void org.openqa.selenium.remote.http.ClientConfig.<init>(java.net.URI, java.time.Duration, java.time.Duratio

    • 3 respostas
  • Marko Smith

    Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)?

    • 4 respostas
  • Marko Smith

    Por que o construtor de uma variável global não é chamado em uma biblioteca?

    • 1 respostas
  • Marko Smith

    Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto?

    • 1 respostas
  • Marko Smith

    Somente operações bit a bit para std::byte em C++ 17?

    • 1 respostas
  • Martin Hope
    fbrereto Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}? 2023-12-21 00:31:04 +0800 CST
  • Martin Hope
    比尔盖子 Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)? 2023-12-17 10:02:06 +0800 CST
  • Martin Hope
    Amir reza Riahi Por que as compreensões de lista criam uma função internamente? 2023-11-16 20:53:19 +0800 CST
  • Martin Hope
    Michael A formato fmt %H:%M:%S sem decimais 2023-11-11 01:13:05 +0800 CST
  • Martin Hope
    God I Hate Python std::views::filter do C++20 não filtrando a visualização corretamente 2023-08-27 18:40:35 +0800 CST
  • Martin Hope
    LiDa Cute Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)? 2023-08-24 20:46:59 +0800 CST
  • Martin Hope
    jabaa Por que o construtor de uma variável global não é chamado em uma biblioteca? 2023-08-18 07:15:20 +0800 CST
  • Martin Hope
    Panagiotis Syskakis Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto? 2023-08-17 21:24:06 +0800 CST
  • Martin Hope
    Alex Guteniev Por que os compiladores perdem a vetorização aqui? 2023-08-17 18:58:07 +0800 CST
  • Martin Hope
    wimalopaan Somente operações bit a bit para std::byte em C++ 17? 2023-08-17 17:13:58 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve