C otimização de literais de string

apenas inspecionando o seguinte no gdb:

char *a[] = {"one","two","three","four"}; char *b[] = {"one","two","three","four"}; char *c[] = {"two","three","four","five"}; char *d[] = {"one","three","four","six"}; 

e eu recebo o seguinte:

 (gdb) pa $17 = {0x80961a4 "one", 0x80961a8 "two", 0x80961ac "three", 0x80961b2 "four"} (gdb) pb $18 = {0x80961a4 "one", 0x80961a8 "two", 0x80961ac "three", 0x80961b2 "four"} (gdb) pc $19 = {0x80961a8 "two", 0x80961ac "three", 0x80961b2 "four", 0x80961b7 "five"} (gdb) pd $20 = {0x80961a4 "one", 0x80961ac "three", 0x80961b2 "four", 0x80961bc "six"} 

Estou realmente surpreso que os pointers de string sejam os mesmos para palavras equivalentes. Eu teria pensado que cada string teria sido alocada sua própria memory na pilha, independentemente de ter sido o mesmo que uma string em outra matriz.

Este é um exemplo de algum tipo de otimização do compilador ou é um comportamento padrão para declaração de string desse tipo?

    É chamado de “agrupamento de strings”. É opcional no Microsoft Compilers, mas não no GCC. Se você desabilitar o agrupamento de cadeias de caracteres no MSVC, as cadeias “mesmas” nas matrizes diferentes serão duplicadas e terão endereços de memory diferentes e, portanto, ocuparão 50 (ou mais) bytes extras de seus dados estáticos.

    EDIT: gcc , de fato, tem uma opção, -fwritable-strings que desabilita o pool de strings. O efeito dessa opção é duplo: permite que os literais de string sejam sobrescritos e desabilita o pool de strings. Então, no seu código, definir esse sinalizador permitiria o código um pouco perigoso

     /* Overwrite the first string in a, so that it reads 'xne'. Does not */ /* affect the instances of the string "one" in b or d */ *a[0] = 'x'; 

    (Eu suponho que o seu a , b , c e d sejam declarados como variables ​​locais, que é o motivo de suas expectativas relacionadas à pilha.)

    Os literais de string em C têm duração de armazenamento estático. Eles nunca são alocados “na pilha”. Eles são sempre alocados na memory global / estática e vivem “para sempre”, ou seja, enquanto o programa é executado.

    Seus arrays a , b , c e d foram alocados na pilha. Os pointers armazenados nesses arrays apontam para memory estática. Sob essas circunstâncias, não há nada incomum sobre pointers para palavras idênticas serem idênticas.

    Se um compilador irá mesclar literais idênticos em um depende do compilador. Alguns compiladores ainda têm uma opção que controla esse comportamento. Os literais de string são sempre somente para leitura (e é por isso que é uma idéia melhor usar o const char * type para seus arrays), então não faz muita diferença se eles são mesclados ou não, até que você comece a confiar no ponteiro real valores.

    PS Apenas por curiosidade: mesmo se esses literais de string fossem alocados na pilha, por que você esperaria que literais idênticos fossem “instanciados” mais de uma vez?