Pergunta

Eu estou tentando construir cairomm para gtkmm no Windows usando mingw. quebras de compilação em uma chamada de função que tem um parâmetro que faz um reinterpret_cast de um bool para a * vazio.

cairo_font_face_set_user_data(cobj(), &USER_DATA_KEY_DEFAULT_TEXT_TO_GLYPHS, reinterpret_cast<void*>(true), NULL);

Este é o lugar onde as quebras de código, ea razão é "reinterpret_cast inválido do bool para void *". Por que isso está acontecendo e como posso modificar esta linha para obtê-lo para compilar? Precisa de ajuda

Foi útil?

Solução

Eu vejo este é os dados do usuário e você tem controle sobre o que é feito com o valor, lançou o bool para um int em primeiro lugar: reinterpret_cast<void *> (static_cast<int> (true)). Fazendo isso faz sentido em que o parâmetro void * toma o lugar do modelo de funções nesta biblioteca ANSI-C. Tudo que você precisa é de um valor true / false. Assim, não deve haver perigo na codificação temporariamente este como um ponteiro, enquanto ele está bem documentada como tal. Realmente, você seria melhor fora com este:. reinterpret_cast<void *> (1) ou reinterpret_cast<void *> (+true)

Outras dicas

Parece que ele deve funcionar, de acordo com o padrão. Seção 3.9.1-7 diz bool é um tipo integral, e 5.2.10-5 diz um valor do tipo integral pode ser explicitamente convertido para um ponteiro usando reinterpret_cast. Parece que o seu compilador não é totalmente padrão.

Você poderia fugir com a mudança do "verdadeiro" a um 1? A conversão entre números inteiros e tipos de ponteiro é uma tradição antiga e desonrosa em C e, portanto, C ++, e seria surpreendente para encontrar um compilador que não iria fazê-lo.

Ou, se você realmente tem que fazer isso, tente (void *) true. Em seguida, lave suas mãos.

reinterpret_cast é um má idéia . Conte-nos mais sobre o problema que você está tentando resolver, e talvez nós vamos encontrar uma solução sem recorrer a reinterpretar. Por que você deseja converter bool para void *?

A única compilador Eu tenho que reclama este é GCC (MinGW com GCC 3.4.5) - e eu não sei por que. O padrão parece indicar claramente isso é permitido:

3.9.1 tipos Fundamentais

...

Tipos bool, char, wchar_t, eo assinado e tipos inteiros não assinados são chamados coletivamente de tipos integrais.

5.2.10 reinterpretar elenco:

...

Um valor de tipo integral ou tipo de enumeração pode ser explicitamente convertido para um ponteiro.

Dito isso, de Monjardin solução alternativa de usar reinterpret_cast<void *> (static_cast<int> (true)) ou reinterpret_cast<void *> (1) soluções alternativas razoáveis.

Ele falha porque o elenco não faz sentido - você está tomando um verdadeiro falso valor booleano /, e pedindo ao compilre interpretar isso como um ponteiro, o que em termos contundentes é um local de memória. Os dois Arent mesmo remotamente relacionado.

Tente uma versão mais recente do seu compilador. Eu apenas testada e esse elenco funciona em pelo menos gcc 4.1 e acima. Eu não sei exatamente como versões gcc mapear para versões MinGW embora.

Em algumas situações, é altamente desejável ter o compilador avisar ou erro no código como reinterpret_cast<void*>(true), mesmo que este código é C aparentemente legal ++. Por exemplo, ele ajuda a portar para plataformas de 64 bits.

Lançando um ponteiro de 64 bits em um tipo integral que é menor do que um ponteiro (como int ou bool) é muitas vezes um erro: você está truncar o valor do ponteiro. Além disso, a especificação C ++ não parece garantia de que você pode diretamente converter um ponteiro para um tipo integral menor (ênfase adicionada):

5.2.10.4. Um ponteiro pode ser explicitamente convertido para qualquer tipo integral grande o suficiente para segurá-la . A função de mapeamento é definido pela implementação.

Da mesma forma, lançando um tipo integral menor em um ponteiro de 64 bits (como acontece com reinterpret_cast<void*>(true)) é muitas vezes um bug bem: o compilador tem de preencher bits superiores do ponteiro com alguma coisa; ele zero preenchimento ou sign-estender? A menos que você está código específico da plataforma de escrita de baixo nível de memória mapeada I / Acesso O ou DMA, você geralmente não quer fazer isso em tudo, a menos que você está fazendo algo hacky (como encher um booleano em um ponteiro ). Mas a especificação C ++ não parece dizer muito sobre este caso diferente do que é definido pela implementação (nota de rodapé omitida):

5.2.10.5. Um valor de tipo integral ou tipo de enumeração pode ser explicitamente convertido a um ponteiro. *

Um ponteiro convertidos para um número inteiro de tamanho suficiente (se tal existir sobre a aplicação) e de volta para o mesmo tipo de ponteiro terá o seu valor original; mapeamentos entre ponteiros e inteiros são de outra maneira definido pela implementação.

@monjardin reinterpret_cast<void*>(static_cast<int>(true)) sugeriu. Se a origem do erro foi a incompatibilidade entre tamanho e o tamanho do ponteiro do tipo integral, então isso vai funcionar na maioria das plataformas de 32 bits (onde ambos int e void* são 32 bits), mas falham na maioria das plataformas de 64 bits (onde int é de 32 bits e é void* 64 bits). Nesse caso, substituindo int nesta expressão com um tipo inteiro ponteiro de tamanho, tais como uintptr_t ou DWORD_PTR (no Windows) deve funcionar, uma vez que as conversões entre bool e ponteiro de tamanho inteiros são permitidos, e por isso são as conversões entre inteiros ponteiro de tamanho e ponteiros.

As versões posteriores do GCC têm a seguinte supressão aviso opções , mas não para C ++ :

-Wno-int-a-ponteiro-cast (C e só Objective-C)
avisos Suprimir de moldes para tipo de ponteiro de um inteiro de tamanho diferente.

-Wno-ponteiro-a-int-cast (C e só Objective-C)
avisos Suprimir de moldes de um ponteiro para um tipo inteiro de um tamanho diferente.

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