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 / 78967806
Accepted
RogueGingerz
RogueGingerz
Asked: 2024-09-10 11:36:01 +0800 CST2024-09-10 11:36:01 +0800 CST 2024-09-10 11:36:01 +0800 CST

Compreendendo ponteiros opacos

  • 772

Peço desculpas se essa for uma pergunta óbvia, mas em C, Opaque Pointers são semelhantes a Java Interfaces? Como estou tentando entendê-los, estou interpretando-os de forma semelhante a Java interfaces no sentido de que eles estabelecem uma maneira obrigatória de interagir com o método/função? Então, se eu quisesse usar um Opaque Pointer, eu precisaria defini-lo em um arquivo .h enquanto eu o chamaria em um arquivo .c? Opaque pointers apenas definem a assinatura do método/função (no arquivo .h) enquanto o arquivo .c pega essas funções com essas assinaturas e as implementa.

c
  • 4 4 respostas
  • 133 Views

4 respostas

  • Voted
  1. Allan Wind
    2024-09-10T11:41:12+08:002024-09-10T11:41:12+08:00

    Não. Um ponteiro opaco é um design onde a implementação de um tipo (geralmente struct; opcionalmente typedef'ed) é oculta (encapsulada) do cliente. Este módulo pode instanciar o tipo da forma que achar melhor; frequentemente alocado dinamicamente (e desalocado). Os clientes precisam usar funções fornecidas pelo módulo para operar no ponteiro opaco.

    Você terá algo parecido com isto no seu arquivo de cabeçalho (interface):

    #ifndef FOO_H
    #define FOO_H
    
    typedef struct foo foo; // forward declaration
    foo *foo_create();
    void foo_destroy(foo *f);
    #endif
    

    e então o módulo implementa é:

    #include <stdlib.h>
    #include "foo.h"
    
    struct foo {
       int data;
    };
    
    foo *foo_create() {
       return calloc(1, sizeof(foo));
    }
    
    void foo_destroy(foo *f) {
       free(f);
    }
    
    
    • 6
  2. Chris
    2024-09-10T13:37:19+08:002024-09-10T13:37:19+08:00

    Como adendo à resposta de Allan Wind, ponteiros opacos dependem de um fato muito simples: todos os ponteiros struct têm o mesmo tamanho 1 , enquanto o tamanho das coisas para as quais eles apontam pode diferir muito.

    Em C, as funções devem saber os tamanhos de seus argumentos, variáveis ​​locais e valores de retorno. Portanto, em nenhum lugar do arquivo de cabeçalho podemos passar ou retornar um tipo de dado abstrato por valor .

    Como o tipo de dado real é definido no arquivo de implementação e, portanto, essa unidade de tradução está "ciente" do tamanho dos dados, podemos trabalhar em valores do tipo de dado abstrato diretamente ali.

    Isso permite que o tipo de dado seja definido de qualquer forma que desejarmos, desde que o arquivo de cabeçalho permaneça consistente. Melhorias podem ser feitas na implementação sem ter que ajustar como o tipo de dado é realmente usado por programas clientes.


    1 O tamanho de um ponteiro depende da plataforma de hardware e software.

    • 2
  3. Best Answer
    Mike Nakis
    2024-09-10T16:15:59+08:002024-09-10T16:15:59+08:00

    Estou interpretando-os de forma semelhante às interfaces Java no sentido de que eles estabelecem uma maneira obrigatória de interagir com o método/função

    Sua interpretação está no caminho certo, mas está faltando um ponto-chave: o motivo pelo qual usamos ponteiros opacos é para que possamos manter os detalhes da implementação da estrutura ocultos, para que possamos modificar essa estrutura em uma versão futura do nosso software sem quebrar o código existente que a utiliza.

    Essencialmente, a analogia com Java é a seguinte:

    • A declaração do ponteiro opaco, e de cada função que aceita (ou retorna) tal ponteiro opaco, corresponde a um interfaceem Java. (Observação: apenas as declarações. Não suas definições reais.)

    • A estrutura apontada pelo ponteiro opaco e o conjunto de definições de função são mais como uma classe Java concreta cuja implementsinterface contém apenas campos de membros privados, de modo que ninguém pode acessá-los.

    Outro conceito muito similar a ponteiros opacos é handles . A open()função retorna an intque é um identificador de arquivo , os read()métodos write(), e close()aceitam tal identificador como parâmetro. Esse número pode ser qualquer coisa, você não deve interpretá-lo de forma alguma ou esperar que seu valor esteja dentro de qualquer intervalo específico. Em teoria, em um sistema onde an inté grande o suficiente para conter um ponteiro para a estrutura, um identificador de arquivo pode, na verdade, ser um ponteiro struct que foi convertido para int. Na prática, é um índice em alguma tabela de FILE(ou similar) que é mantido inteiramente pela biblioteca padrão (ou pelo sistema operacional), então você não consegue vê-lo e, portanto, não pode estragá-lo.

    Esses são todos mecanismos muito primitivos para atingir o encapsulamento que as pessoas usavam antes da invenção da Programação Orientada a Objetos. E como não havia princípios orientadores e nenhuma maneira padrão de fazer as coisas, as pessoas estavam fazendo hacks aqui e ali, que violavam o encapsulamento de várias maneiras.

    • Por exemplo, a biblioteca padrão C poderia ser tratada FILE como um ponteiro opaco, mas por algum motivo a maioria das implementações opta por não fazê-lo, porque elas definem o structfor FILEem um arquivo de cabeçalho que você pode realmente #include. (Veja Stack Overflow: Onde FILE é definido no Unix )

    • Como outro exemplo, você não deve interpretar o valor de um identificador de arquivo, mas os identificadores de arquivo para os fluxos padrão (entrada, saída, erro) têm valores muito conhecidos publicamente, que são, essencialmente, nada mais que números mágicos .

    • 2
  4. Luis Colorado
    2024-09-11T02:37:58+08:002024-09-11T02:37:58+08:00

    Peço desculpas se esta for uma pergunta óbvia, mas em C, os Ponteiros Opacos são semelhantes às Interfaces Java?

    Não, é algo completamente sem relação.

    Ponteiros opacos são ponteiros para s especificados incompletamente (externamente) struct, usados ​​para esconder a representação interna da estrutura. Melhor dito, eles são ponteiros para tipos definidos incompletamente (uma estrutura de campo não especificada, ou um array de comprimento não especificado). Dessa forma, o ponteiro pode ser usado, mas não os dados apontados, pois o conteúdo da estrutura é desconhecido para o compilador.

    typedef struct hash_table *hash_table_p;
    

    No código acima, definimos o tipo hash_table_pcomo um ponteiro para uma estrutura indefinida. Esse ponteiro pode ser usado por rotinas de tabela de hash como um dado opaco que é fornecido ao usuário, apenas para passá-lo de volta para as rotinas que manipulam os aspectos internos da estrutura como campos externamente inacessíveis.

    Como ponteiros para tipos não são intercambiáveis, referências de ponteiros não podem ser intermisturadas, fazendo com que os ponteiros para struct hash_tablesempre tenham que ser inicializados com uma referência de tabela hash autêntica (algo que, se você for cuidadoso, sempre será garantido pelo compilador). Um ponteiro para um tipo diferente nunca será compatível (exceto se você o converter) com um ponteiro para um tipo diferente. A única exceção é o ponteiro para voidque é compatível com qualquer outro tipo de ponteiro.

    Você pode deixar externamente a declaração como tal, e no código de implementação, fornecer uma definição completa de struct hash_table. O compilador permitirá que você declare quantos ponteiros do tipo referenciado, mas os internos dos dados são ocultos para o código externo. A struct hash_tableestrutura é definida normalmente em um hash_tableP.harquivo include (que também inclui o externo) e assim C pode emular as unidades de compilação DEFINITION MODULEand IMPLEMENTATION MODULEda linguagem Modula-2 (ou o packageand package bodydo Ada)

    Interfaces Java, por outro lado, são conjuntos de declarações de métodos que permitem que classes orientadas a objetos façam implementisso, assim chamado, interface, e sejam tratadas como objetos de uma classe que implementa todos esses métodos. Isso de alguma forma define uma classe como objeto, mas sem derivá-la de outra classe.

    C não pode associar um conjunto de declarações de procedimentos a um tipo, para fazer com que apenas instâncias que implementam esses procedimentos sejam consideradas pertencentes a um único tipo (se um tipo puder ser comparado a uma classe), então não há figura semelhante em C ao modelo de interface Java.

    • 1

relate perguntas

  • Multiplicação mais rápida que *

  • Usando uma macro para comprimento de string no especificador de formato scanf () em C

  • Como você pode definir o tipo de dados de #define para long double?

  • Ponteiros const incompatíveis

  • Mudança de cor não gradual no OpenGL

Sidebar

Stats

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

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle?

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Quando devo usar um std::inplace_vector em vez de um std::vector?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Marko Smith

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

    • 1 respostas
  • Martin Hope
    Aleksandr Dubinsky Por que a correspondência de padrões com o switch no InetAddress falha com 'não cobre todos os valores de entrada possíveis'? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer Quando devo usar um std::inplace_vector em vez de um std::vector? 2024-10-29 23:01:00 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST
  • Martin Hope
    MarkB Por que o GCC gera código que executa condicionalmente uma implementação SIMD? 2024-02-17 06:17:14 +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