C/C++ Umgebungs-Daten

Umgebungs-Variable, CLI-Argumente (argc,argv)

Die meisten Programmiersprachen bieten Funktionen, die Informationen über die Umgebung liefern. Diese dienen als Grundlage für die Erstellung professioneller Programme, die unabhängig von der Umgebung laufen sollen.
C/C++ Klassiker der modernen Programmiersprachen
Umgebungs-Daten Die wichtigsten Methoden zur Übergabe von Daten an Programme
CLI Commandline Interface (CLI) Argumente, die Variablen argc und argv
CLI-Decodierung Decodierung der von einem Programm erhaltenen Argumente
CLI für Profis Struktur der CLI Argumente
ENV Struktur der Umgebungs-Variablen
Funktion getenv() Standard C/C++ Funktion zum Lesen von Umgebungs-Daten
System-Befehl Erteilen eines System-(Konsolen)-Befehls und Analyse der erhaltenen Daten
HTTP-GET Decodierung von User-Daten mit der GET-Methode
HTTP-POST Decodierung von User-Daten mit der POST-Methode
Preprocessor Umgebungs-Daten des C/C++ Compiler-Programms
Verwandte Themen Umgebungs-Daten in Perl, PHP, VBA

Umgebungs-Daten

Jedes Programm (Prozess) erhält von seinem parent (Umgebungs)-Daten. Parent ist jenes Programm, von dem ein Prozess gestartet wurde.

Die Auswahl der Daten hängt von der Anwendung ab:
Eine Konsole (Shell, cmd.exe), ein Server (Zeit-Server cron, Webserver httpd, ...) oder ein anderes parent-Programm können einem von ihnen gestarteten child-Programm ganz unterschiedliche Daten mitgeben. Auf dieser Seite werden einige davon vorgestellt.
Mit Hilfe der erhaltenen Daten kann man das Verhalten eines Programms an unterschiedliche - zur Ausführungs-Zeit herrschende - Bedingungen anpassen. Alle Programmiersprachen bieten Funktionen zum Lesen der erhaltenen Umgebungs-Daten, auch C/C++.

CLI-Argumente

Wenn man ein Programm an einer Konsole startet, dann kann man nach Angabe seines Namens (Pfades) weitere Daten (CommandLine Interface Argumente, Optionen, Schalter) in der Befehlszeile angeben.
Beispiel: Start des 'directory'-Programms an einer Windows-Konsole:
C:\> dir
C:\> dir /?
C:\> dir *.cpp
C:\> dir /A *.txt

Die CLI-Argumente dienen zur Steuerung des aufgerufenen (Child)-Programms. Es gibt dazu nur wenige Regeln: Die einzelnen Argument-Daten sind Strings und werden voneinander durch Leerzeichen getrennt.

CLI-Argumente kann man allerdings nicht nur manuell übergeben, sondern auch durch jedes andere parent-Programm, einfach durch Anfügen an den jeweiligen Befehlstext.

Details im Kapitel ↓ CLI-Argumente dieser Seite.

System-Variable

Jedes Betriebssystem definiert einige (meist global verfügbare) Variable mit Umgebungs-Daten von allgemeiner Bedeutung.
Beispiel: (Linux, Windows):
# export
C:\> set

C/C++ bietet mit der Funktion getenv() die Möglichkeit, jede dieser Variablen zu lesen.

Details zur Verwendung der C/C++ Funktion ↓ getenv()

Leider werden von den gängigen Betriebssysteme und -Versionen sehr unterschiedliche Namen für die jeweiligen Umgebungs-Variablen verwendet. Lediglich eine besonders wichtige Daten findet man in jedem Betriebssystem unter dem gleichen Variablen-Namen.

Windows ist ein komplizierter Fall: Zwar gibt es auch hier Umgebungs-Variable, die meisten Umgebungs-Daten sind jedoch in der Registry-Datenbank organisiert, die nur mit besonderen Maßnahmen zugänglich ist.

CGI-Variable

sind Umgebungs-Variable, die von einem Webserver an die von ihm gestarteten CGI-HilfsProgramme übergeben werden.
Beispiel: Jedes CGI-Programm kann die → IP-Adressen von Client und Server lesen:
getenv('REMOTE_ADDR') = 38.107.179.213
getenv('SERVER_ADDR') = 195.70.232.194

Auch diese Daten sind mit Funktion getenv() lesbar. Sie werden zum Glück sehr einheitlich verwendet. Jeder professionelle Webserver bietet die Möglichkeit, zusätzlich individuell definierte Umgebungs-Variable an alle oder nur an bestimmte CGI-Programme weiterzugeben.

