Dyskusja:C/Przenośność programów

Najnowszy komentarz napisał(a) 17 lat temu Mina86 w wątku Rozmiar zmiennych

Kolejność pobierania argumentów edytuj

Bardzo ciekawe zagadnienie i duża pułapka! Przetestujcie poniższy program:

void TEST( int a1, int a2, int a3, int a4 ){
   printf( "%d %d %d %d \n", a1, a2, a3, a4 );
}

void main(){
  int i = 0;
  TEST( i++, i++, i++, i++ );
}

Wynik na x86 (GNU/Linux):

3 2 1 0

Wynik na PPC (Mac OS X):

0 1 2 3 
Ja wiem czy ciekawe? Zwykła konsekwencja tego, że pomiędzy dwoma sequence pointami próbujesz modyfikować tą samą zmienną wiele razy. Jest to opisane w rozdziale Operatory przy okazji opisywania operatorów ink- i dekrementacji. Takie coś jest naruszeniem standardu i wywołuje undefined behaviour, czyli podany przez Ciebie program może równie dobrze wypisać ala ma kota jak i przyzwać szatana, który opęta osobę siedzącą najbliżej komputera. Innymi słowy nie jest to kwestia przenośności programu, ale błędu w programie.
Pojawia się jeszcze kwestia tego, że kolejność w jakiej argumenty wywołania funkcji są obliczane jest nieokreślona. Jest to wspomniane w pierwszej sekcji zaraz po wstępie komentowanego rozdziału (ostatni akapit). -- mina86 (talk) 09:58, 5 lut 2007 (CET)Odpowiedz
Lepszym przykładem na nieokreśloną kolejność obliczania argumentów funkcji byłoby:
#include <stdio.h>
int foo(int a) { printf("%d\n", a); return 0; }
int bar(int a, int b, int c, int d) { return a + b + c + d; }
int main(void) { return bar(foo(1), foo(2), foo(3), foo(4)); }

Porządek bitów edytuj

I jakie to ma znaczenie dla programu napisanego w C? I tak nie można w nim dobrać się do pojedynczego bitu tylko operuje się bezpośrednio na bajtach więc efektu tego nie da się zaobserwować. Co więcej wcale nie musi być tak jak jest to opisane. Kwestia porządkowania bitów jest niezależna od porządkowania bajtów. -- mina86 (talk) 14:40, 26 sty 2007 (CET)Odpowiedz

Konwersja z jednego porządku do innego edytuj

Ktoś tutaj chyba się zagalopował. Little endian i big endian to nie jedyne sposoby w jakie mogą być ustawione bajty zatem nie można zakładać, że jeżeli porządek nie jest big endian to jest little endian. -- mina86 (talk) 14:43, 26 sty 2007 (CET)Odpowiedz

Owszem, zgadza (np. bodajże komputery PDP miały "swój" porządek). Jednak chodziło tutaj o pokazanie współczesnych architektur, z którymi przeciętny czytelnik może się spotkać. --Kj 17:47, 26 sty 2007 (CET)Odpowiedz
Ej no sorry... Albo coś robimy porządnie albo tego nie robimy w ogóle, toteż albo piszemy całą prawdę albo nie piszemy nic w ogóle. Na tej zasadzie mogę powiedzieć, że przeciętny czytelnik będzie korzystał z GCC na Linuksie i zamiast się bawić w czytanie i interpretowanie standardu mogę wkleić strony manuala. Chyba nie o to chodzi, żeby stworzyć jakieć "coś" pełne niedomówień i nieścisłości. -- mina86 (talk) 19:22, 26 sty 2007 (CET)Odpowiedz

Rozmiar zmiennych edytuj

Wybaczcie szczerość, ale czy osoba pisząca tę sekcję miała zielone pojęcie o czym pisze? Jednak na platformach 64-bitowych przyjęło się, że typ long ma rozmiar 64 bitów. -- to bardzo ciekawe, bo na moim uczelnianym serwerze, ktory jest 64 bitowy, poniższy kod:

#include <stdio.h>
#include <limits.h>
int main(void) {
  printf("%d\n", (int)(CHAR_BIT * sizeof(long)));
  return 0;
}

wypisuje 32. -- mina86 (talk) 14:59, 26 sty 2007 (CET)Odpowiedz

Może fragment pliku /usr/include/bits/types.h:
64              -- "natural" 64-bit type (long or long long)

