これは、環境への単なるポインターであり、
extern char **environ;
どちらもバージョン 7 以降の UNIX で使用できます (バージョン 6 には環境変数がありませんでした)。名前が標準化extern
されました。environ
dont の 3 番目の引数main
。main
ある種のファッション ステートメントを除いて、3 引数を使用する理由はありません。
呼び出すプロセス セットアップ コードは、main
main が 3 つの引数を予期するかどうかを知る必要はありません。アセンブリ レベルでは、2 つの引数を受け取る関数と 3 つの引数を受け取るが 3 つ目の引数を使用しない関数の間に違いはないからです。または、引数を取らない関数と 2 つの引数を取り、それらを使用しない関数の間でも機能しますint main(void)
。
Unix に似ていない ABI を使用するシステムでは、どの種類の ABI をmain
呼び出しているかを知る必要がある場合があります。
これを 1 つのファイルに入れます。
#include <stdio.h>
int foo(int argc, char **argv)
{
int i;
for(i=0;i<argc;++i)
puts(argv[i]);
return 0;
}
そして、これは別のものです:
extern int foo(int argc, char **argv, char **envp);
int main(int argc, char **argv)
{
char *foo_args[] = { "foo", "arg", "another arg" };
char *foo_env[] = { "VAR=val", "VAR2=val2" };
foo(3, foo_args, foo_env);
return 0;
}
これは、クロスプラットフォームの言語弁護士の観点からは完全に間違っています。の型についてコンパイラに嘘をつき、foo
必要以上の引数を渡しました。しかし、UNIXでは機能します。余分な引数は、関数が戻った後に呼び出し元によって適切に考慮されてクリーンアップされるスタック上のスロットを無害に占有するか、呼び出し先が特に何も見つけることを期待していないレジスタに一時的に存在し、呼び出し元が呼び出し先が上書きすることを期待しているため、呼び出し先でレジスタが別の目的で再利用されてもかまいません。
これはまさに、envp
引数が 2 つの main を持つ通常の C プログラムで起こることです。argc
と をargv
使用したプログラムで何が起こるかint main(void)
。
しかし、envp
それ自体と同様に、これを本格的なコードで利用する正当な理由はありません。型チェックはあなたにとって良いことであり、それを回避できることを知っていることは、そうすべきではないことを知っていることと一緒に行くべきです。