C პროგრამირების ენის სამყაროში არსებობს ერთი მწარე რეალობა: ISO C სტანდარტების სრულყოფილად დაცვა თითქმის არარეალურია. პრაქტიკაში, უმეტესობა კოდისა იყენებს არა-სტანდარტულ ქცევებსა და კომპილატორის სპეციფიკურ გაფართოებებს. ეს ხშირად არა დამატებითი ფუნქციების, არამედ არსებული შეცდომების გვერდის ავლის მიზნით ხდება.

სისტემური ბიბლიოთეკების გამოწვევა

ნებისმიერი ახალი C კომპილატორისთვის პირველი დიდი დაბრკოლება სისტემური ბიბლიოთეკების სათაურებია. მაგალითად, Linux-ზე glibc-ის გარეშე შეუძლებელია თუნდაც მარტივი პროგრამის შედგენა. თუმცა, sys/cdefs.h-ის მსგავსი ფაილები სავსეა კომპილატორის სპეციფიკური შემოწმებებით.

პრობლემა მაშინ იჩენს თავს, როდესაც კომპილატორი არ არის GCC, Clang ან TCC. სისტემური სტრუქტურები, როგორიცაა epoll_event, იყენებენ GNU-ს სპეციფიკურ ატრიბუტებს. თუ კომპილატორი არ ცნობს ამ ატრიბუტებს, შედეგად ვიღებთ ABI-ს დარღვევას და კოდის გაუმართაობას.

პორტაბელურობის ფასი

POSIX სტანდარტი მოითხოვს გარკვეულ მუდმივებს limits.h-ში, რომლებიც პლატფორმის სპეციფიკურია. ეს ქმნის დამოკიდებულებას კომპილატორის შიდა, ჩაშენებულ სათაურებზე. შედეგად, დეველოპერები იძულებულნი არიან გამოიყენონ #include_next-ის მსგავსი ტექნიკები, რაც პროცესს ზედმეტად ართულებს.

ასევე საინტერესოა SDL_endian.h-ის მაგალითი, რომელიც ცდილობს გამოიყენოს კომპილატორის ჩაშენებული ფუნქციები. სამწუხაროდ, ლოგიკა ხშირად ეყრდნობა მხოლოდ GCC-სა და Clang-ის მხარდაჭერას, რაც სხვა კომპილატორებს ავტომატურად გამორიცხავს.

ინლაინ ფუნქციების პრობლემა

OpenBSD-ის მიერ გამოყენებული __only_inline მაკროები კიდევ ერთი მაგალითია იმისა, თუ როგორ შეიძლება დაზიანდეს კოდი კომპილატორის სპეციფიკური სემანტიკის გამო. განსხვავება C-სა და C++-ის inline ფუნქციებს შორის ქმნის მუდმივ კონფლიქტს, რომლის მოგვარებაც ხშირად `_ANSI_LIBRARY` მაკროს გამოყენებით ხდება.

Android-ის libc, იგივე bionic, კიდევ უფრო შორს მიდის და ეყრდნობა Clang-ის სპეციფიკურ გაფართოებებს, როგორიცაა nullability შემოწმებები. ეს კიდევ უფრო ამცირებს კოდის პორტაბელურობას სხვადასხვა გარემოში.

როგორ უნდა მოიქცნენ კომპილატორების ავტორები?

არსებობს რამდენიმე გზა ამ დილემის გადასაჭრელად:

  • შეცდომების გასწორება პირველწყაროებში (Upstream).
  • საკმარისი პოპულარობის მოპოვება, რათა დეველოპერებმა დაამატონ თქვენი კომპილატორის მხარდაჭერა.
  • კომპილატორის ისე მორგება, რომ მან თავი მოაჩვენოს GCC-დ, რაც უკვე აპრობირებული მეთოდია Clang-ის შემთხვევაში.

მიუხედავად იმისა, რომ GCC/Clang დუოპოლია დღევანდელი რეალობაა, დამოუკიდებელი კომპილატორების ავტორები, როგორებიც არიან tcc, kefir და სხვები, აგრძელებენ სისტემის განვითარებას. იდეალურ შემთხვევაში, მომავალში კომპილატორის სპეციფიკური შემოწმებების ნაცვლად, უფრო მეტი აქცენტი გაკეთდება ფუნქციების ტესტირების სტანდარტულ მაკროებზე.