Pergunta

É o seguinte seguro conversão?

int b[10][10];
char *x;
int a[]={0,1,2,3,4,5,6,7,8,9};

for(int i=0;i<10;i++)
  for(int j=0;j<10;j++)
    b[i][j]=a[i];

for(x=(char *)&b[0];x<=(char *)&b[9][9];x+=sizeof(a+1)) // Problem lies here!
    printf("%d\n",*x);

Eu não acho que a conversão acima no circuito for é seguro (eu acho que é dependente de plataforma). Por favor corrija-me se eu estiver errado. Estou surpreso porque os compila o código, sem dar qualquer aviso, mesmo quando compilado usando as opções -Wall -pedantic no gcc.

Foi útil?

Solução

Essa coisa toda tem uma chance de ser legal para um e uma única razão: o objeto de matriz int 2D é reinterpretado como um array de objetos char. Embora, em geral de memória caso reinterpretação leva a um comportamento indefinido, a especificação da linguagem permite explicitamente "matriz de [assinados / não assinado] char" reinterpretações para objetos de qualquer tipo.

No entanto, um problema de segurança formal ainda está lá. O idioma não garante que qualquer padrão de bits é um valor válido do tipo char. Sua tentativa de ler a memória reinterpretado através do tipo char teoricamente pode causar um comportamento indefinido se encontra representação armadilha para char. Para ser seguro aqui você tem que usar o tipo unsigned char, que é o único tipo que não tem representações armadilha. Claro, uma plataforma com um char prendendo pode ser chamado de forma segura "exótico".

Enquanto isso, seu sizeof(a + 1) não parece fazer qualquer sentido. a + 1 é uma expressão do tipo int *. Por que você iria querer usar o tamanho do ponteiro para incrementar seu valor x neste caso não é claro para mim. O que você estava tentando alcançar?

Quanto à ausência de avisos ... Eu não esperaria o compilador para emitir quaisquer avisos aqui. GCC frequentemente adverte sobre tipo trocadilhos (aka reinterpretação de memória), mas desde reinterpretações char são explicitamente permitido (como eu disse acima), não há nenhum aviso aqui. Além disso, conversões explícitas geralmente tendem a suprimir todos os avisos, uma vez que são uma maneira de dizer ao compilador que você realmente quer fazer algo, independentemente de quão errada e / ou perigoso que poderia ser.

Outras dicas

um molde de qualquer tipo de ponteiro para char * é expressamente permitida pela linguagem C. assim a maioria isso é bom.

for(x=(char *)&b[0]; x <= (char *)&b[9][9]; x += sizeof(a+1))  

A primeira parte é muito bem x = (char*)&b[0]; estabelece um ponteiro char para o início da matriz. O teste também é bem x <= (char *)&b[9][9] será verdade enquanto x pontos dentro do array.

x += sizeof(a+1) é a parte duvidoso. Na maioria das arquiteturas de CPU de 32 bits sizeof (int *) apenas acontece para ser o mesmo que sizeof (int), de modo que este código irá provavelmente trabalho , mas apenas por acidente.

Estou certo o que se pretendia era x += sizeof(a[0]) ou x += sizeof(b[0]), mas desde que o código realmente fez o que se pretendia, ninguém percebeu o erro.

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