• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Problem z kompilacja kodu w Visual Studio - E0028 Expression must have a constant value (C++)

Object Storage Arubacloud
0 głosów
1,020 wizyt
pytanie zadane 4 listopada 2020 w C i C++ przez MONKNOW Użytkownik (720 p.)

Witam, probuje dzisiaj "przesiasc sie" z Codeblocks na Visual Studio i chcialem na probe zbudowac program ktory w Codeblocks dzialal bez zarzutu. Niestety w VS dostaje blad, ktorego kompilator Codeblocksa nie wyswietlal, a mianowicie E0028 Expression must have a constant value. To jest moj main, kompilator przyczepil sie do int ile_p = 5.

#include <iostream>
#include <numeric>
#include "FunkcjeApki.h"
using namespace std;

int main()
{
    int ile_p = 5; //wpisz tutaj ilosc obiektow produkt, ktorymi chcesz operowac w programie.
    string wybor; //nawiguje uzytkownika po sklepie
    bool czy_lista = 0; //zmienna sprawdzajaca czy program jest w funkcji wyswietl_nazwy()
    int koszyk[ile_p]; //alokacja pamieci na ID produktow do kupienia
    produkt lista[ile_p]; //alokacja pamieci na obiekty produkt

    // v tu dodawaj kolejne produkty(nazwa, ilosc, cena, ID) v
    lista[0].podaj_dane("Jablko", 20, 2, 9);
    lista[1].podaj_dane("Chleb", 10, 5, 4);
    lista[2].podaj_dane("Marchew", 40, 2, 5);
    lista[3].podaj_dane("Mleko", 10, 3, 6);
    lista[4].podaj_dane("Hot-dog", 50, 3, 8);
    // ^ tu dodawaj kolejne produkty(nazwa, ilosc, cena, ID) ^

    while (1) {
        cout << "Witaj w sklepie, przejdz do listy produktow (L) albo do koszyka (K)" << endl;
        cin >> wybor;
        nawigacja(ile_p, lista, koszyk, wybor, czy_lista);
    }

    return 0;
}

 

1 odpowiedź

0 głosów
odpowiedź 4 listopada 2020 przez Whiskey_Taster Pasjonat (15,610 p.)
wybrane 5 listopada 2020 przez MONKNOW
 
Najlepsza

Nie, kompilator przyczepił się do Twojej tablicy
 

int koszyk[ile_p]

Alokacja pamięci na tablicę jest w momencie wejścia do funkcji main (o ile się nie mylę). Za to zmienna ile_p nie ma przydzielonej wartości przez Ciebie w momencie wejścia do funkcji, a ma losową wartość, jakiegoś śmiecia. Stąd nie wiadomo, co tam jest i kompilator najwidoczniej się buntuje. Code Blocks za to jest słabszy, więc dopuszcza taką możliwość. Jak chcesz tak zrobić, to zalecam alokację dynamiczną. 

 

EDIT: Możesz jeszcze zrobić tak 
 

#include <iostream>
#include <numeric>
#include "FunkcjeApki.h"
using namespace std;
const int ile_p = 5; //wpisz tutaj ilosc obiektow produkt, ktorymi chcesz operowac w programie.
 
int main()
{
    
    string wybor; //nawiguje uzytkownika po sklepie
    bool czy_lista = 0; //zmienna sprawdzajaca czy program jest w funkcji wyswietl_nazwy()
    int koszyk[ile_p]; //alokacja pamieci na ID produktow do kupienia
    produkt lista[ile_p]; //alokacja pamieci na obiekty produkt
 
    // v tu dodawaj kolejne produkty(nazwa, ilosc, cena, ID) v
    lista[0].podaj_dane("Jablko", 20, 2, 9);
    lista[1].podaj_dane("Chleb", 10, 5, 4);
    lista[2].podaj_dane("Marchew", 40, 2, 5);
    lista[3].podaj_dane("Mleko", 10, 3, 6);
    lista[4].podaj_dane("Hot-dog", 50, 3, 8);
    // ^ tu dodawaj kolejne produkty(nazwa, ilosc, cena, ID) ^
 
    while (1) {
        cout << "Witaj w sklepie, przejdz do listy produktow (L) albo do koszyka (K)" << endl;
        cin >> wybor;
        nawigacja(ile_p, lista, koszyk, wybor, czy_lista);
    }
 
    return 0;
}

