validade do programa; tempo de vida e escopo da variável definida dentro do loop
Considere o programa
#include <stdio.h>
int main(void) {
for (int curr = 0; curr < 3; curr++) {
int prev;
if (curr) {
printf("%d\n", prev); //valid; prev has 0 or 1
}
prev = curr;
}
}
É válido?
Qual é a vida útil e o escopo de prev?
Haverá 3
prevs distintos com tempo de vida e escopo dentro doforloop.
Osprevs distintos podem (mas não são obrigados a) compartilhar o mesmo endereço.
O programa não é válido.Haverá 3
prevs com vida útil e escopo dentro doforloop.
Osprevs irão compartilhar o mesmo endereço, comportando-se como se definidos comstatic.
O programa é válido.Haverá 1
prev, como se fosse definido fora doforloop.
O programa é válido.
Nota: pergunta originada durante a discussão sobre esta resposta
Respostas
Ao usar o C89, ou ao usar apenas os construtos de loop fornecidos em versões posteriores do C, é impossível para o código chegar a um local acima da declaração de um objeto automático durante o tempo de vida do objeto. C99, no entanto, adicionou a capacidade de usar gotopara transferir o controle de um ponto abaixo de uma declaração para um ponto acima dentro do tempo de vida do objeto declarado por meio disso. Não tenho certeza de até que ponto quaisquer programas não planejados dependem do fato de que usar gotopara transferir o controle acima da declaração de um objeto não-VLA não encerra sua vida útil, mas o Padrão exige que as implementações levem em consideração tal comportamento, por exemplo,
void test(void)
{
int pass=0;
int temp;
int *p;
int result;
firstPass:
if (pass)
{
temp = *p;
goto secondPass;
}
pass++;
int q=1;
p=&q;
q++;
goto firstPass;
secondPass:
return temp + q;
}
o tempo de vida de qcomeçaria quando o código fosse inserido teste se estenderia por toda a execução da função, mesmo se o código se ramificasse para um ponto acima da declaração. Se a execução atinge uma declaração com um inicializador, o valor do objeto é atribuído naquele momento; se atingir uma declaração sem um inicializador, o valor do objeto se tornará indeterminado naquele momento, mas se o código pular a declaração, o objeto reterá seu valor.
Três prevs diferentes e distintos que não (precisam) compartilhar endereço ou valor.
Em cada loop, um diferente prevserá "criado" e "excluído".
1
prev é tratada como uma variável automática que tem um escopo dentro da instância do loop
Isso significa que, a cada iteração, todas as variáveis automáticas são liberadas e readquiridas quando o loop é executado novamente.
Na verdade, a definição de for-loopé que a instrução for é executada a cada vez (incrementando a variável, neste caso) e testando a condição, portanto, mesmo olhando para o código, você pode ver que o escopo entre colchetes termina cada vez que o loop termina.
Qualquer garantia do endereço no qual a variável local é alocada (ou um registro contendo o valor) é nula. É totalmente dependente da implementação.