GET-Argumente

Die meisten Webseiten werden mit Hilfe der GET-Anweisung des → HTTP-Protokolls angefordert. Diese Anweisung wird als einfacher Klartext im Netzwerk transportiert.
Beispiel: Suche nach den Stichworten http und get bei Google:

Die Syntax (Grammatik) Des HTTP-Protokolls erlaubt es, nach dem Namen des angeforderten Web-Dokuments einige Daten als QUERYSTRING anzugeben. Wenn die angeforderte Datei ein CGI-Programm ist, dann gibt der Webserver diesen String an das Programm weiter.

Details zur Decodierung von GET-Daten

POST-Argumente

Das HTTP-Protokoll erlaubt alternativ zu einer GET-Anweisung die Anforderung von Web-Daten mit der POST-Methode. Für BesucherInnen von Webseiten ergeben sich keine merkbaren Unterschiede.

Diese Methode wird weniger oft verwendet als GET und erlaubt die Übergabe umfangreicher Daten an ein angefordertes CGI-Programm.

Details zur Decodierung von POST-Daten

Preprocessor Umgebung

Der C/C++ Preprocessor ist ein Programm wie jedes andere und verfügt daher ebenfalls über eigene Umgebungs-Daten.
Diese Daten gelten allerdings für das Compiler-Programm und nicht für das mit dem Compiler erzeugte Programm.

Die Preprocessor Umgebungs-Daten gelten für jenen PC, auf dem der Compiler ausgeführt wurde und für den Zeitpunkt der Compilierung. Diese Daten sind für ein fertiges Projekt kaum brauchbar, jedoch während der Entwicklung wertvoll.

Commandline Interface (CLI) Argumente

Standard-Argumente argc, argv

Wenn man ein beliebiges Programm an einer → Konsole (→ Linux-Shell, → Windows cmd.exe) startet, dann kann man ihm in der Befehls-Zeile Daten (Argumente, Optionen, Schalter) mitgeben.
Das Programm kann diese Daten zu seiner Steuerung verwenden.

Jedes Programm erhält mindestens 2 Argumente: argc, argv
argc ... Anzahl der in argv enthaltenen Elemente
argv ... Pointer auf ein Array von Pointern. Jeder dieser Pointer zeigt auf einen String, welcher das jeweilige Argument enthält.

Die Namen der argc und argv sind nicht vorgeschrieben, jedoch sehr empfehlenswert: Jede/r EntwicklerIn kennt diese Namen und ihre Bedeutung.
C/C++ Quelltext-Datei argtest.cpp
Das Programm gibt die erhaltenen CLI-Argumente als Text aus. Das Programm ist in dieser Form weit verbreitet.
#include <stdio.h>
int main(int argc, char* argv[]) {
int n;
printf("argc = %d\n",argc);
for (n=0;n<argc;n++) {
printf("argv[%d] = %s\n",n,argv[n]);
}
return 0;
}
Eine äquivalente Formulierung der ersten main()-Zeile lautet:
int main(int argc, char **argv) {...}

Fortgeschrittene EntwicklerInnen können die ↓ Programm-Versionen der folgenden Kapitel studieren, die nicht nur die CLI-Daten sondern die zugrunde liegende Strukturen ausgeben.
Anwendung: Starten sie das Programm z.B. mit diesen Befehlszeilen:
C:\> argtest
C:\> argtest zapp
C:\> argtest \?
C:\> argtest wapp=zapp abc=123
C:\> argtest "String mit Leerzeichen"
Beispiel für die Ausgabe:
C:\> argtest ab=xyz cd=123
argc = 3
argv[0] = argtest
argv[1] = ab=xyz
argv[2] = cd=123

Programm-Start ohne Argumente

Wenn man das oben vorgestellte C-Programm argtest.cpp compiliert (=in ein ausführbares Programm argtext.bin oder argtest.exe umwandelt), dann kann man es an einer Konsole starten - im einfachsten Fall durch Eingabe des Pfades zum Programm, ohne weitere Daten:

Das Betriebssystem übergibt den Pfad zum Programm als erstes Argument. Mindestens dieses Argument ist daher immer enthalten, daher ist immer argc>=1 und in diesem Fall argc=1
Beispiel: Start ohne Argumente an einer Linux Shell-Konsole:
# /home/ich/bin/argtest.bin
argc=1
argv[0]=/home/ich/bin/argtest.bin
#
Start ohne Argumente an einer Windows-Konsole cmd.exe :
C:\> C:\Programme\argtest.exe
argc=1
argv[0]=C:\Programme\argtest.exe
C:\>