--Kj 17:35, 26 sty 2007 (CET)Odpowiedz

Ale co to ma do czegokolwiek? W tekście jak byk stoi, że na platformach 64-bitowych przyjęło się, że typ long ma rozmiar 64 bitów, gdy tymczasem na 64 bitowym SPARC-u long ma 32 bity. Może mi powiesz, że SPARC to nie jest współczesna archtiektura? A możę, że przeciętny czytelnik nie będzie pisał na SPARC-ach? -- mina86 (talk) 19:22, 26 sty 2007 (CET)Odpowiedz
Jedna prośba: mógłbyś sprawdzić na tym komputerze wynik działania programu:
#include <stdio.h>
#include <limits.h>
int main(void) {
  printf("%d\n", (int)(CHAR_BIT * sizeof(void*)));
  return 0;
}
--Kj 16:23, 14 lut 2007 (CET)Odpowiedz
32, co nie zmienia faktu, że komputerek jest 64 bitowy. A widziałeś np. opcję -mlong64 i -mlong32 dostępne w GCC na MIPS-ach? Może i faktycznie przesadziłem trochę sugerując, że osoba pisząca tę sekcję [nie] miała zielone pojęcie o czym pisze, ale nadal obstaje przy tym, że wiązanie wielkości typu long z liczbą bitów architektury jest conajmniej nieprawidłowe. -- mina86 (talk) 17:38, 14 lut 2007 (CET)Odpowiedz
Nie, nie o to chodzi ;-). Po prostu Sparc był początkowo 32-bitowy, a GCC ma to do siebie, że jeśli jakaś architektura była początkowo 32-bitowa a potem stworzono jej 64-bitową wersję, to tworzy kod kompatybilny wstecz. A do zmuszenia go do wytwarzania kodu w trybie 64-bitowym służy opcja -m64 (niedostępna np. dla komputerów opartych na procesorach Alpha - "domyślnie" 64-bitowych). Aha - zdaje mi się, że gdzieś kiedyś spotkałem się z informacją, że w języku C typ long odpowiadał słowu maszynowemu, dlatego też w taki sposób pisałem ten rozdział. --Kj 21:09, 14 lut 2007 (CET)Odpowiedz
Owszem, przy kompilowaniu z -m64 oba programy dają w wyniku 64.-- mina86 (talk) 22:23, 14 lut 2007 (CET)Odpowiedz

Kolejna bzdura: Osiem kolejnych bitów stanowi bajt. i od -128 do 127 (jeśli używamy także ujemnych liczb całkowitych). Generalnie, wg mnie cały ten rozdział nadaje się tylko i wyłącznie do gruntownego napisania od nowa. -- mina86 (talk) 19:22, 26 sty 2007 (CET)Odpowiedz

Jeśli tak uważasz i masz czas wprowadzić poprawki - proszę bardzo. --Kj 19:52, 26 sty 2007 (CET)Odpowiedz
Problem w tym, że czasu nie mam. -- mina86 (talk) 20:11, 26 sty 2007 (CET)Odpowiedz

Niejasny fragment ("Otóż nic nie stoi na przeszkodzie...") edytuj

Fragment rozpoczynający się od "Otóż nic nie stoi na przeszkodzie, aby konkretny kompilator opisał działanie jakiegoś wyrażenia..." jest niejasny i wymaga poprawy. -- T ziel, 19:25, 5 lut 2007

Zmieniłem opis, mam nadzieje, że teraz już wszystko jest jasne. -- mina86 (talk) 22:32, 5 lut 2007 (CET)Odpowiedz

Rozumiem, że w tym fragmencie chodzi o to, że niektóre kompilatory "definiują po swojemu" pewne nieokreślone przez standard języka sytuacje i programista po zapoznaniu się z tymi nietypowymi rozwiązaniami kompilatora, może je stosować kosztem przywiązania do konkretnego kompilatora (a czasem nawet do konkretnej wersji kompilatora; jest to widoczne zwłaszcza w starym MS Visual Studio C++).

Dobrze, że poprawiłeś ten fragment (i to jak szybko), ale nadal wydaje mi się on zawiły postaram się napisać to prościej oraz bardziej przejrzyście i zamieszczę propozycję w dyskusji. -- T ziel, 00:17, 6 lut 2007

Powrót do strony „C/Przenośność programów”.