Estou estudando ISO/IEC 9899:2023 (E) 6.2.6 Representações de tipos: 6.2.6.1 Geral, parágrafo 6:
Certas representações de objetos não precisam representar um valor do tipo de objeto. Se tal representação for lida por uma expressão lvalue que não possui tipo de caractere, o comportamento é indefinido. Se tal representação for produzida por um efeito colateral que modifica todo ou parte do objeto por uma expressão lvalue que não possui tipo de caractere, o comportamento é indefinido. 54) Tal representação é chamada de representação sem valor.
Estou interessado na frase em destaque. Isso significa que, por exemplo:
union {
int i;
float f;
} u;
(onde, digamos, sizeof(int) == sizeof(float) == 4 e o tipo 'int' não tem bits de preenchimento),
a linha de código
u.i = some_value; // some_value has 'int' type
conterá comportamento indefinido? Afinal, com essa linha, posso (potencialmente) criar uma visualização sem o valor do membro 'f' do objeto de união (por exemplo, NaN).
Há duas perguntas possíveis aqui:
Tal atribuição produz necessariamente UB? Parece ser isso que você está propondo, mas não é plausível que o comitê pretendesse que toda e qualquer atribuição ao
int
membro de tal sindicato tivesse um comportamento indefinido. Mas,Tal atribuição poderia, em alguns casos, produzir UB? Essa é uma consideração mais interessante. Falaremos mais sobre isso em breve.
Se o tipo de implementação
float
permitir representações sem valor, então sim, por essa abordagem você poderia concebivelmente fazer comu.f
que contivesse uma representação sem valor. Seu.f
fossem lidos enquanto contivessem tal representação, isso definitivamente produziria UB, conforme a primeira parte da disposição que você citou.NO ENTANTO, o formato binário float32 do IEEE-754 não permite nenhuma representação sem valor. Em particular, seus NaNs não são representações sem valor para um
float
tipo que usa o formato IEEE-754 (como a maioria das implementações modernas de C). Embora os NaNs não representem membros do conjunto de números reais, eles são, ainda assim, valores bem definidos de seu tipo.Uma representação sem valor é aquela à qual o tipo de dado relevante não atribui nenhum significado. Por exemplo, considere um tipo inteiro com paridade incorporada e uma representação que não satisfaz a regra de paridade do tipo. Ou um tipo ponteiro que contém bits de sinalizador e um valor com uma combinação inválida desses sinalizadores.
Então, o que acontece se uma atribuição a um membro do sindicato fizer com que outro contenha uma representação sem valor?
Se supusermos que a provisão sobre a qual você está perguntando não é totalmente redundante, então acho que sim, devemos interpretar a especificação para atribuir UB a tal atribuição . Existem pouquíssimas coisas expressáveis em C que poderiam ter UB como resultado dessa provisão, mas que também não têm UB por outro motivo, como violar a regra de aliasing estrito ou ler uma representação sem valor. As possibilidades restantes são as únicas às quais sua provisão poderia se aplicar exclusivamente. Estas são todas as que eu criei:
(Observe que os tipos de estrutura e união não têm representações sem valor, embora seus membros possam ter.)
Não vejo uma boa razão para fazer distinção entre eles em relação à questão em questão.