Programm-Start mit Argumenten

Man kann beim Start jedes beliebigen Programms weitere Daten als Text nach dem Programm-Namen (oder Pfad) angeben. Es liegt am Programm, ob es diese Daten verwertet.

Oft verwendete Argumente sind /? oder help - Die meisten Konsolen-Programme geben darauf einen Hilfe-Text aus, z.B.
C:\> set /?
C:\> ipconfig help

Es gibt keine fixen Regeln zur Gestaltung der Argument-Texte. Sie sollten kurz aber verständlich oder zumindest leicht merkbar sein und keine Umlaute oder Sonderzeichen enthalten.
Tipp: Wenn man Argumente in der Form name=wert angibt, dann kann man die gleichen Funktionen wie zur Decodierung von GET-Argumenten verwenden.

Beispiel: Start mit Argumenten
# /home/ich/bin/argtest.bin x=12 "a b" -q
argc=4
argv[0]=/home/ich/bin/argtest.bin
argv[1]=xyz
argv[2]=a b
argv[2]=-q
#

Mehrere Argumente werden voneinander durch Leerzeichen getrennt. Wenn ein Argument selbst Leerzeichen enthalten soll, dann schließt man den Text in "" ein.

Automatischer Programm-Start

Mit einem entsprechenden Server-Programm (Linux cron, Windows Scheduler) kann man jedes Programm zu vorbestimmten Zeiten oder Anlässen (Events) automatisch starten lassen.

In der Befehlszeile kann man Argumente angeben. Geben sie diese genauso wie an der Konsole nach dem Pfad zum Programm an.

Automatisch gestartete Programme erhalten auf Linux aus Sicherheits-Gründen nur ganz wenige Umgebungs-Daten. In diesem Fall kann man unbedingt benötigte Daten als Argumente mitgeben oder vom Programm aus einer Text-Datei lesen lassen.

Decodierung von CLI-Argumenten

Decodierung von Argumenten

Alle Argumente werden als Strings übergeben, d.h. in C/C++ als Kette aufeinander folgender Bytes, abgeschlossen mit einem 0-Byte.

Um die erhaltenen CLI-Daten im Programm zu verwenden, muss man die erhaltenen Argumente untersuchen. Das Beispiel rechts zeigt eine Möglichkeit, um eine ganze Zahl zu decodieren, die als Argument in der Form i=%d erwartet wird, z.B.
# argtest2 i=123

Dazu werden alle Argumente argv[>=1] an die Funktion decode_i() übergeben. Außerdem erhält die Funktion einen Pointer auf die Variable i, damit sie die gefundenen Daten dort einträgt.

Die Funktion gibt den Erfolg zurück (gesuchte Daten gefunden oder nicht). Bei Erfolg (ok>0) werden die mit sscanf() decodierten Daten an der erhaltenen Adresse pi eingetragen.

Vorsicht: Das Programm arbeitet nur in einfachen Fällen wie erwartet, weil das Ergebnis ungeprüft verarbeitet wird.
C/C++ Quelltext-Datei argtest2.cpp
Das Programm sucht nach einem Argument i=%d (vereinfacht):
#include <stdio.h>
int decode_i(int*,char*);

int main(int argc, char* argv[]) {
int i,n,ok;
printf("argc=%d\n",argc);
for (n=1;n<argc;n++) {
printf("\nargv[%d]=%s\n",n,argv[n]);
ok=decode_i(&i,argv[n]);
if(ok) {printf("gefunden: i=%d\n",i);}
}
return 0;
}

int decode_i(int *pi,char *s) {
// Decode Argument i=%d
int i,ok;
ok=sscanf(s,"i=%d",&i);
if(ok) {*pi=i;}
return ok;
}

Struktur der CLI-Argumente

Details (für Fortgeschrittene)

Das Beispiel zeigt die Details bei der Übergabe von Argumenten:

Die Aufgabe besteht darin, eine variable Anzahl argc von Argumenten variabler Größe zu übergeben.
Sie wird gelöst, indem der Pointer argv auf ein Array von Pointern zeigt:
An der mit argv angegebenen Adresse befindet sich der Pointer argv[0], im Abstand von (normalerweise) 4 Byte der Pointer argv[1], im Abstand von 8 Byte der Pointer argv[2] usw.
Die Anzahl der im Array argv enthaltenen Pointer ist um +1 größer als die Anzahl der nach dem Programm-Namen angegebenen Argumente.
Jeder Pointer argv[0]...argv[argc-1] zeigt auf eine Adresse, an der sich die Zeichen (Bytes) des jeweiligen Arguments befinden.
Am Ende jedes Strings ist ein Null-Byte eingetragen. (Dieses und andere nicht druckbare Zeichen wird vom Programm als . Punkt ausgegeben).

