O padrão de mandato de um lvalue-para-rvalue conversão da variável ponteiro quando a aplicação de indireção?

StackOverflow https://stackoverflow.com//questions/21053273

Pergunta

TL;DR

Dado o seguinte código:

int* ptr;
*ptr = 0;

não *ptr necessitam de uma lvalue-para-rvalue conversão de ptr antes de aplicar o engano?

A norma abrange o tema da lvalue-para-rvalue em muitos lugares, mas não parece especificar informações suficientes para determinar se o * operador de exigir tal conversão.

Detalhes

O lvalue-para-rvalue a conversão é coberto em N3485 na seção 4.1 Lvalue-para-rvalue de conversão parágrafo 1 e diz (ênfase minha vai para a frente):

Um glvalue (3.10) de uma não-função, não do tipo de matriz T pode ser convertido para um prvalue.53 Se T é um tipo incompleto, um programa que necessita esta conversão é mal-formada.Se o objeto ao qual o glvalue refere-se não é um objeto do tipo T, e não é um objeto de uma tipo derivado a partir de T, ou se o objeto não é inicializado, um programa que este necessita de conversão tem comportamento indefinido.[...]

Por isso, não *ptr = 0; exigem esta conversão?

Se nós vá para a seção 4 parágrafo 1 ele diz:

[...]Um padrão de conversão será aplicado a uma expressão se necessário para convertê-lo para um destino necessário de tipo.

Então, quando é que necessário?Se olharmos para a seção 5 Expressões o lvalue-para-rvalue a conversão é mencionada no parágrafo 9 que diz:

Sempre que um glvalue expressão aparece como um operando do operador que espera um prvalue para que operando, o lvalue-para-rvalue (4.1), matriz-para-ponteiro (4.2), ou função-para-ponteiro (4.3) padrão as conversões são aplicadas para converter a expressão de um prvalue.[...]

e o parágrafo 11 que diz:

Em alguns contextos, uma expressão aparece apenas por seus efeitos colaterais.Tal expressão, é chamado de um descartada-expressão de valor.[...] O lvalue-para-rvalue de conversão (4.1) é aplicada se, e somente se, a a expressão é um lvalue volátil-tipo qualificado e é um dos o seguinte [...]

nem o parágrafo parece aplicar-se a este código de exemplo e 5.3.1 Operadores unários parágrafo 1 ele diz:

O operador unário * operador executa indireção:a expressão que ele é aplicada deve ser um ponteiro para um tipo de objeto, ou um ponteiro para um tipo de função e o resultado é um lvalue referindo-se ao objeto ou função para o qual a expressão de pontos.Se o tipo de expressão é "ponteiro para T," o tipo do resultado é "T". [ Nota:indireção através de um ponteiro para um tipo incompleto (excepto cv void) é válido.O lvalue assim obtido pode ser usado de forma limitada (para inicializar um de referência, por exemplo);este lvalue não deve ser convertido para um prvalue, consulte 4.1.—nota final ]

ele não parece requerer o valor do ponteiro e não vejo qualquer exigências para a conversão do ponteiro aqui eu estou faltando alguma coisa?

Por que isso importa?

Eu vi uma resposta e comentários em outras perguntas que afirmam que o uso de um ponteiro não inicializado é um comportamento indefinido devido a necessidade de um lvalue-para-rvalue conversão de ptr antes de aplicar o endereçamento indireto.Por exemplo: Onde exatamente padrão de C++ dizer remover a referência de um ponteiro que não foi inicializado é um comportamento indefinido? faz esse argumento, e eu não posso conciliar o argumento com o que é apresentado em qualquer uma das recentes versões de rascunho de padrão.Desde que eu tenho visto isso várias vezes, eu queria ter um esclarecimento.

A prova real de comportamento indefinido não é tão importante, pois como eu disse nos vinculada a pergunta acima, temos outros maneira de obter um comportamento indefinido.

Foi útil?

Solução 2

Eu ter convertido a seção atualização na minha pergunta para uma resposta pois neste ponto parece ser a resposta, ainda que uma insatisfatória que a minha pergunta é irrespondível:

dyp indicou-me dois relevantes segmentos que abrangem muito semelhante à terra:

O consenso parece ser o de que a norma é mal especificado e, portanto, não pode fornecer a resposta que eu estou procurando, José Mansfield postou um relatório de defeitos sobre essa falta de especificação, e parece que é ainda aberto e não está claro quando ele pode ser esclarecida.

Existem alguns argumentos de senso comum para ser feita intenção da norma.Pode-se argumentar Logicially, um operando é um prvalue se a operação requer a utilizar o valor do operando.Outro argumento é que, se olharmos para trás, para o C99 projecto de norma diz um lvalue para rvalue conversão é feita por padrão e as exceções são observadas.A seção relevante do projecto de C99 padrão é 6.3.2.1 Lvalues, matrizes, e a função de designadores parágrafo 2 que diz:

Exceto quando for o operando do operador sizeof, o unário & operador, o operador++, -- o operador ou o operando esquerdo do .o operador ou um operador de atribuição, um lvalue que não tem o tipo de matriz é convertido para o valor armazenado no objeto designado (e não é um lvalue).[...]

o que, basicamente, diz que, com algumas exceções, um operando é convertido para o valor armazenado e desde indireção não é uma exceção se esta é esclarecida também ser o caso em C++ bem, então, seria, de facto, fazer a resposta para a minha pergunta sim.

Como eu tentava esclarecer a prova do comportamento indefinido era menos importante do que esclarecer se um lvalue-para-rvalue a conversão é obrigatória.Se queremos provar comportamento indefinido temos métodos alternativos.Jerry abordagem do senso comum e que indireção requer que a expressão ser um ponteiro para um objeto ou uma função e um valor indeterminado só por acidente aponte para um objeto válido. Em geral, o projeto de C++ padrão não dar uma explícita declaração para dizer usando indeterminado valor é indefinido, ao contrário do C99 projecto de norma Em C++11 e volta a norma não dar uma explícita declaração para dizer usando indeterminado valor é indefinido.Com exceção de iteradores e, por extensão, ponteiros, temos o conceito de valor singular e nos é dito na seção 24.2.1 que:

[...][ Exemplo:Após a declaração de um ponteiro não inicializado x (como int* x;), x deve sempre ser considerado ter um único valor de um ponteiro.exemplo ] [...] Dereferenceable valores são sempre não-singular.

e:

Um erro de iteração é um iterador que pode ser singular.268

e a nota de rodapé 268 diz:

Esta definição aplica-se a ponteiros, desde que os ponteiros são os iteradores.O efeito de remover a referência de um iterador que foi invalidado é indefinido.

Em C++1y as alterações de idioma e temos uma explícita declaração de fazer o uso de um valor intermediário indefinido, com algumas exceções estreitas.

Outras dicas

Eu acho que você está se aproximando, ao invés de partir de um ângulo oblíquo, por assim dizer.De acordo com o §5.3.1/1:

Os unários * operador executa indireção:a expressão à qual ele é aplicado, deve ser um ponteiro para um tipo de objeto, ou um ponteiro para um tipo de função e o resultado é um lvalue referindo-se ao objeto ou função para que a expressão de pontos.Se o tipo da expressão é "ponteiro para T," o tipo do resultado é "T".

Embora isso não falar sobre o lvalue-para-rvalue conversão, ele requer que a expressão ser um ponteiro para um objeto ou função.Um ponteiro não inicializado não (exceto, talvez por acidente) ser qualquer coisa, de modo que a tentativa de desreferência dá comportamento indefinido.

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