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
-1wyglą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żą