Najlepsza odpowiedź
Przenośny plik wykonywalny
Portable Executable format to format plików wykonywalnych, kodu obiektowego, bibliotek DLL, plików czcionek FON i innych używanych w 32-bitowych i 64-bitowych wersjach systemów operacyjnych Windows. Format PE to struktura danych, która zawiera informacje potrzebne programowi ładującemu systemu Windows do zarządzania opakowanym kodem wykonywalnym.
Obejmuje to odniesienia do bibliotek dynamicznych do łączenia, tabele eksportu i importu API, dane zarządzania zasobami i wątki dane z pamięci lokalnej (TLS). W systemach operacyjnych NT format PE jest używany dla plików EXE, DLL, SYS (sterownik urządzenia) i innych typów plików. Specyfikacja Extensible Firmware Interface (EFI) stwierdza, że PE jest standardowym formatem wykonywalnym w środowiskach EFI.
Odpowiedź
Przenośność kodu źródłowego w C oznacza, że tak długo, jak pożądana platforma docelowa ma działający kompilator C, możesz przenieść kod źródłowy C na platformę docelową, rekompilując go, bez konieczności modyfikowania. Ponieważ prawie każda platforma docelowa ma dostępny kompilator C, C jest uważany za bardzo przenośny język programowania.
To powiedziawszy, zwykłe pisanie kodu w C powoduje nie gwarantuje przenośności. Musisz zachować dyscyplinę, aby uniknąć pisania kodu, który nie jest przenośny. Na przykład napisanie kodu, który wykona jedną z poniższych czynności, spowoduje powstanie kodu nieprzenośnego:
- Przyjmuje założenia dotyczące rozmiarów dowolnych typów danych innych niż znaki.
- Sprawia, że założenia dotyczące sposobu wyrównywania danych w pamięci i wewnątrz struktur.
- Przyjmuje założenia dotyczące sposobu pakowania / wypełniania danych w strukturach.
- Przyjmuje założenia dotyczące kolejności bajtów (big endian vs little endian) .
- Używa niestandardowego rozszerzenia kompilatora, które może nie być dostępne we wszystkich implementacjach kompilatora.
- Używa niestandardowego rozszerzenia biblioteki, które może nie być dostępne na wszystkich platformach.
- Opiera się na każdym zachowaniu zdefiniowanym w implementacji, które może działać inaczej w innej implementacji kompilatora.
- Zawiera dowolne niezdefiniowane zachowanie, które może pojawiają się , aby działać w jednym środowisku, ale mogą zachowywać się nieprzewidywalnie w innym.
- Wykonuje wywołania interfejsu API (interfejsu programowania aplikacji) do system, który może nie być dostępny we wszystkich środowiskach.
- Przyjmuje założenia dotyczące określonych adresów pamięci (np., że określony adres pamięci jest mapowany do rejestru urządzenia sprzętowego itp.).
- Przyjmuje założenia dotyczące rozmiaru wskaźnika lub że wskaźnik ma taki sam rozmiar jak int.
- Przyjmuje założenia dotyczące sposobu przekazywania argumentów (na stosie lub w określonych rejestrach).
- Zawiera dowolny wbudowany kod źródłowy języka asemblera.
- Wykorzystuje najnowszą i najlepszą cechę języka C, która może nie być jeszcze obsługiwana przez niektóre implementacje kompilatorów (aw niektórych przypadkach może nigdy nie być obsługiwane).
- Polega na bibliotece, która wykonuje którekolwiek z powyższych.
To nie jest pełna lista.
Jeśli możesz Unikaj używania nieprzenośnego kodu, najlepszym rozwiązaniem jest odizolowanie tego nieprzenośnego kodu do oddzielnego pliku źródłowego. Następnie, gdy trzeba przenieść kod na nową platformę docelową, jest bardzo jasne, jaki podzbiór kodu źródłowego należy zmodyfikować.