Jaka różnica? Ano taka, że zmienna statyczna jest inicjalizowana przed wejściem do funkcji main() i ma ona w zasięgu funkcję main(). Stąd jest dostępna "od ręki" i wszystko gra. Kwestia tego, jak chcesz to zrobić należy do Ciebie. 

1
komentarz 4 listopada 2020 przez draghan VIP (106,230 p.)

Alokacja pamięci na tablicę jest w momencie wejścia do funkcji main (o ile się nie mylę). Za to zmienna ile_p nie ma przydzielonej wartości przez Ciebie w momencie wejścia do funkcji, a ma losową wartość, jakiegoś śmiecia. Stąd nie wiadomo, co tam jest i kompilator najwidoczniej się buntuje.

Mamy tutaj do czynienia z innym problemem. Alokacja jest dokonywana w kolejności definicji, możesz to sprawdzić i zmierzyć samodzielnie obiektami z własnym konstruktorem.

W standardzie C++ nieprawidłowym jest tworzenie tablic statycznych o niestałym rozmiarze - innymi słowy wielkość tablicy statycznej musi być znana na etapie kompilacji.

To, co podajemy w nawiasach kwadratowych musi spełniać następujący warunek:

an integral constant expression (until C++14)a converted constant expression of type std::size_t (since C++14), which evaluates to a value greater than zero

[źródło]

Nielegalne jest zatem utworzenie tablicy w taki sposób:

int tab_size = 5;
int tab[tab_size];

Poprawnie należy to zrobić tak:

const int tab_size = 5;
int tab[tab_size];

Code Blocks za to jest słabszy, więc dopuszcza taką możliwość. Jak chcesz tak zrobić, to zalecam alokację dynamiczną. 

Code::Blocks na Windows jest zbundlowany z MinGW, które zawiera port GCC. Kompilator g++ z kolei, który jest składnikiem GCC, posiada rozszerzenie, które pozwala na taką konstrukcję. Nazywa się to VLA (Variable-length Array) i w g++ wzięło się z tego, że jest to legalne w standardzie C99. Developerzy g++ widocznie uznali że programiści C++ nie mogą być "gorsi" od programistów C i pozwolą na takie wygibasy. ;)

komentarz 4 listopada 2020 przez Whiskey_Taster Pasjonat (15,610 p.)
Fajnie, dobrze wiedzieć :)
Jeszcze zapytam z ciekawości: dlaczego było to dozwolone? Jakby nie patrzeć nie wiadomo, co tam siedzi w momencie przydzielania pamięci na zmienną, więc jaki to miało wówczas sens?
2
komentarz 4 listopada 2020 przez draghan VIP (106,230 p.)

Jakby nie patrzeć nie wiadomo, co tam siedzi w momencie przydzielania pamięci na zmienną

To nie do końca prawda. Tak jak napisałem wcześniej, to nie jest tak że zmienne lokalne przyjmują swoje wartości w losowej kolejności. Jak zdefiniujesz najpierw zmienną x o wartości 200, to możesz użyć jej wartości przy definicji kolejnej zmiennej:

int x = 200;
int y = x + 200; // y = 400, x is already properly constructed at this point

 

Patrząc na poniższy kod, człowiek widzi jaki rozmiar powinna mieć tablica:

int tab_size = 5;
int tab[tab_size];

Kompilator również nie ma z tym problemu. VLA w C mogą być alokowane zarówno na stosie (automatic storage duration), jak i na stercie (dynamic storage duration). W C++ ograniczeniem są same reguły standardu (i nie jest to koniecznie coś złego). Zwykła tablica musi być alokowana na stosie, a to wymusza żeby rozmiar był znany podczas kompilacji i niezmienny, a zmienna która nie posiada modyfikatora const (lub constexpr) tego nie gwarantuje.

komentarz 5 listopada 2020 przez Whiskey_Taster Pasjonat (15,610 p.)
W zupełności już rozumiem. Dziękuję :)
komentarz 5 listopada 2020 przez MONKNOW Użytkownik (720 p.)
Ja rowniez pieknie dziekuje :)

Podobne pytania

0 głosów
1 odpowiedź 1,859 wizyt
pytanie zadane 14 sierpnia 2019 w C i C++ przez Mavimix Dyskutant (8,390 p.)
0 głosów
1 odpowiedź 370 wizyt
0 głosów
1 odpowiedź 1,542 wizyt

92,570 zapytań

141,422 odpowiedzi

319,643 komentarzy

61,958 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...