Zagwostka nt. Switcha

0

Cześć wszystkim ;)

Mam taką dziwną zagwostkę, mianowicie w instrukcji sterującej switch, przy etykiecie case może pojawić się tylko i wyłącznie stałe wyrażenie, czyż nie? No to dlaczego to działa:

#include <iostream>
using namespace std;
const int a = 2, b = 3, c = 4;
const int tabliczka[5] = {1, 2, 3, 4, 5};
int main(int argc, char **argv) 
{
    cout << "Hello, world! Today we are going to test switch instruction :)" << endl;
    cout << "Gimme some fish : \t";
    int wartosc = 0;
    
    cin >> wartosc;
    switch(wartosc)
    {
      case a: 
      {
	cout << "To jest wlasnie " << a << endl;
      }
      break;
      case b:
	{
	cout << "To jest wlasnie " << b << endl;
      }
      break;
      case c: 
      {
	cout << "To jest wlasnie " << c << endl;
      }
      break;
      default: 
      {
	cout << "To jest wlasnie " << wartosc << endl;
      }
      break;
    }
    return 0;
}

A to już nie działa:

#include <iostream>
using namespace std;
const int a = 2, b = 3, c = 4;
const int tabliczka[5] = {1, 2, 3, 4, 5};
int main(int argc, char **argv) 
{
    cout << "Hello, world! Today we are going to test switch instruction :)" << endl;
    cout << "Gimme some fish : \t";
    int wartosc = 0;
    
    cin >> wartosc;
    switch(wartosc)
    {
      case tabliczka[1]: 
      {
	cout << "To jest wlasnie " << tabliczka[1] << endl;
      }
      break;
      case tabliczka[2]:
	{
	cout << "To jest wlasnie " << tabliczka[2] << endl;
      }
      break;
      case tabliczka[3]: 
      {
	cout << "To jest wlasnie " << tabliczka[3] << endl;
      }
      break;
      default: 
      {
	cout << "To jest wlasnie " << wartosc << endl;
      }
      break;
    }
    return 0;
}

Czyli, dlaczego niepowiązane w tablice obiekty mogą stać przy etykiecie case, a stałe obiekty powiązane w tablice już nie?

Z góry dzięki za odpowiedź :)

0

Popatrzyłem na to, co zwraca gcc + gdb. I widzę, że const inty zostały zamienione bezpośrednio na ich wartości. To znaczy:

case a: /* ... */
case b: /* ... */

Zostało przez kompilator "zamienione" na:

case 2: /* ... */
case 3: /* ... */

...czyli na wyrażenie stałe (można było się tego spodziewać). Tymczasem odwołanie do tablicy nie można zamienić na wyrażenie stałe, ponieważ pobranie wartości z tablicy jest identyczne z pobraniem wartości z odpowiedniego miejsca w pamięci (czego nie można zrobić w czasie kompilacji, prawda?)

0

Dzięki za odpowiedź :) Teraz już rozumiem :)

Pozdrawiam

0

Ja tylko napisałem, co wypluwa gcc podczas kompilacji przykładowych programów. Dziwnym trafem (?) const int poza tablicą zamienia na ich wartości, a te w tablicy zamienia na odwołania do pamięci.

No to niezły zonk.

Coś takiego:

    const int a[1] = {5};
    const_cast<int*>(a)[0] = 6;
    printf("%d\n", a[0]);

wypluwa 6, ale już:

    const int a = 5;
    *const_cast<int*>(&a) = 6;
    printf("%d\n", a);

wypluwa 5.

Zabawny ten C++ :P

0

W drugim przypadku jak dopiszesz do deklaracji tej stałej volatile to już wypluje 6 :p
Z C++ nie można się nudzić :D Całe życie można się go uczyć a i tak do końca nie poznasz :D

0

Zabawny ten C++
bo const_cast służy do pozbycia się consta w sytuacji, gdy zmienna ma go „niesłusznie” (była castowana lub przekazana jako const), lub gdy funkcja nie przestrzega „const correctness”, np. pobiera wejściowego c-stringa jako char* zamiast const char*.
const_cast nie służy zaś do tego, by „oszukiwać” kompilator i próbować zmieniać wartość stałej. To nie musi działać.

0

Świetnie. W takim razie proszę o listę słusznych i niesłusznych rzeczy :p

Standard C++.

Depending on the type of the object, a write operation through the pointer, lvalue or pointer to data member resulting from a const_cast that casts away a const-qualifier may produce undefined behavior

oraz:

Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const
object during its lifetime (3.8) results in undefined behavior.

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