Der erste Pointer argv[0] enthält den gesamten Text vor dem 1. Leerzeichen, d.h. den eingegebenen Programm-Namen oder -Pfad. Dieser String ist daher immer verfügbar - auch dann, wenn keine Argumente übergeben wurden.

Tipp: Starten sie das Programm mit unterschiedlich vielen Argumenten. Alle verwendeten Pointer und die an den angegebenen Adressen enthaltenen Daten werden angegeben (jedoch von längeren Strings nur die ersten 20 Zeichen).
C/C++ Quelltext-Datei argtest3.cpp
Das Programm gibt die Details der Pointer und Daten aus:
#include <stdio.h>
void dump_string(char*);

int main(int argc, char* argv[]) {
int n;
printf("\n### Commandline-Argumente ###\n");
printf("Integer argc = %d\n",argc);
printf("Pointer argv = %p\n",argv);
for (n=0;n<argc;n++) {
printf("\nargv[%d]:\n",n);
printf("*%p = %p\n",&argv[n],argv[n]);
dump_string(argv[n]);
}
return 0;
}

void dump_string(char *p) {
// Byte-weise Ausgabe ab Adresse p
int offset=0;
char c=1;
printf("*%p =\n",p);
// Hexadezimale Ausgabe von <=20 Bytes
while(c) {
c=*(p+offset);
printf("%02X ",c);
offset++;
if(offset>20) {printf("..."); c=0;}
}
printf("\n");
c=1; offset=0;
// Zeichen Ausgabe von <=20 Bytes
while(c) {
c=*(p+offset);
if(c>31 && c<127) {printf(" %c ",c);}
else{printf(" . ");}
offset++;
if(offset>20) {printf("..."); c=0;}
}
printf("\n");
}
Beispiel für die Anwendung des Programms argtest3 (Linux) bzw. argtest3.exe (Windows) mit je 2 Argumenten:
# argtest3 abc 123
C:\> argtest3 abc 123

RAM-Dump der Strings (je 8 Byte pro Zeile, bekannte Bytes sind eingetragen, die übrigen mit .. Punkten angedeutet):
003E3ED0 .. .. .. .. .. .. .. ..
003E3ED8 .. 61 72 67 74 65 73 74
003E3EE0 33 00 .. 61 62 63 00 ..
003E3EE8 31 32 33 00 .. .. .. ..
RAM-Dump der Pointer:
003E3F28 D9 3E 3E 00 E3 3E 3E 00
003E3F30 E8 3E 3E 00 .. .. .. ..
Ausgabe-Text des Programm-Beispiels argtest3:
(Die Werte der Pointer variieren, sind daher nur Beispiele).
Integer argc = 3
Pointer argv = 003E3F28

argv[0]:
*003E3F28 = 003E3ED9
*003E3ED9 =
61 72 67 74 65 73 74 33 00 
 a  r  g  t  e  s  t  3  . 

argv[1]:
*003E3F2C = 003E3EE3
*003E3EE3 =
61 62 63 00 
 a  b  c  . 

argv[2]:
*003E3F30 = 003E3EE8
*003E3EE8 =
31 32 33 00 
 1  2  3  . 

Environment-Pointer

Standard-Argumente argc, argv, envp

Zusätzlich zu den 'klassischen' Argumenten argc und argv erhalten ausführbare Programme als 3. Argument einen Environment-Pointer env
Damit kann ein (Parent)-Programm eine beliebige Anzahl von Umgebungs-Daten an einen von ihm gestarteten (Child)-Prozess weitergeben.

Das 3. Argument env ist ein Pointer auf ein Array von Pointern. Das Array enthält beliebig viele weitere Pointer auf Strings. In diesem Fall wird jedoch nicht die Anzahl der Array-Elemente angegeben, sondern das Ende ist durch einen NULL-Pointer definiert.

Jedes Programm erhält normalerweise 3 Argumente: argc, argv, envp

argc ... Anzahl der in argv enthaltenen Elemente

argv ... Pointer auf ein Array von Pointern. Jeder dieser Pointer zeigt auf einen String, welcher das jeweilige Argument enthält. Das Array argv enthält argc Elemente. Die Anzahl der Elemente ist bekannt, daher werden sie in einer for-Schleife durchlaufen.

