Pergunta

Suponha que eu tenho uma função

void foo(char *)

O que, internamente, precisa tratar sua entrada como um bloco de bytes terminados por nul (por exemplo, é uma função de hash em strings). Eu poderia lançar o argumento para unsigned char* na função. Eu também poderia mudar a declaração para

void foo(unsigned char *)

Agora, dado isso char, signed char e unsigned char são três tipos diferentes, isso constituiria uma mudança de interface, sob qualquer definição razoável do termo "interface" em C?

(Esta questão pretende resolver um discussão levantado por outra questão. Eu tenho minhas opiniões, mas não aceitarei uma resposta até que alguém apareça como um "vencedor" pelos votos dos outros.)

Foi útil?

Solução

De acordo com ISO/IEC 9899: TC3,

  • Chamar uma função através de uma expressão de tipo incompatível é um comportamento indefinido (6.5.2.2 §9)
  • Os tipos de função compatíveis devem ter tipos de parâmetros compatíveis (6.7.5.3 §15)
  • Os tipos de ponteiros compatíveis devem apontar para os tipos compatíveis (6.7.5.1 §2)
  • char, signed char e unsigned char são diferentes tipos básicos (6.2.5 §14) e, portanto, incompatíveis (6.2.7 §1), que também é explicitamente mencionado na nota de rodapé 35 na página 35

Então, sim, isso é claramente uma alteração na interface de programação.

No entanto, como char *, signed char * e unsigned char * terá representações idênticas e requisitos de alinhamento em qualquer implementação sã do idioma C, a interface binária permanecerá inalterada.

Outras dicas

É sim. O código do cliente que compilou anteriormente não será mais compilar (ou de qualquer maneira provavelmente gerará novos avisos), então essa é uma mudança de quebra.

Eu escolho "C - nenhuma das opções acima".

Embora não seja uma resposta direta para a pergunta que você realmente fez, a solução certa para a situação parece bastante simples e óbvia para mim: você realmente não deveria estar usando nada disso.

Pelo menos IMO, você tem um bom motivo para fazer o contrário, sua função deve aceitar um void * ou (de preferência) void const *. O que você está procurando é basicamente um ponteiro opaco, e é exatamente isso void * fornece. O usuário não precisa saber nada sobre os internos da sua implementação e, uma vez que qualquer outro tipo de ponteiro se converterá para void * Implicitamente, é uma das poucas possibilidades que também não quebra nenhum código existente.

Um char* se converte implicitamente em um char não assinado*?

  • Sim - você não quebrou sua interface
  • Não - você vazou implementação
    detalhes.

Não, não é. Qualquer alteração no código do cliente é trivial (especialmente se for apenas para evitar um aviso) e, na prática, em praticamente qualquer implementação C, você descobrirá que nem precisar char* e unsigned char* será passado exatamente da mesma maneira na convenção de chamada.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top