Frage zu FEATURE TEST MACROS
-
Hallo NG,
in der Manpage der math.h Funktion round() steht unter anderem:
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
round(), roundf(), roundl():
_XOPEN_SOURCE >= 600 || _ISOC99_SOURCE || _POSIX_C_SOURCE >= 200112L;
or cc -std=c99Und beim nachlesen in der FEATURE TEST MACROS Manpage und anderen Quellen im Netz hab ich zu meinem großen erstaunen feststellen müssen, dass ich die Macros selber definieren soll.
Das wundert mich jetzt, weil wenn ich portablen oder rückwärtskompatiblen Code schreibe, mir auf älteren Plattformen keine Funktion herbeiwünschen kann wenn ich die Macros auf den Wert setzte, die ich gerne hätte. Viemehr würde ich erwarten, dass diese Macros ab einer bestimmten glibc Version existieren und dann auch mit fortschreitender Version auch einen bestimmten Wert vorgeben. Demnach sollte ich doch prüfen ob das Macro definiert ist und wenn ja, prüfen ob es mindestens den von mir gewünschten Wert enthält.Wieso also soll ich das Macro definieren. Was verstehe ich da nicht?
Gruß,
BlackPepper
-
round/roundf/roundl sind erst ab C99 im Standard gefordert, d.h. für maximal portablen Code kannst du von der Existenz dieser Bibliotheksfunktionen nicht ausgehen, nichts anderes sagt die Beschreibung.
Es kann sein, dass ein älterer gcc im C89-Modus diese Funktion(en) anbietet, es muss aber nicht sein.
Willst du maximal portabel sein, musst du dir diese Funktionen selbst schreiben (mit C89-Funktionen; sollte aber hierbei nicht so schwer sein).
-
Hallo Wutz,
das was Du schreibst weiß ich. Und ich habe auch eine eigene Funktion round(). Da sich aber in diversen Funktionen diese Macros finden, z.B. fchmof()
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
fchmod():
_BSD_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED
|| /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200809Lwürde ich gerne wissen ob es denn wirklich simmt, dass ich die Macros selber definieren soll wie ich sie gerne hätte (macht für mich keinen Sinn)? Weil dadurch dass ich
#define _POSIX_C_SOURCE 200809L
schreibe, taucht auf einem alten System fchmod nicht auf.
Gruß,
BlackPepper
-
Ist doch ziemlich klar erklärt auf der Manpage, wozu das da ist:
This system exists to allow the library to conform to multiple standards. Although the different standards are often described as supersets of each other, they are usually incompatible because larger standards require functions with names that smaller ones reserve to the user program. This is not mere pedantry — it has been a problem in practice. For instance, some non-GNU programs define functions named getline that have nothing to do with this library's getline. They would not be compilable if all features were enabled indiscriminately.
This should not be used to verify that a program conforms to a limited standard. It is insufficient for this purpose, as it will not protect you from including header files outside the standard, or relying on semantics undefined within the standard.
Du schreibst dein Programm konform zu einem bestimmten Standard* und setzt die Makros diesem Standard entsprechend, damit die richtigen Funktionsdeklarationen eingebunden werden.
*: Wenn keine Not am Mann ist, dann sollte dieser Standard ANSI-C oder wenigstens GNU-C sein. Das heißt, du solltest diese Makros gar nicht brauchen.
-
Hallo Sepp3,
Du schreibst genau das, was ich auch gelesen habe. Die Macros stellen nicht sicher, das ich einen bestimmten Standard vorfinde. Aber wenn der Code, den ich schreibe auf einem alten System eine Anwendung ausblenden soll weil eine glibc Funktion nicht zur Verfügung steht, muss ich hierfür selber auf jedem System altersabhängig die Macros umdefinieren.
Ansonsten definiere ich die Macros wie ich sie gerne hätte und schreibe den Code so, das er auf dem ältesten System übersetzbar ist oder ich verzichte auf Systeme ab einem bestimmten Alter.Wenn es mit dem Feature Test Macros so ist, wie kann ich feststellen ob der Quellcode gerade auf einem 3er gcc mit 2.2er Linux + entsprechender glibc übersetzt wird oder auf einem aktuellen Debian 6.0 mit aktuellerer Umgebung.
Gruß,
BlackPepper
-
BlackPepper schrieb:
Wenn es mit dem Feature Test Macros so ist, wie kann ich feststellen ob der Quellcode gerade auf einem 3er gcc mit 2.2er Linux + entsprechender glibc übersetzt wird oder auf einem aktuellen Debian 6.0 mit aktuellerer Umgebung.
Der GCC definiert ein paar Makros, die nützlich sind:
http://gcc.gnu.org/onlinedocs/cpp/Predefined-Macros.html#Predefined-MacrosAber eigentlich ist das Aufgabe des Buildsystems, festzustellen, ob die nötigen Features vorhanden sind, und ggf. Ersatz zu definieren (oder die Übersetzung zu verweigern). Konkret findet diese Prüfung auf Ebene des configure-Scripts statt. Die GNU autotools helfen dir, deinen Code automatisch nach benutzten Features zu untersuchen und ein entsprechendes configure-Script zu erstellen.
-
SeppJ schrieb:
*: Wenn keine Not am Mann ist, dann sollte dieser Standard ANSI-C oder wenigstens GNU-C sein. Das heißt, du solltest diese Makros gar nicht brauchen.
Die Nutzung von GNU C (-std=gnuXY) aktiviert (unter Glibc) einen Teil dieser Makros implizit. Wenn er Sachen wie fchmod benötigt, wird er mit ANSI C sowieso nicht auskommen.
Das ganze verhält sich (unter Glibc) so:
Kompilierst du mit einem ISO-C-Schalter (-std=cXY) sind viele POSIX- oder Glibc-spezifische Deklarationen in den Headern nicht sichtbar. Möchtest du sie dennoch nutzen, musst du in der Tat die entsprechenden Feature-Test-Makros selbst setzen.Aufgrund der unterschiedlichen Semantik der Makros in der BSD- und Solaris-libc[*] würde ich sie allerdings nicht im Quellcode definieren. Lieber im Makefile.
[*] Dort ist standardmäßig alles sichtbar. Die Makros schränken die Sichtbarkeit dann auf die durch den entsprechenden Standard gegebenen Dinge ein. Bei Glibc kann man die Makros auch additiv verwenden.
-
Hallo Sepp3 und Mieser Schimmler,
das heißt dann ich definiere im Buildsystem die Macros, prüfe dann ob die gewünschten Funktionen enthalten sind und reagiere dann auf das Prüfergebnis. Das ist ja mit den Autotools recht einfach, z.B.
AC_CHECK_LIB([m],[round] ,[MATH_LIBS="-lm"],[AC_MSG_ERROR([round() in libm.a needed but not found])])
Ein
AC_FUNC_ROUND
gibt es nämlich nicht. (http://www.gnu.org/software/autoconf/manual/autoconf.html)
Der Quellcode muss dann aber bereits an einem bestimmten Standard angepast sein und für fehlende Funktionen selbst für Ersatz sorgen. Das Buildsystem muss dann dafür sorgen, das die Übersetzung des Quellcodes dem System entsprechend läuft oder die Übersetzung abbrechen.
Aber dann brauche ich die Macros nur um glibc Funktionen zugänglich zu machen wenn sie denn da wären.Weil folgender Quellcode benutzt die altenative wenn ich die Macros nicht definiere. Zumindest bei mir.
gcc (GCC) 4.2.4 (Debian 4.2.4-6)
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.#include <stdio.h> #include <stdlib.h> #include <math.h> double iff_round(double value) { double integer_value = 0.0; #if _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE || _POSIX_C_SOURCE >= 200112L integer_value = round(value); #else double fractional_value = 0.0; fractional_value = modf (value, &integer_value); if (integer_value < 0.0) { if (fractional_value < -0.5) { integer_value = integer_value - 1.0; } else { /* Do nothing */ } } else { if (fractional_value >= 0.5) { integer_value = integer_value + 1; } else { /* Do nothing */ } } #endif return integer_value; } int main(int argc, char *argv[]) { double number_one = 13.198553490; double number_two = 13.998553490; #if !( defined _XOPEN_SOURCE ) printf("_XOPEN_SOURCE ist nicht definiert\n"); #endif #if !( defined _ISOC99_SOURCE ) printf("_ISOC99_SOURCE ist nicht definiert\n"); #endif #if !( defined _POSIX_C_SOURCE ) printf("_POSIX_C_SOURCE ist nicht definiert\n"); #endif printf("Number=%f gerundet=%f\n", number_one, iff_round(number_one)); printf("Number=%f gerundet=%f\n", number_two, iff_round(number_two)); return EXIT_SUCCESS; }
Gruß,
BlackPepper