env ... Pointer auf ein Array von Pointern. Jeder dieser Pointer zeigt auf einen String, welcher das jeweilige Argument enthält.
Alle ENV-Strings sind in der Form NAME=wert angegeben. Die Anzahl der Elemente ist zunächst unbekannt, daher werden sie in einer while-Schleife durchlaufen.
C/C++ Quelltext-Datei clitest.cpp
Das Programm zeigt alle 3 erhaltenen Argumente inklusive der damit erreichbaren Array-Elemente an:
#include <stdio.h>
int main(int argc,char* argv[],char* env[]) {
int n;
printf("Content-Type: text/plain;\r\n\r\n");

printf("argc=%d\n",argc);
printf("argv = %p -> %p\n",argv,*argv);
for (n=0;n<argc;n++) {
printf("argv[%d] = %p -> %s\n",n,argv[n],argv[n]);
}

printf("\nenv = %p -> %p\n",env,*env);
n=0;
while(env[n]!=NULL) {
printf("env[%d] = %p -> %s\n",n,env[n],env[n]);
n++;
}
printf("env[%d] = %p\n",n,0);

return 0;
}
Das Programm gibt alle jeweils erhaltenen CLI-Argumente und danach alle erhaltenen ENV-Elemente als Text aus. Die Ausgabe enthält sowohl die Pointer als auch die Daten. Die erste Zeile der Ausgabe wird von einem CGI-Programm gebraucht.

Beispiel:

Liste der CLI-Argumente und Umgebungs-Daten durch ein mit C/C++ erstelltes Programm, ausgeführt als Webserver-(CGI)-Hilfsprogramm (Die 1. Ausgabe-Zeile mit der Ankündigung der → MIME-Type wird in diesem Fall nicht ausgegeben):
argc=1
argv = 003E24F8 -> 003E24C1
argv[0] = 003E24C1 -> /srv/www/cgi-bin/clitest

