Program działa a nie powinien

0

Jakiś czas temu, jak jeszcze nie znałem tablic dynamicznych napisałem taki oto program (do rozwiązywania układu równań):

#include <iostream>
#include <conio.h>
#include <cstdlib>
#include <ctime>

using namespace std;

main ()
{
	srand( time( NULL ) );
	int n, kolejna=0, kolejna2=0, numer_niewiadomej=1;
	float mnoznik, zmienna;

	cout<<"Wczytaj liczbe rownan, bedaca jednoczesnie liczba niewiadomych :  ";
	cin>>n;
	cout<<endl;
	
	float tab [n*(n+1)];
	cout<<endl<<sizeof(tab);
	 
	for(int i=0; i<=n*(n+1)-1; i++)
	{
		tab[i]=(rand()%200)+(-100);
		if ((i+1)%(n+1)==0)
		cout<<"\t="<<tab[i]<<endl;
		else
		{
		cout<<"\t";
		if (tab[i]>0)
		cout<<"+"<< tab[i]<<"*x"<<(i%(n+1))+1;
		else
		cout<<tab[i]<<"*x"<<(i%(n+1))+1;
		}		
	}
	
	for(int j=0; j<n; j++)
	{
		if (tab[j*(n+2)]!=1)
		{
			zmienna=tab[j*(n+2)];
			for(int y=0; y<=n; y++)
			{
				tab[kolejna]=tab[kolejna]/zmienna;
				kolejna++;
			}
		}
		int skok=j;
		kolejna2=0;
		while (kolejna2<=n*(n+1)-1)
		{			
			mnoznik=tab[skok];
			for(int z2=j*n+j; z2<=(j+1)*n+j; z2++)
			{
				if (kolejna2!=z2)
				{
					tab[kolejna2]=tab[kolejna2]-mnoznik*tab[z2];
					kolejna2++;
				}
				else kolejna2++;
			}
			skok=skok+n+1;	
		}
	}
		
	cout<<endl<<endl<< "Obliczenia wykonano metoda eliminacji Gaussa.\nPrzeksztalcona macierz ma postac:"<<endl<<endl;
	for(int i2=0; i2<n*(n+1); i2++)
	{
		if ((i2+1)%(n+1)==0)
		cout<<"\t"<<tab[i2]<<endl;
		else
		cout<<"\t"<<tab[i2];
	}	
	cout<<endl<<endl<<"WYNIKI:"<<endl;
	for(int i3=0; i3<n; i3++)
	cout<<"x"<<i3+1<<"= "<<tab[(i3+1)*n+i3]<<endl;
		
	getch ();
	return 0;
}

Zadeklarowałem tablicę statyczną tab[]. Dziś już wiem, że aby taką tablicę zadeklarować, jej wielkość musi być znana w chwili kompilacji. Więc prawidłowo powinienem zrobić tak:

const int n=5;
float tab [n*(n+1)];

lub po prostu

float tab [5];

lub zadeklarować tablicę dynamiczną:

 float *tab=new float [n*(n+1)];

Ja natomiast zadeklarowałem zmienną int n i w trakcie działania programu inicjalizuję ją wartością podaną z klawiatury i dopiero w kolejnym kroku tworzę tablicę o określonej już wielkości. Coś takiego nie powinno działać, a jednak działa. Program się wykonuje prawidłowo. Dlaczego?

1

dawniej nie wolno było tego robić obecnie wolno i to tyle.
pewnie C89 by się obraziło. C11 już nie,

4

W C++ to było od dawna dostępne rozszerzenie kompilatora, niby niezgodne ze standardem ale mimo to dostępne.

3

https://en.wikipedia.org/wiki/Variable-length_array
tldr: jest to niezgodne ze standardem, mimo to sporo kompilatorow implementuje to jako rozszerzenie. Sprawa jest dość skomplikowana, głównie chodzi tutaj o bezpieczeństwo aplikacji. Używanie VLA to prawie zawsze bardzo zła praktyka - mamy std::vector i korzystajmy z niego.

1 użytkowników online, w tym zalogowanych: 0, gości: 1