Por que são compostos literais em C modificáveis

normalmente associamos 'não modificável' ao termo literal

char* str = "Hello World!";
*str = 'B';  // Bus Error!

No entanto, ao usar literais compostos, descobri rapidamente que eles são completamente modificáveis (e travando no código da máquina gerada, você vê que eles são empurrados na pilha):

char* str = (char[]){"Hello World"};
*str = 'B';  // A-Okay!

estou a compilar com clang-703.0.29. Esses dois exemplos não deveriam gerar o mesmo código de máquina? Um literal composto é mesmo literal, se é modificável?

editar: um exemplo ainda mais curto iria be:

"Hello World"[0] = 'B';  // Bus Error!
(char[]){"Hello World"}[0] = 'B';  // Okay!
Author: hgiesel, 2016-04-17

1 answers

Um literal composto é um valor lvalue e os valores dos seus elementos são modificáveis. No caso de

char* str = (char[]){"Hello World"};
*str = 'B';  // A-Okay!  
Estás a modificar um literal composto que é legal.

C11-§6.5.2.5/4:

Se o nome do tipo indicar um array de tamanho desconhecido, o tamanho é determinado pela lista de inicialização, conforme especificado em 6.7.9, e o tipo do literal composto é o do tipo de array completo. Caso contrário (quando o nome do tipo especifica um tipo de objecto) , o tipo of the compound literal is that specified by the type name. em ambos os casos, o resultado é um valor lvalue .

Como pode ser visto que o tipo de composto literal é um tipo de array completo e é lvalue, por isso é modificável ao contrário de literais de cadeias de caracteres

A norma também menciona que

§6.5.2.5/7:

Literais de texto, e literais compostos com tipos qualificados de const, não necessitam de designar distintos objecto.101

Além disso, diz:

11 exemplo 4 um literal composto apenas para leitura pode ser especificado através de construções como:

(const float []){1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6}   

12 exemplo 5 as três expressões seguintes têm significados diferentes:

"/tmp/fileXXXXXX"
(char []){"/tmp/fileXXXXXX"}
(const char []){"/tmp/fileXXXXXX"}

A primeira sempre tem duração de armazenamento estático e tem array tipo de char, mas não precisa ser modificável; as duas últimas têm duração de armazenamento automático quando ocorrem dentro do corpo de uma função, e o primeiro destes dois é modificável .

13 exemplo 6 como literais de cordas, literais compostos qualificados de const podem ser colocados em memória apenas de leitura e podem até ser partilhados. Por exemplo,

(const char []){"abc"} == "abc"

Pode produzir 1 Se o armazenamento dos literais for partilhado.

 6
Author: haccks, 2016-04-17 12:29:11