Acessar matriz além do limite em C e C ++

int data[8]; data[9] = 1; 

O que o padrão c ++ diz sobre isso? Esse comportamento é indefinido?

Pelo menos o compilador C (gcc-std = c99 -pedantic -W-Wall) não diz nada sobre isso.

Obrigado.

Acessar fora dos limites da matriz é o comportamento indefinido, da seção padrão do rascunho do c99 Annex J.2 J.2 O comportamento indefinido inclui o seguinte ponto:

Um subscrito de array está fora de alcance, mesmo que um object seja aparentemente acessível com o subscrito dado (como na expressão de lvalue a [1] [7] dada a declaração int a [4] [5]) (6.5.6).

e o rascunho da norma C ++ na seção 5.7 Aditivos no parágrafo 5 diz:

Quando uma expressão que possui um tipo integral é adicionada ou subtraída de um ponteiro, o resultado tem o tipo do operando do ponteiro. Se o operando ponteiro apontar para um elemento de um object de matriz e o array for grande o suficiente , o resultado apontará para um deslocamento de elemento do elemento original, de modo que a diferença dos índices dos elementos de matriz original e resultante seja igual à expressão integral. […] Se tanto o operando do ponteiro e o resultado apontarem para elementos do mesmo object de matriz, ou um após o último elemento do object de matriz, a avaliação não produzirá um estouro; caso contrário, o comportamento é indefinido.

Para fins de integralidade, a seção 5.2.1 Subscrito no parágrafo 1 diz:

[…] A expressão E1 [E2] é idêntica (por definição) a * ((E1) + (E2)) [Nota: veja 5.3 e 5.7 para detalhes de * e + e 8.3.4 para detalhes de matrizes. – end note]

É importante observar que o compilador não é obrigado a produzir um aviso ( diagnóstico ) para comportamento indefinido, o padrão de rascunho C ++ na seção 1.4 parágrafo 1 de conformidade de implementação diz:

O conjunto de regras diagnosticáveis ​​consiste em todas as regras sintáticas e semânticas nesta Norma Internacional, exceto aquelas regras que contêm uma notação explícita de que “nenhum diagnóstico é necessário” ou que são descritas como resultando em “comportamento indefinido”.

Sim, é um comportamento indefinido.

Um compilador pode ou não avisar você sobre comportamento indefinido, mesmo que seja capaz de detectá-lo.

Isso é considerado comportamento indefinido. Os compiladores não são obrigados a emitir avisos se você tentar compilar um código que resultará em um comportamento indefinido, embora seja bom fazê-lo.

Espero que isto ajude!

Indefinido. Pode ou não ser memory inválida, o que a torna perigosa. Você pode usar ferramentas como o valgrind para detectar accesss ruins como este.

Sim, é um comportamento indefinido. Tudo pode acontecer, pode funcionar ou não, pode funcionar 2 anos e depois parar para o trabalho. Isso é o mais perigoso de três:

  • comportamento indefinido
  • comportamento não especificado
  • comportamento definido pela implementação

Você pode verificar isso para conhecer outros parentes: Quais são todos os comportamentos indefinidos que um programador C ++ deve conhecer?

Comportamento indefinido, não especificado e definido pela implementação

C e C ++ não verificam limites. Os valores que você está tentando alcançar podem ser praticamente qualquer coisa. Pode parecer funcionar em seu compilador, mas não é legal C ou C ++, e não há garantia de que ele ainda funcionará na próxima vez que você executar o programa.

De acordo com o padrão ISO C, acessar uma matriz fora dos limites causa

comportamento indefinido: comportamento, mediante o uso de uma construção de programa não portável ou errônea ou de dados errados, para os quais esta Norma não impõe requisitos

Falhas de segmentação ocorrem quando você está tentando excluir um ponteiro para a memory que seu programa não tem permissão para acessar, e apenas passando o final de sua matriz provavelmente não causará isso. Mas provavelmente lhe dará alguns valores ruins.

Sim, é um comportamento indefinido, alguns compiladores dão avisos sobre isso, outros não, mas deixa olhar, o seu código faz.

Veja a implementação inline dos opor- tadores [] . a[b] é na verdade *(a + b) . Então volte para o seu código.

 int data[8]; data[9] = 1; 

Primeiro você aloca uma parte da pilha e cria um ponteiro para o primeiro elemento. Então você reescreve alguns dados, que são logo após o array, então você corrompe alguns dados.

Vamos pegar outro exemplo:

 int data[8]; int data2[8] = {}; data[9] = 1; 

É muito provável que o compilador gere código que aloca uma vez e crie dois pointers como matrizes. Então, data[9] = 1; pode definir o segundo valor de data2 para um, no entanto, não há garantias sobre isso.