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

Z Wikibooks, biblioteki wolnych podręczników.
Przejdź do nawigacji Przejdź do wyszukiwania

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)); }
-- mina86 (talk) 10:20, 5 lut 2007 (CET)[odpowiedz]

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