C erhält die Hauptargumente aus der Funktion. Hauptfunktionsargumente. Verwenden von Befehlszeilenargumenten
Manchmal ist es beim Starten eines Programms nützlich, ihm einige Informationen zu übergeben. Normalerweise werden diese Informationen über Befehlszeilenargumente an main() übergeben. Befehlszeilenargument sind Informationen, die in der Befehlszeile des Betriebssystems nach dem Programmnamen eingegeben werden. Um beispielsweise mit dem Kompilieren eines Programms zu beginnen, müssen Sie nach der Eingabeaufforderung in der Befehlszeile etwa Folgendes eingeben:
CC Programmname
Programmname ist ein Befehlszeilenargument; es gibt den Namen des Programms an, das Sie kompilieren möchten.
Um Befehlszeilenargumente zu akzeptieren, werden zwei spezielle integrierte Argumente verwendet: argc und argv. Der argc-Parameter enthält die Anzahl der Argumente in der Befehlszeile und ist eine Ganzzahl, und er ist immer mindestens 1, da das erste Argument der Name des Programms ist. Und der Parameter argv ist ein Zeiger auf ein Array von Zeigern auf Zeichenfolgen. In diesem Array zeigt jedes Element auf ein Befehlszeilenargument. Alle Befehlszeilenargumente sind Strings, daher muss bei der Programmentwicklung für die Konvertierung beliebiger Zahlen in das gewünschte Binärformat gesorgt werden.
Hier ist ein einfaches Beispiel für die Verwendung eines Befehlszeilenarguments. Auf dem Bildschirm werden das Wort Hallo und Ihr Name angezeigt, der als Befehlszeilenargument angegeben werden muss.
#enthalten
Wenn Sie diesen Programmnamen (Name) aufgerufen haben und Ihr Name Tom ist, müssen Sie zum Ausführen des Programms den Namen Tom in die Befehlszeile eingeben. Als Ergebnis der Ausführung des Programms erscheint die Meldung Hallo, Tom auf dem Bildschirm.
In vielen Umgebungen müssen alle Befehlszeilenargumente durch ein Leerzeichen oder Tabulatorzeichen getrennt werden. Kommas, Semikolons und ähnliche Zeichen gelten nicht als Trennzeichen. Zum Beispiel,
Lauf Spot, lauf
besteht aus drei Zeichenfolgen, while
Eric, Rick, Fred
stellt eine einzelne Zeichenfolge dar – Kommas gelten in der Regel nicht als Trennzeichen.
Wenn eine Zeichenfolge Leerzeichen enthält, können Sie die Zeichenfolge in einigen Umgebungen in doppelte Anführungszeichen setzen, um zu verhindern, dass mehrere Argumente generiert werden. Infolgedessen wird die gesamte Zeichenfolge als ein Argument betrachtet. Um mehr darüber zu erfahren, wie Ihr Betriebssystem Befehlszeilenparameter festlegt, lesen Sie die Dokumentation Ihres Betriebssystems.
Es ist sehr wichtig, argv korrekt zu deklarieren. So wird es am häufigsten gemacht:
Char *argv;
Leere eckige Klammern zeigen an, dass das Array eine unbestimmte Länge hat. Auf einzelne Argumente kann jetzt durch Indizieren des argv-Arrays zugegriffen werden. argv zeigt beispielsweise auf die erste Zeichenfolge, die immer der Programmname ist; argv zeigt auf das erste Argument und so weiter.
Ein weiteres kleines Beispiel für die Verwendung von Befehlszeilenargumenten ist das folgende Programm: Countdown. Dieses Programm zählt rückwärts, beginnend mit einem Wert (in der Befehlszeile angegeben) und gibt einen Signalton aus, wenn er 0 erreicht. Beachten Sie, dass das erste Argument, das den Startwert enthält, mithilfe der Standardfunktion atoi () in einen ganzzahligen Wert konvertiert wird. Wenn das zweite Befehlszeilenargument (und wenn wir den Programmnamen als Argument betrachten, dann das dritte) die Zeile „display“ (display) ist, wird das Ergebnis der Zählung (in umgekehrter Reihenfolge) auf dem Bildschirm angezeigt.
/* Programm zum Zählen in umgekehrter Reihenfolge. */ #enthalten
Bitte beachten Sie, dass eine Fehlermeldung angezeigt wird, wenn keine Befehlszeilenargumente angegeben werden. Programme, die Befehlszeilenargumente akzeptieren, führen häufig Folgendes aus: Wenn der Benutzer diese Programme ausführt, ohne die erforderlichen Informationen einzugeben, werden Anweisungen zur korrekten Angabe der Argumente angezeigt.
Um auf ein einzelnes Zeichen eines der Befehlszeilenargumente zuzugreifen, geben Sie einen zweiten Index in argv ein. Das folgende Programm gibt beispielsweise zeichenweise alle Argumente aus, mit denen es aufgerufen wurde:
#enthalten Denken Sie daran, dass der erste Index von argv den Zugriff auf die Zeichenfolge und der zweite Index den Zugriff auf die einzelnen Zeichen ermöglicht. Normalerweise werden argc und argv verwendet, um dem Programm die ersten Befehle zu geben, die es beim Start benötigt. Befehlszeilenargumente geben beispielsweise häufig Informationen wie einen Dateinamen, eine Option oder ein alternatives Verhalten an. Die Verwendung von Befehlszeilenargumenten verleiht Ihrem Programm ein „professionelles Aussehen“ und erleichtert die Verwendung in Batchdateien. Die Namen argc und argv sind traditionell, aber nicht erforderlich. Sie können diese beiden Parameter in der Funktion main() beliebig aufrufen. Darüber hinaus unterstützen einige Compiler möglicherweise zusätzliche Argumente für main(). Überprüfen Sie daher unbedingt die Dokumentation Ihres Compilers. Wenn ein Programm keine Befehlszeilenparameter benötigt, ist es am häufigsten, die Funktion main() explizit so zu deklarieren, dass sie keine Parameter hat. In diesem Fall wird das Schlüsselwort void in der Parameterliste dieser Funktion verwendet. Stichworte: Befehlszeilenoptionen C ist eine kompilierte Sprache. Nach der Assemblierung ist das Programm eine ausführbare Datei (wir erwägen nicht die Erstellung dynamischer Bibliotheken, Treiber usw.). Unsere Programme sind sehr einfach und enthalten keine Laufzeitbibliotheken, sodass sie auf einen Computer mit demselben Betriebssystem (und ähnlicher Architektur) übertragen und dort ausgeführt werden können. Das Programm kann beim Start Parameter übernehmen. Sie sind Argumente für die Hauptfunktion. Die allgemeine Ansicht der Hauptfunktion ist wie folgt Void main(int argc, char **argv) ( ... ) Das erste Argument von argc ist die Anzahl der an die Funktion übergebenen Parameter. Das zweite Argument ist ein Array aus Strings – den Parametern selbst. Da die Parameter einer Funktion alles sein können, werden sie als Zeichenfolgen übergeben und das Programm selbst muss sie analysieren und in den gewünschten Typ konvertieren. Das erste Argument (argv) ist immer der Programmname. In diesem Fall wird der Name abhängig davon angezeigt, von wo aus das Programm gestartet wurde. #enthalten Lassen Sie uns nun lernen, ein wenig mit der Befehlszeile zu arbeiten. Dies wird benötigt, um Argumente an unser Programm zu übergeben. Die Tastenkombination Win+R öffnet das Fenster „Ausführen“. Geben Sie cmd ein und Sie öffnen die Befehlszeile. Sie können cmd.exe auch finden, indem Sie im Startmenü suchen. In Unix-ähnlichen Betriebssystemen können Sie das Terminalprogramm aufrufen. Wir werden nicht zu viele Befehle lernen. Nur diejenigen, die für die Arbeit benötigt werden. Der für alle Betriebssysteme standardmäßige Befehl cd navigiert zum gewünschten Ordner. Es gibt zwei reservierte Namen – . (Punkt) und.. (zwei Punkte). Der Punkt ist der Name des aktuellen Ordners. Geht nirgendwo hin Zugriff auf den übergeordneten Ordner Gehen Sie zum übergeordneten Ordner Um zur gewünschten zu gelangen, geben Sie die CD-Adresse ein. Beispielsweise müssen Sie in Windows zum Ordner C:\Windows\System32 wechseln Cd C:\Windows\System32 Unter Linux gehen Sie bei Bedarf zum Ordner /var/mysql Cd /var/mysql Wenn der Pfad Leerzeichen enthält, wird er in doppelte Anführungszeichen geschrieben Cd „D:\Dokumente und Einstellungen\Prolog“ Das Terminal verfügt über die folgenden nützlichen Funktionen: Wenn Sie den Aufwärtspfeil drücken, wird der zuvor ausgeführte Befehl angezeigt. Wenn Sie die Tabulatortaste drücken, versucht das Terminal, die Zeile mit einem ihm bekannten Befehl zu vervollständigen oder den Pfad zu vervollständigen, indem es alle Ordner und Dateien im aktuellen Ordner durchläuft. Ein weiterer wichtiger Befehl, dir unter Windows und ls unter Linux, zeigt den Inhalt des aktuellen Ordners (des Ordners, in dem Sie sich gerade befinden) in der Konsole an. Ihr Programm hat seinen vollständigen Namen zurückgegeben. Gehen Sie zu dem Ordner, in dem sich Ihr Programm befindet, und sehen Sie sich dessen Inhalt an Nachdem wir nun zu unserem Ordner navigiert sind, können wir unser Programm ausführen. Geben Sie dazu ihren Namen ein. Beachten Sie, dass sich der Name geändert hat. Da das Programm aus einem eigenen Ordner aufgerufen wird, wird der relative Name angezeigt. Jetzt ändern wir das Programm und lassen es alle Argumente ausgeben. die ihr geschenkt wurden. #enthalten Stellen Sie das Projekt zusammen. Stellen Sie vor dem Zusammenbau sicher, dass das Programm geschlossen ist. Rufen Sie nun das Programm auf und übergeben Sie ihm verschiedene Argumente. Schreiben Sie dazu den Namen des Programms und die durch ein Leerzeichen getrennten Argumente Schreiben wir nun ein Programm, das zwei Zahlenargumente akzeptiert und deren Summe ausgibt #enthalten Lasst uns abholen und anrufen So funktionieren die meisten Programme. Durch Klicken auf eine Verknüpfung rufen Sie das Programm auf, auf das sie verweist. Die meisten Programme akzeptieren auch verschiedene Argumente. Sie können beispielsweise den Firefox-Browser über die Befehlszeile aufrufen und die Argumente übergeben Viele Standardbefehle verfügen auch über Parameter. In Windows ist es üblich, dass sie mit einem Schrägstrich beginnen, in Unix mit einem Minus oder zwei Minuszeichen. Zum Beispiel Zeigt nur Ordner an, jedoch im Linux-Terminal Ls -l listet alle Dateien und Ordner mit Attributen auf Um zusätzliche Windows-Befehle anzuzeigen, geben Sie „help“ in die Befehlszeile ein oder lesen Sie im Handbuch nach (es ist leicht im Internet zu finden). Für Linux gibt es viel mehr Befehle und ihre Optionen, und einige davon sind unabhängige Programmiersprachen, daher lohnt es sich, zumindest den Mindestsatz und ihre Optionen zu lernen. Borland C++ unterstützt drei Argumente für main(). Die ersten beiden sind das traditionelle argc und argv. Dies sind die einzigen durch den ANSI-C-Standard definierten Argumente für main(). Sie ermöglichen die Übergabe von Befehlszeilenargumenten an das Programm. Befehlszeilenargumente sind die Informationen, die dem Programmnamen in der Befehlszeile des Betriebssystems folgen. Wenn ein Programm beispielsweise mit dem Borland-Zeilencompiler kompiliert wird, wird es normalerweise als bcc eingegeben Programmname Wo Programmname ist ein Programm, das kompiliert werden muss. Der Programmname wird als Argument an den Compiler übergeben. Der Parameter argc enthält die Anzahl der Befehlszeilenargumente und ist eine Ganzzahl. Es ist immer mindestens 1, da der Programmname als erstes Argument gilt. Der argv-Parameter ist ein Zeiger auf ein Array von Zeichenzeigern. Jedes Element dieses Arrays zeigt auf ein Befehlszeilenargument. Alle Befehlszeilenargumente sind Zeichenfolgen. Alle Zahlen werden vom Programm in das interne Format umgewandelt. Das folgende Programm gibt „Hallo“ gefolgt vom Benutzernamen aus, wenn es direkt nach dem Programmnamen eingegeben wird: #enthalten Wenn Sie diesen Programmnamen nennen und der Benutzername Sergey ist, müssen Sie zum Starten des Programms Folgendes eingeben: Befehlszeilenargumente müssen durch Leerzeichen oder Tabulatoren getrennt werden. Kommas, Semikolons und ähnliche Zeichen gelten nicht als Trennzeichen. Zum Beispiel: Besteht aus drei Zeilen, während Herb, Rick, Fred Dies ist eine Zeile – Kommas sind keine Trennzeichen. Wenn Sie eine Zeichenfolge mit Leerzeichen oder Tabulatoren als einzelnes Argument übergeben müssen, müssen Sie diese in doppelte Anführungszeichen setzen. Dies ist zum Beispiel ein Argument: "das ist ein Test" Es ist wichtig, argv korrekt zu deklarieren. Die typischste Methode ist: Leere Klammern zeigen an, dass das Array keine feste Länge hat. Sie können mithilfe der argv-Indizierung auf einzelne Elemente zugreifen. argv zeigt beispielsweise auf die erste Zeile, die immer den Programmnamen enthält. argv zeigt auf die nächste Zeile und so weiter. Nachfolgend finden Sie ein kleines Beispiel für die Verwendung von Befehlszeilenargumenten. Es zählt ab dem in der Befehlszeile angegebenen Wert herunter und gibt ein Signal aus, wenn dieser Null erreicht. Beachten Sie, dass das erste Argument eine Zahl enthält, die mithilfe der Standardfunktion atoi() in eine Ganzzahl umgewandelt wurde. Wenn als zweites Argument die Zeichenfolge „display“ vorhanden ist, wird der Zähler selbst auf dem Bildschirm angezeigt. /* Zählprogramm */ #enthalten Bitte beachten Sie, dass eine Fehlermeldung erscheint, wenn keine Argumente angegeben werden. Dies ist am typischsten für Programme, die Befehlszeilenargumente verwenden, um Anweisungen auszugeben, wenn versucht wurde, das Programm ohne die richtigen Informationen auszuführen. Um auf einzelne Befehlszeilenzeichen zuzugreifen, fügen Sie argv einen zweiten Index hinzu. Das folgende Programm gibt beispielsweise alle Argumente, mit denen es aufgerufen wurde, zeichenweise aus: #enthalten Wir müssen bedenken, dass der erste Index für den Zugriff auf eine Zeichenfolge und der zweite für den Zugriff auf ein Zeichen in einer Zeichenfolge dient. Normalerweise werden argc und argv verwendet, um Quellbefehle abzurufen. Theoretisch sind bis zu 32767 Argumente möglich, aber die meisten Betriebssysteme erlauben nicht einmal annähernd diese Zahl. Normalerweise werden diese Argumente verwendet, um einen Dateinamen oder Optionen anzugeben. Die Verwendung von Befehlszeilenargumenten verleiht dem Programm ein professionelles Aussehen und ermöglicht die Verwendung des Programms in Batchdateien. Wenn Sie die mit Borland C++ gelieferte Datei WILDARGS.OBJ einbinden, können Sie Vorlagen in Argumenten vom Typ *.EXE verwenden. (Borland C++ verarbeitet Platzhalter automatisch und erhöht argc entsprechend.) Wenn Sie beispielsweise WILDARGS.OBJ mit dem folgenden Programm verbinden, erfahren Sie, wie viele Dateien mit dem in der Befehlszeile angegebenen Dateinamen übereinstimmen: /* Dieses Programm mit WILDARGS.OBJ verknüpfen */ #enthalten Wenn wir dieses Programm WA nennen und es dann wie folgt ausführen, erhalten wir die Anzahl der Dateien mit der Erweiterung EXE und eine Liste der Namen dieser Dateien: Zusätzlich zu argc und argv bietet Borland C++ auch ein drittes Befehlszeilenargument –env. Der env-Parameter ermöglicht einem Programm den Zugriff auf Informationen über die Betriebssystemumgebung. Der Parameter env muss auf argc und argv folgen und wird wie folgt deklariert: Wie Sie sehen, wird env auf die gleiche Weise wie argv deklariert. Genau wie argv ist es ein Zeiger auf ein Array von Strings. Jede Zeile ist eine vom Betriebssystem definierte Umgebungszeichenfolge. Der env-Parameter hat keinen entsprechenden argc-Parameter, der angibt, wie viele Umgebungszeilen vorhanden sind. Stattdessen ist die letzte Zeile der Umgebung null. Das folgende Programm druckt alle derzeit im Betriebssystem definierten Umgebungszeichenfolgen: /* Dieses Programm zeigt alle Umgebungszeilen an */ #enthalten Bitte beachten Sie, dass argc und argv zwar nicht vom Programm verwendet werden, aber in der Parameterliste vorhanden sein müssen. C kennt die Parameternamen nicht. Stattdessen wird ihre Verwendung durch die Reihenfolge bestimmt, in der die Parameter deklariert werden. Tatsächlich können Sie den Parameter beliebig nennen. Da argc, argv und env traditionelle Namen sind, ist es am besten, sie weiterhin zu verwenden, damit jeder, der das Programm liest, sofort verstehen kann, dass es sich um Argumente für die Funktion main() handelt. Eine typische Aufgabe für Programme besteht darin, einen in einer Umgebungszeichenfolge definierten Wert nachzuschlagen. Beispielsweise ermöglicht der Inhalt der PATH-Zeile Programmen die Verwendung von Suchpfaden. Das folgende Programm zeigt, wie Sie Zeichenfolgen finden, die Standardsuchpfade deklarieren. Es verwendet die Standardbibliotheksfunktion strstr(), die den folgenden Prototyp hat: Char *strstr(const char *str1, const char *str2); Die Funktion strstr() sucht in der Zeichenfolge, auf die str2 zeigt, nach der Zeichenfolge, auf die str1 zeigt. Wird ein solcher String gefunden, wird ein Zeiger auf die erste Position zurückgegeben. Wenn keine Übereinstimmungen gefunden werden, gibt die Funktion NULL zurück. /* Das Programm sucht in den Umgebungszeichenfolgen nach einer Zeile mit PATH */ #enthalten Es kommt vor, dass Daten beim Aufruf von der Kommandozeile an ein Programm übertragen werden. Solche Daten werden Befehlszeilenargumente genannt. Das sieht zum Beispiel so aus: ./a.out test.txt ls -lt /home/peter/ Hier werden die Programme a.out (aus dem aktuellen Verzeichnis) und ls (aus demselben Verzeichnis, das in der Umgebungsvariablen PATH angegeben ist) aufgerufen. Das erste Programm empfängt von der Befehlszeile ein Wort – test.txt, das zweite – zwei: -lt und /home/peter/. Wenn das Programm in C geschrieben ist, wird die Steuerung beim Start sofort an die Funktion main() übergeben. Daher ist es die Funktion, die die Befehlszeilenargumente empfängt, die ihren Parametervariablen zugewiesen sind. Zuvor haben wir die Funktion main() so definiert, als ob sie keine Parameter akzeptiert und nichts zurückgibt. Tatsächlich gibt in der Sprache C jede Funktion standardmäßig (sofern nichts anderes definiert ist) eine Ganzzahl zurück. Da können Sie sicher sein. Wenn Sie den Code so schreiben: main() ( printf ("Hallo \N"); return 0 ; ) Dann tritt beim Kompilieren keine Warnung oder kein Fehler auf. Das Gleiche passiert, wenn Sie int main() schreiben. Dies beweist, dass die Funktion standardmäßig eine Ganzzahl und nicht nichts (void) zurückgibt. Obwohl das, was eine Funktion zurückgibt, immer „überschrieben“ werden kann, zum Beispiel voidmain() oder float main() . Beim Aufruf eines Programms über die Befehlszeile wird ihm immer das folgende Datenpaar übergeben: Bedenken Sie, dass auch der Programmname selbst zählt. Wenn der Anruf beispielsweise so aussieht: ./a.out 12 Thema 2 Dann hat das erste Argument des Programms den Wert 4 und das String-Array ist definiert als („./a.out“, „12“, „theme“, „2“). Beachten Sie die Terminologie: Es gibt nur zwei Programmargumente (eine Zahl und ein Array), aber beliebig viele Befehlszeilenargumente. Befehlszeilenargumente werden in Programmargumente (in main()-Funktionsargumente) „umgewandelt“. Nur weil Daten an das Programm übergeben werden, bedeutet das nicht, dass die Funktion main() diese akzeptieren muss. Wenn die Funktion main() ohne Parameter definiert ist, ist der Zugriff auf die Befehlszeilenargumente nicht möglich. Obwohl Sie nichts daran hindert, sie zu übertragen. Es wird kein Fehler auftreten. Um auf die an das Programm übergebenen Daten zugreifen zu können, müssen diese Variablen zugewiesen werden. Da die Argumente sofort an main() übergeben werden, sollte der Header wie folgt aussehen: Die erste Variable (n) enthält die Anzahl der Wörter und die zweite Variable enthält einen Zeiger auf ein Array von Zeichenfolgen. Oft wird der zweite Parameter als **arr geschrieben. Es ist jedoch dasselbe. Denken Sie daran, dass das String-Array selbst Zeiger auf Strings als seine Elemente enthält. Und wir übergeben der Funktion einen Zeiger auf das erste Element des Arrays. Es stellt sich heraus, dass wir einen Zeiger auf einen Zeiger übergeben, d.h. **arr. Übung #enthalten Es zeigt beim Aufruf die Anzahl der Wörter in der Befehlszeile und jedes Wort in einer neuen Zeile an. Rufen Sie es ohne Befehlszeilenargumente und mit Argumenten auf. Im Programm haben wir die Parametervariablen argc und argv verwendet. Es ist üblich, diese Namen zu verwenden, aber tatsächlich können sie alles sein. Halten Sie sich besser an diesen Standard, damit Ihre Programme nicht nur für Sie, sondern auch für andere Programmierer besser verständlich sind. Wenn Sie Erfahrung mit der GNU/Linux-Befehlszeile haben, wissen Sie, dass die meisten Befehle Schalter und Argumente haben. Wenn Sie beispielsweise den Inhalt von Verzeichnissen anzeigen, kopieren oder verschieben, werden die Dateisystemobjekte, für die der Befehl ausgeführt wird, als Argumente angegeben. Die Merkmale seiner Implementierung werden anhand von Schlüsseln bestimmt. Zum Beispiel im Team Cp -r ../les_1 ../les_101 cp ist der Befehlsname, -r ist der Schalter und ../les_1 und ../les_101 sind die Befehlsargumente. Im Allgemeinen werden Dateiadressen und „Modifikatoren“ (das sind Schlüssel) des Programmausführungsprozesses meistens beim Start an Programme übertragen. Schreiben wir ein Programm, das vom Benutzer in der Befehlszeile angegebene Dateien zum Schreiben oder Hinzufügen öffnet und dort die gleichen Informationen schreibt (hinzufügt), die der Benutzer während der Programmausführung über die Tastatur eingibt: #enthalten Erläuterungen zum Code: Eines Tages interessierte ich mich für den Inhalt des Stacks der Hauptfunktion eines Prozesses in Linux. Ich habe ein wenig recherchiert und präsentiere euch nun das Ergebnis. Möglichkeiten zur Beschreibung der Hauptfunktion: Argc – Anzahl der Parameter Die Größe des Stack-Segments finden Sie in der Maps-Datei: Bevor der Loader die Steuerung an main überträgt, initialisiert er den Inhalt der Arrays mit Befehlszeilenparametern, Umgebungsvariablen und Hilfsvektoren. Ich habe nicht nach 32 Bit gesucht, aber höchstwahrscheinlich reicht es aus, die Größen einfach durch zwei zu teilen. 1. Der Zugriff auf Adressen über dem obersten Punkt führt zu einem Segfault. Hilfsvektor Zweite Möglichkeit, den Inhalt eines Vektors abzurufen: Die am besten lesbare Darstellung wird durch Festlegen der Umgebungsvariablen LD_SHOW_AUXV erreicht. LD_SHOW_AUXV=1 ls Rückkehr von main() Ich hoffe, es war interessant. Vielen Dank an Benutzer Xeor für den nützlichen Tipp.Befehlszeilenoptionen
Geben Sie cd C:\ ein.
Drücken Sie die Tabulatortaste und sehen Sie, was passiert.
firefox.exe „www.mozilla.org“ „site“ und öffnet sofort die Websites an den angegebenen Adressen in zwei Registerkarten.
{
if(argc!=2)
{
printf("Sie haben vergessen, Ihren Namen einzugeben\n");
Rückgabe 1;
}
printf("Hallo %s", argv);
0 zurückgeben;
}
Name Sergej.
Als Ergebnis des Programms erscheint Folgendes:
„Hallo Sergey.“
#enthalten
#enthalten
int main(int argc, char *argv)
{
int disp, count;
if(argc<2)
{
printf("Sie müssen die Länge der Zählung eingeben\n");
printf("in der Befehlszeile. Versuchen Sie es erneut.\n");
Rückgabe 1;
}
if (argc==3 && !strcmp(argv,"display")) disp = 1;
sonst disp = 0;
for(count=atoi(argv); count; -count)
if (disp) printf("%d ", count);
printf("%c", "\a"); /* auf den meisten Computern ist dies ein Anruf */
0 zurückgeben;
}
int main(int argc, char *argv)
{
int t, i;
for(t=0; t
ich = 0;
while(argv[t][i])
{
printf("%c", argv[t][i]);
}
printf(" ");
}
0 zurückgeben;
}
int main(int argc, char *argv)
{
registrieren int i;
printf("%d Dateien stimmen mit dem angegebenen Namen überein\n", argc-1);
printf("Sie sind: ");
for(i=1; i
0 zurückgeben;
}
int main(int argc, char *argv, char *env)
{
int t;
for(t=0; env[t]/ t++)
printf("%s\n", env[t]);
0 zurückgeben;
}
#enthalten
int main (int argc, char *argv, char *env)
{
int t;
for(t=0; env[t]; t++)
{
if(strstr(env[t], "PATH"))
printf("%s\n", env[t]);
}
0 zurückgeben;
}
Diese Daten (Nummer und Zeiger) werden dem Programm auch dann übergeben, wenn es einfach namentlich aufgerufen wird, ohne ihm etwas zu übergeben: ./a.out. In diesem Fall hat das erste Argument den Wert 1 und das zweite zeigt auf ein Array, das nur aus einer Zeile besteht („"./a.out").
main (int n, char *arr)
Schreiben Sie ein Programm wie dieses:Die praktische Bedeutung der Datenübertragung an das Programm
1. int main()
2. int main(int argc, char **argv)
3. int main(int argc, char **argv, char **env)
4. int main(int argc, char **argv, char **env, ElfW(auxv_t) auxv)
5. int main(int argc, char **argv, char **env, char **apple)
argv – Nullterminal-Array von Zeigern auf Bef
env ist ein Nullterminal-Array von Zeigern auf Zeichenfolgen von Umgebungsvariablen. Jede Zeile im Format NAME=VALUE
auxv – Array von Hilfswerten (nur für PowerPC verfügbar)
apple – Pfad zur ausführbaren Datei (unter MacOS und Darwin)
Ein Hilfsvektor ist ein Array mit verschiedenen Zusatzinformationen, wie z. B. der effektiven Benutzerkennung, dem Setuid-Bit-Attribut, der Speicherseitengröße usw.
cat /proc/10918/maps
…
7ffffffa3000-7ffffffff000 rw-p 00000000 00:00 0
…
Nach der Initialisierung sieht die Oberseite des Stapels für die 64-Bit-Version in etwa so aus.
Seniorenadresse oben.1.
0x7ffffffff000
Der oberste Punkt des Stapelsegments. Der Aufruf verursacht einen Segfault
0x7ffffffff0f8
NULL
Leere*
8
0x00"
2.
Dateiname
verkohlen
1+
„/tmp/a.out“
verkohlen
1
0x00
...
env
verkohlen
1
0x00
...
verkohlen
1
0x00
3.
0x7fffffffe5e0
env
verkohlen
1
..
verkohlen
1
0x00
...
argv
verkohlen
1
0x00
...
verkohlen
1
0x00
4.
0x7fffffffe5be
argv
verkohlen
1+
„/tmp/a.out“
5.
Array mit zufälliger Länge
6.
Daten für Auxv
Leere*
48"
AT_NULL
Elf64_auxv_t
16
{0,0}
...
auxv
Elf64_auxv_t
16
7.
auxv
Elf64_auxv_t
16
Bsp.: (0x0e,0x3e8)
NULL
Leere*
8
0x00
...
env
verkohlen*
8
8.
0x7fffffffe308
env
verkohlen*
8
0x7fffffffe5e0
NULL
Leere*
8
0x00
...
argv
verkohlen*
8
9.
0x7fffffffe2f8
argv
verkohlen*
8
0x7fffffffe5be
10.
0x7fffffffe2f0
argc
lange int
8"
Anzahl der Argumente + 1
11.
Lokale Variablen und Argumente von Funktionen, die vor main aufgerufen werden
12.
Lokale Variablen main
13.
0x7fffffffe1fc
argc
int
4
Anzahl der Argumente + 1
0x7fffffffe1f0
argv
verkohlen**
8
0x7fffffffe2f8
0x7fffffffe1e8
env
verkohlen**
8
0x7fffffffe308
14.
Lokale Funktionsvariablen
" - Ich habe in den Dokumenten keine Beschreibungen der Felder gefunden, aber sie sind im Dump deutlich sichtbar.
2. Eine Zeichenfolge, die den Pfad zur ausführbaren Datei enthält.
3. Array von Strings mit Umgebungsvariablen
4. Array von Strings mit Befehlszeilenparametern
5. Array zufälliger Länge. Seine Auswahl kann mit den Befehlen deaktiviert werden
sysctl -w kernel.randomize_va_space=0
echo 0 > /proc/sys/kernel/randomize_va_space
6. Daten für den Hilfsvektor (zum Beispiel die Zeichenfolge „x86_64“)
7. Hilfsvektor. Weitere Details weiter unten.
8. Nullterminal-Array von Zeigern auf Zeichenfolgen von Umgebungsvariablen
9. Nullterminal-Array von Zeigern auf Bef
10. Ein Maschinenwort, das die Anzahl der Befehlszeilenparameter enthält (eines der Argumente der „Hauptfunktionen“, siehe Abschnitt 11)
11. Lokale Variablen und Argumente von Funktionen, die vor main(_start,__libc_start_main..) aufgerufen werden
12. In main deklarierte Variablen
13.Argumente der Hauptfunktion
14. Variablen und Argumente lokaler Funktionen.
Für i386 und x86_64 ist es nicht möglich, die Adresse des ersten Elements des Hilfsvektors abzurufen, der Inhalt dieses Vektors kann jedoch auf andere Weise abgerufen werden. Eine davon besteht darin, auf den Speicherbereich direkt hinter dem Array von Zeigern auf Zeichenfolgen von Umgebungsvariablen zuzugreifen.
Es sollte ungefähr so aussehen:
#enthalten
Die Elf(32,64)_auxv_t-Strukturen werden in /usr/include/elf.h beschrieben. Funktionen zum Füllen von Strukturen in linux-kernel/fs/binfmt_elf.c
hexdump /proc/self/auxv
AT_HWCAP: bfebfbff //Prozessorfunktionen
AT_PAGESZ: 4096 //Speicherseitengröße
AT_CLKTCK: 100 //Häufigkeitszeiten aktualisieren()
AT_PHDR: 0x400040 //Header-Informationen
AT_PHENT: 56
AT_PHNUM: 9
AT_BASE: 0x7fd00b5bc000 // Interpreteradresse, also ld.so
AT_FLAGS: 0x0
AT_ENTRY: 0x402490 //Programmeinstiegspunkt
AT_UID: 1000 //Benutzer- und Gruppenkennungen
AT_EUID: 1000 //nominal und effektiv
AT_GID: 1000
AT_EGID: 1000
AT_SECURE: 0 //ob das Setuid-Flag gesetzt ist
AT_RANDOM: 0x7fff30bdc809 //Adresse von 16 Zufallsbytes,
beim Start generiert
AT_SYSINFO_EHDR: 0x7fff30bff000 //Zeiger auf die Seite, die für verwendet wird
//Systemaufrufe
AT_EXECFN: /bin/ls
AT_PLATFORM: x86_64
Links steht der Name der Variablen, rechts der Wert. Alle möglichen Variablennamen und deren Beschreibungen finden Sie in der Datei elf.h. (Konstanten mit AT_-Präfix)
Nachdem der Prozesskontext initialisiert wurde, wird die Steuerung nicht an main(), sondern an die Funktion _start() übergeben.
main() wurde bereits von __libc_start_main aufgerufen. Diese letzte Funktion hat eine interessante Funktion: Ihr wird ein Zeiger auf eine Funktion übergeben, die nach main() ausgeführt werden soll. Und dieser Zeiger wird auf natürliche Weise durch den Stapel weitergeleitet.
Im Allgemeinen sehen die Argumente für __libc_start_main gemäß der Datei glibc-2.11/sysdeps/ia64/elf/start.S so aus
/*
* Argumente für __libc_start_main:
* out0: Haupt
* out1: argc
* out2: argv
* out3:init
* out4: fini //Funktion wird nach main aufgerufen
* out5: rtld_fini
* out6: stack_end
*/
Diese. Um die Adresse des Fini-Zeigers zu erhalten, müssen Sie zwei Maschinenwörter von der letzten lokalen Variablen main verschieben.
Folgendes ist passiert (die Funktionsfähigkeit hängt von der Compilerversion ab):
#enthalten
Viel Glück.