Witam!
Patrzcie jakiego buga znalazłem dzisiaj w C, powinienem za to dostać z milion dolarów.
#include <stdio.h>
int main()
{
int i = -1;
int o[1000];
o[i] = 100;
printf("%d\n", o[-1]);
return 0;
}
Witam!
Patrzcie jakiego buga znalazłem dzisiaj w C, powinienem za to dostać z milion dolarów.
#include <stdio.h>
int main()
{
int i = -1;
int o[1000];
o[i] = 100;
printf("%d\n", o[-1]);
return 0;
}
To nie jest bug.
To jest zdefiniowane w specyfikacji C, jako undefined behaviour.
ProgrammingKing napisał(a):
Witam!
Patrzcie jakiego buga znalazłem dzisiaj w C, powinienem za to dostać z milion dolarów.
No biznes w tym jest. Wiele milionów(miliardów?) dolarów już poszło na inwestowanie w języki memory safe (od kilku lat hype'owany jest Rust), które chronią m.in. przed takimi właśnie dziwnymi rzeczami.
Ale że tak po omacku programujesz nie rozumiejąc co piszesz?
Może liczba -1
wygląda dziwnie, ale to jest równoważne 0 - 1
, i teraz jak sobie w tabelce jak w podstawówce policzysz, to wyjdzie, że będziesz musiał pożyczać w nieskończoność bo masz.
(32bity) 00000000000 - 1
, to pożyczasz pożyczasz pożyczasz, czyli masz jedną magiczną jedynkę z przodu 10000000 - 1
, czyli coś podobnego do 1000 - 1 w dziesiętnym to będzie 999, a w bitowym same 1111111111
Czyli twoje i
wynosi: printf("%u\n", i);
potraktowane jako unsigned.
A w bitach w C++ to byś odczytał tak.
int i = -1;
#include <bitset>
std::bitset<32> j(i);
std::cout << j << std::endl;
tumor napisał(a):
Ale że tak po omacku programujesz nie rozumiejąc co piszesz?
Może liczba
-1
wygląda dziwnie, ale to jest równoważne0 - 1
, i teraz jak sobie w tabelce jak w podstawówce policzysz, to wyjdzie, że będziesz musiał pożyczać w nieskończoność bo masz.
(32bity)00000000000 - 1
, to pożyczasz pożyczasz pożyczasz, czyli masz jedną magiczną jedynkę z przodu10000000 - 1
, czyli coś podobnego do 1000 - 1 w dziesiętnym to będzie 999, a w bitowym same1111111111
No nie bardzo o to chodzi, po prostu arytmetyka wskaźników jest odwracalna o[1]
czy o[0 + 1]
to to samo co 0[o + 1]
czyli po prostu wartość z pamięci o adresie o przesuniętym o 1, tak samo można wziąć po prostu adres o 1 mniejszy. Tu na przykład możesz zrobić tablicę b
, potem wskaźnik c
wskazujący na środek tej tablicy, a potem odwołać się do c[-1]
lub 0[c - 1]
i w ten sposób weźmiesz element z lewej strony od środka tablicy
#include <stdio.h>
int main()
{
int b[10];
b[4] = 69;
b[3] = 42;
int* c = &b[5];
printf("%d\n", c[-1]); // 69
printf("%d\n", 0[c - 1]); // 69
printf("%d\n", c[-2]); // 42
printf("%d\n", 0[c - 2]); // 42
return 0;
}
o[-1]
po prostu modyfikuje losową wartość w pamięci zależy od kompilatora i jak się zmienne ułożą
Dzięki, dzwoniłem juz do komisji standaryzacyjnej z tym problemem, teraz tylko formalności i w następnym tygodniu wypłacają mi nagrodę