env = 003E2AF8 -> 003E2B78
env[0] = 003E2B78 -> HTTP_HOST=demo-server
env[1] = 003E2BF8 -> HTTP_ACCEPT=text/html;q=0.9,*/*;q=0.8
env[2] = 003E2C50 -> HTTP_ACCEPT_LANGUAGE=de,en;q=0.5
env[3] = 003E2C80 -> HTTP_ACCEPT_ENCODING=gzip, deflate
env[4] = 003E2CB0 -> HTTP_ACCEPT_CHARSET=ISO-8859-1,utf-8;q=0.7,*;q=0.7
env[5] = 003E2CF0 -> HTTP_CONNECTION=keep-alive
env[6] = 003E2FC0 -> SERVER_SOFTWARE=Apache/2.2
env[7] = 003E2FF0 -> SERVER_NAME=demo-server
env[8] = 003E3010 -> SERVER_ADDR=192.168.0.1
env[9] = 003E3030 -> SERVER_PORT=80
env[10] = 003E3048 -> REMOTE_ADDR=192.168.0.23
env[11] = 003E30B8 -> SCRIPT_FILENAME=/srv/www/cgi-bin/clitest
env[12] = 003E30E8 -> REMOTE_PORT=1066
env[13] = 003E3108 -> GATEWAY_INTERFACE=CGI/1.1
env[14] = 003E3130 -> SERVER_PROTOCOL=HTTP/1.1
env[15] = 003E3158 -> REQUEST_METHOD=GET
env[16] = 003E3178 -> QUERY_STRING=
env[17] = 003E3190 -> REQUEST_URI=/cgi-bin/clitest
env[18] = 003E31B8 -> SCRIPT_NAME=/cgi-bin/clitest
env[19] = 00000000

Konsole

Starten sie das mit C/C++ erzeugte Programm an der Konsole, z.B. (Linux, Windows):
# /home/test/argtest4
C:\> C:\test\argtest4.exe

Sie erhalten meist eine relativ lange Liste von Umgebungs-Daten.
Die Namen der erhaltenen Umgebungs-Variablen unterscheiden sich leider je nach Betriebssystem und -Version erheblich. Wenn man derartige nicht portable Daten in einem Programm verwendet, dann muss man auch vom C/C++ Quelltext eine eigene Version für jedes gewünschte Betriebssystem herstellen.

Webserver-(CGI)-Hilfsprogramm

Kopieren sie das mit C/C++ erzeugte Programm in das CGI-Arbeits-Verzeichnis eines Webservers, z.B.:
/srv/www/cgi-bin/argtest4
C:\Web\cgi-bin\argtest4.exe
Ändern sie auf Linux die ZugangsRechte, d.h. erteilen sie Lesen+Ausführen für alle User.
Starten sie am gleichen PC ein Browser-Programm und geben sie die Web-Adresse des CGI-Programms ein, z.B.
http://localhost/cgi-bin/argtest4
http://localhost/cgi-bin/argtest4.exe

Sie erhalten eine ganz andere Liste als vom gleichen Programm an der Konsole. Die Namen der meisten Umgebungs-Variablen sind standardisiert und die Daten daher gut brauchbar.
Das Programm ist in der hier gezeigten Version zwar gut geeignet, um eine Liste der Umgebungs-Variablen anzuzeigen, jedoch weniger gut, um diese Daten in einem Programm zu verwenden. Zum Lesen von Umgebungs-Variablen mit bereits bekannten Namen eignet sich die ↓ Funktion getenv() wesentlich besser.

Funktion   getenv()

getenv()

Diese Funktion ist in der Bibliothek <stdlib.h> enthalten und liefert die Daten einer Umgebungs-Variablen als String. Sie müssen den Namen der jeweiligen Variablen kennen um die Funktion anzuwenden.

Wenn sie die Namen der erhaltenen Variablen nicht kennen, verwenden sie den ↑ Environment-Pointer zu einer Anzeige einer Liste.

Die Namen der Umgebungs-Variablen sind nur bei Verwendung von Webserver-(CGI)-Hilfsprogrammen einigermaßen portabel und daher verlässlich.

Wenn sie die vom Betriebssystem erhaltenen Umgebungs-Daten verwenden wollen, müssen sie die verwendeten Namen an jedes System, teilweise an einzelne Versionen individuell anpassen.
Beispiel: Die Umgebungs-Variable PATH ist unabhängig von Betriebssystem und -Version fast immer verfügbar:
#include <stddio.h>
#include <stdlib.h>

int main(void) {
char *pe;
pe = getenv("PATH");
if(pe) { printf("PATH=%s\n",pe); }
else{ printf("PATH ist nicht definiert\n"); } return 0;
}

Parent

Die Umgebungs-Variablen werden vom aufrufenden (Parent)-Programm übergeben. Je nach Parent kann das gleiche Programm daher ganz unterschiedliche Umgebungs-Variablen erhalten. Unterscheiden sie mindestens diese Parents:

Konsole: An der → Linux-Shell erhalten sie die Liste so:
# export
an der → Windows-Konsole cmd.exe:
C:\> set

Server-Programme
Je nach Programmierung und Konfiguration geben die Server-Programme unterschiedliche Umgebungs-Variablen an die von ihnen gestarteten Programme weiter. Besonders knausrig ist z.B. der Linux-Server crond: Er gibt aus Sicherheits-Gründen nur wenige Variable an Programme weiter, die von ihm Zeit-gesteuert automatisch gestartet werden.

Webserver: Ein Webserver-(CGI)-Hilfsprogramm erhält einige typische Umgebungs-Variablen, die man z.B. im Globalen Array $_SERVER von → PHP übersichtlich studieren kann.

Zusätzlich kann man die Umgebungs-Variablen in der Konfiguration des → Apache Webservers manipulieren, z.B.:
Anweisung SetEnv erzeugt eine (neue, eigene) Umgebungs-Variable
Anweisung PassEnv gibt eine Variable weiter, die der Webserver selbst erhalten hat, normalerweise jedoch nicht weitergibt.
Anweisung SetEnvIf erzeugt eine Umgebungs-Variable abhängig von Bedingungen.

Großbuchstaben

Linux (und alle anderen gängigen Betriebssysteme) unterscheidet streng zwischen großen und kleinen Buchstaben. Die Namen HTTP_PROXY und http_proxy bezeichnen daher 2 verschiedene Variable !

Tipp: Verwenden sie nach Möglichkeit nur Großbuchstaben für die Namen von Umgebungs-Variablen. Wenn der gleiche Name in mehreren Varianten definiert ist, dann sollte die Werte unbedingt übereinstimmen !

Windows unterscheidet in den meisten Fällen nicht zwischen großen und kleinen Buchstaben, es gibt davon jedoch auch Ausnahmen.

Testen sie daher im Zweifel stets alle in Frage kommenden Namens-Varianten !

CGI-Programme

Wenn ein Programm als Webserver-(CGI)-Hilfsprogramm erbeitet, dann kann man vom Client (Browser) Daten an das Programm senden. Das erfolgt typisch mit Hilfe von → HTML <form>-Elementen (Formularen).
Zum Transport der User-Daten werden 2 unterschiedliche Methoden des → HTTP-Protokolls verwendet: GET oder POST

Das (z.B. mit C/C++ hergestellte) Empfangs-Programm muss die erhaltenen Daten verwerten. Zur Auswertung werden u.a. 2 Umgebungs-Variablen verwendet: Mit der GET-Methode QUERYSTRING, mit der POST-Methode CONTENT_LENGTH

Details zur Decodierung von GET_ und POST-Daten

Verwandte Funktionen

Die Funktionen putenv(), setenv(), unsetenv() erlauben die Manipulation von Umgebungs-Variablen durch ein C/C++ Programm.
Die sinnvolle Anwendung erfordert fortgeschrittene Kenntnisse und wird hier nicht vorgestellt.

Tipp: Verwenden sie Umgebungs-Variable im Zweifel immer wie ReadOnly-Daten.

Umgebungs-Daten mit System-Befehl

Das Beispiel rechts verwendet den Konsolen-Befehl des jeweiligen Betriebssystems, um alle Umgebungs-Variablen auszugeben. Der gesamte Ausgabe-Text wird in eine Pipe umgeleitet und zeilenweise an die String-Variable line übergeben.

An der bezeichneten Stelle kann man jede erhaltene Text-Zeile analysieren und/oder verarbeiten.

Diese Methode setzt keine Kenntnisse der Namen der Umgebungs-Variablen voraus: Sie liefert in jeder Zeile sowohl den Namen als auch den Wert der jeweiligen Variablen.

Details zum Erteilen und Analysieren von System-Befehlen mit C/C++
Analyse der ausgeführten System-Befehle:
#include <stdio.h>
int main() {
char *s="export";   // Linux
//char *s="set";   // Windows
char line[200];
FILE *pipe;
pipe = (FILE*)popen(s,"r");
if(pipe) {
while ( fgets( line, sizeof line, pipe)) {
printf("line=%s", line);
// Text hier verarbeiten
}
pclose(pipe);
}
return 0;
}

Preprocessor Umgebung

Die Makro-Konstanten des Preprocessors beschreiben die Umgebungs-Daten des Compilers zum Zeitpunkt der Compilierung. Man kann sie u.a. zum Debuggen und zum 'Bedingten Compilieren' verwenden. In diersem Kapitel wird eine kleine Auswahl (!) von Preprocessor-Makros vorgestellt.
Links: GCC Macros, Predefined Compiler Macros (Sourceforge Projekt)

Compiler-Makros

Wenn man den → GNU GCC Compiler mit dem Schalter -dM startet, dann erhält man eine (lange) Liste aller als 'System-spezifisch' angegebenen Makros. Diese Makros sind zusätzlich zu den nach C/C++ Standard definierten Makros definiert.

Man muss wie üblich eine Eingabe-Datei (*.h, *.c, *.cpp) angeben, jedoch keine Ausgabe-Datei. Als Eingabe-Datei (hier dummy.h) genügt eine leere Text-Datei.
In jedem Fall ist es empfehlenswert, die Liste zu sortieren, (mit grep) zu filtern und/oder in eine Text-Datei auszugeben.
Linux:
# touch dummy1.h; cpp -dM dummy1.h | sort
# touch dummy2.h; cpp -dM dummy2.h | grep linux
# touch dummy3.h; cpp -dM dummy3.h | sort >> makroliste.txt
# rm dummy*

Windows:
C:\> cpp -dM dummy.h
C:\> cpp -dM dummy.h | sort >> makroliste.txt

Bedingte Compilierung:

Der Quelltext eines guten C/C++ Programms sollte portabel sein. Manchmal muss man jedoch einzelne Anweisungen je nach Umgebung (z.B. Betriebssystem) unterschiedlich programmieren.
Im Beispiel werden dazu die Preprocessor-Konstanten System_Linux, System_Windows (nächster ↓ Absatz) verwendet: Beim Compilieren werden nur die zum System passenden Anweisungen eingebunden.
Alle portablen Anweisungen folgen nach #endif
Aus dem gleichen Quelltext werden je nach Betriebssystem teilweise unterschiedliche Anweisungen compiliert:
#ifdef System_Linux
/* ...Linux-Anweisungen... */
#endif
#ifdef System_Windows
/* ...Windows-Anweisungen... */
#endif

