Operador de incremento de matriz em C

Eu não entendo os resultados do seguinte código:

#include  #include  int main() { int a[4]={1, 3, 5, 6}; //suppose a is stored at location 2010 printf("%d\n", a + 2); printf("%d", a++); return 0; } 

Por que a segunda function printf produz o seguinte erro?

error: lvalue required as increment operand

Parte 1:

Os nomes das matrizes são constantes (lvalue não modificável), você pode adicionar valor ao nome da matriz, mas não pode modificá-lo.

A expressão a + 2 não modifica a si mesma, mas quando você faz a++ que é equivalente a a = a + 1 tente modificar o nome da matriz –lvalue error. A expressão a++ em segundo printf está errada – um exemplo de erro de fase semântico. leia os seguintes padrões de idioma:

6.3.2.1 Lvalores, arrays e designadores de function

724 Um lvalue modificável é um lvalue que não possui um tipo de matriz, não possui um tipo incompleto, não possui um tipo com qualificação constante e, se for uma estrutura ou união, não possui nenhum membro (incluindo, recursivamente, qualquer membro ou elemento de todos os agregados ou uniões contidos) com um tipo const-qualificado.

729 Exceto quando é o operando do operador sizeof ou o unary & operator, ou é um literal de string usado para inicializar um array, uma expressão que possui o tipo “array of type” é convertida em uma expressão com o tipo “pointer to type” que aponta para o elemento inicial do object da matriz e não é um lvalue .

Parte 2:

Note que os nomes das matrizes na maioria das expressões decaem no endereço do primeiro elemento (leia algumas exceções em que o nome da matriz não decai em um ponteiro para o primeiro elemento respondido normalmente por @H 2 CO 3 ).

Quando você faz a + 2 o resultado é o endereço do terceiro elemento (ou endereço do elemento no índice 2 ). Então, a + 2 é o mesmo que &a[2] É endereço e não valor no índice.

Para imprimir o endereço, use %p vez de %d e o endereço de typecast em void* seguinte forma:

 printf("address (a + 2) = %p , &a[2] = %p", (void*)(a + 2), (void*)(&a[2])); 

Para imprimir o valor, você precisa do operador de defesa * como segue:

 printf("address *(a + 2) = %d , a[2] = %d", *(a + 2), a[2]); 

Parte 3:

suponha que a é armazenado no local de 2010, é a saída da primeira function printf 2012?

Não, a aritmética do ponteiro é diferente da aritmética inteira. Como sabemos, o nome da matriz decai para o endereço do primeiro elemento na maioria das expressões Então, quando você faz a + 2 o valor é o endereço do terceiro elemento que está no índice 2 . Então, suponha que se int tamanho em seu sistema é de 4 bytes, em seguida, a + 2 stat apontando para a localização 2018 de acordo com a suposição de que a valor de endereço é 2010.

Para entender ler 10.2 Ponteiros e Arrays; Aritmética de ponteiro e aritmética de ponteiro .

 int a[4]={1,3,5,6}; printf("%d\n",a++); // you should not modify array name illegal in c 

Suponha que pa seja um ponteiro inteiro

A pointer is a variable, so pa=a and pa++ are legal. But an array name is not a variable; constructions like a=pa and a++ are illegal.

Eu acho que a primeira saída será baseada em como o tipo inteiro é representado em seu computador. Se um único inteiro ocupa 4 bytes na memory, a saída deve ser 2018, ou seja, 2010 + 2 * 4. O segundo printf pode causar um erro de compilation.

Primeiro, este programa invoca um comportamento indefinido e não me sinto desanimado com tantas respostas que nenhuma delas menciona isso. Em ambas as chamadas do printf , seu argumento é um ponteiro, mas você está especificando o formato como %d que espera e int deve ser% p . O padrão de rascunho C99 na seção 7.19.6.1 A function fprintf à qual a seção printf se refere de volta para o parágrafo de seqüência de formatação 9 diz:

Se uma especificação de conversão for inválida, o comportamento é indefinido. […]

De volta à sua pergunta, a expressão a a++ produz um erro porque o incremento de postfix requer que o operando seja um lvalue modificável , o padrão de rascunho na seção 6.5.2.4 incremento e decremento do postfix, parágrafo 1, diz ( ênfase minha ):

O operando do operador de incremento ou decremento de postfix deve ter um tipo de ponteiro ou real qualificado ou não qualificado e deve ser um valor modificável .

podemos ver a partir dos valores, arrays e designadores de funções do setion 6.3.2.1 , o parágrafo 1 diz:

[…] Um lvalue modificável é um lvalue que não tem tipo de array […]

Os endereços de memory de matriz permanecem constantes, portanto, você não pode alterá-la. Isso é o que você está fazendo em uma instrução ++. Então, o compilador lançará um erro.

a não é uma variável do tipo int, é um ponteiro para inteiro, então, para imprimi-lo, é necessário desreferê-lo primeiro

 printf("%d\n", *(a + 2)); 

O nome da matriz é um ponteiro constante e, portanto, sempre apontará para o 0º elemento dessa matriz. Não é uma variável, então nem podemos atribuir outro endereço a ela nem podemos movê-la incrementando ou decrementando. Conseqüentemente

 a = &var; /*Illegal*/ a++; /*Illegal*/ a = a-1; /*Illegal*/