Hardware und System

Die wichtigste Information ist die BusBreite des Systems. Dazu gibt es leider mehrere Makro-Konstanten, z.B. für 32-Bit(i386, __i386, __i386__, _X86_) oder 64-Bit(__amd64, __amd64__, __x86_64, __x86_64__, _LP64, __LP64__). Ihr Wert ist - wenn definiert - stets 1 und lässt sich daher zu einer einzigen Konstanten zusammenfassen. Das Beispiel berücksichtigt zur besseren Übersicht nur je 3 der Konstanten.

Für alle gängigen Betriebssysteme gibt es ebenfalls mehrere Makro-Konstanten, z.B. für Linux (linux, __linux, __linux__, unix, __unix, __unix__) oder Windows(WIN32, WINNT, _WIN32, __WIN32, __WIN32__, ...) Ihr Wert ist - wenn definiert - stets 1 und lässt sich zusammenfassen.
Hardware (Bus-Breite):
#if i386 || __i386_ || _X86_
#define System_32
#endif
#if __amd64 || __x86_64 || __x86_64__
#define System_64
#endif

Betriebssystem
#if linux || __linux || __unix__
#define System_Linux 1
#endif
#if WIN32 || _WIN32 || WINNT
#define System_Windows 1
#endif

Quelltext-Datei und -Zeile

Die beiden Makro-Konstanten __FILE__ und __LINE__ bezeichnen Datei-Pfad (String) und Zeile (als ganze Zahl).
Die Konstante __BASE_FILE__ ist nur im GCC Compiler definiert. Sie gibt den Pfad zur ersten im Compiler-Befehl angegebenen Quelltext-Datei an - normalerweise zum 'Hauptprogramm'.
Damit kann man z.B. schwer auffindbare Fehler lokalisieren, insbesondere in komplexen Projekten mit zahlreichen einzelnen Quelltext-Dateien.
Anwendung:
printf("Pfad: %s\n",__FILE__);
printf("Zeile: %d\n",__LINE__);

Datum und Zeit

Die beiden Makro-Konstanten __DATE__ und __TIME__ bezeichnen den Zeitpunkt der Compiler-Arbeit am Entwicklungs-PC. Sie ändern sich nur dann, wenn das Programm erneut compiliert wurde.
Die Makro-Konstante __TIMESTAMP__ ist nur im → GCC COmpiler definiert. Sie gibt den Zeitpunkt der letzten Änderung der jeweiligen Quelltext-Datei als String an.
Daten und Format sind vom Betriebssystem abh&aumkl;ngig.
Anwendung:
printf("Datum: %s\n",__DATE__);
printf("Zeit: %s\n",__TIME__);
#ifdef __TIMESTAMP__
printf("Timestamp: %s\n",__TIMESTAMP__);
#endif
Alternative: Datum und Zeit zur Ausführungs-Zeit

C oder C++

Die Makro-Konstanten __cplusplus und __OBJC__ geben an, mit welcher Variante der Programmiersprache compiliert wurde.
In C ist __cplusplus nicht definiert, in C++ wird die Version angegeben.
Bedingte Verzweigung:
#ifdef __cplusplus
printf("cplusplus=%s\n",__cplusplus);
#else
printf("cplusplus ist nicht definiert\n");
#endif

GNU GCC Compiler

Die beiden Makro-Konstanten __GNUC__ und __GNUG__ (nur in C++ definiert) bezeichnen die C bzw. C++ Version des → GNU GCC Compilers als Strings.
Anwendung:
printf("GNUC: %s\n",__GNUC__);
#ifdef __GNUG__
printf("GNUG: %s\n",__GNUG__);
#endif

Typen

Eine sehr große Anzahl von Makro-Konstanten bezeichnet die Eigenschaften der Variablen-Typen. Die mit __SIZEOF_ beginnenden Konstanten sind fast immer definiert und geben den Speicherplatz für eine Variable der jeweiligen Type in Byte an.

Aus diesen Daten kann man selbst alle wichtigen Eigenschaften ableiten, z.B.
Werte-Bereich von ganzzahligen Typen
Werte-Bereich und Genauigkeit von Gleitkomma-Typen.

Details zu numerischen Daten, Mantisse und Exponent, Standard IEEE-754
#ifdef __GNUC__
printf("INT: %d\n",__SIZEOF_INT__);
printf("LONG: %d\n",__SIZEOF_LONG__);
printf("LONGLONG: %d\n",__SIZEOF_LONG_LONG__);
printf("SHORT: %d\n",__SIZEOF_SHORT__);
printf("FLOAT: %d\n",__SIZEOF_FLOAT__);
printf("DOUBLE: %d\n",__SIZEOF_DOUBLE__);
printf("LONGDOUBLE: %d\n",__SIZEOF_LONG_DOUBLE__);
printf("POINTER: %d \n",__SIZEOF_POINTER__);
#endif

Letzte Änderung dieser Seite: 2012-04-30 13:08:52