Использование '__progname' вместо argv [0]
В среде C/Unix, в которой я работаю, некоторые разработчики используют __progname вместо argv [0] для сообщений use(). Есть ли некоторые преимущества? Какая разница между __progname и argv [0]. Он переносится?
Ответы
Ответ 1
__progname
не является стандартным и, следовательно, не переносимым, предпочитайте argv[0]
. Я полагаю, что __progname
может искать строковый ресурс, чтобы получить имя, которое не зависит от имени файла, в котором вы его запускали. Но argv[0]
даст вам имя, которое они на самом деле запускали, как я нашел бы более полезным.
Ответ 2
Использование __progname
позволяет изменять содержимое массива argv[]
при сохранении имени программы. Некоторые из обычных инструментов, таких как getopt()
, изменяют argv[]
при обработке аргументов.
Для переносимости вы можете strcopy argv[0]
в свой собственный буфер progname
при запуске вашей программы.
Ответ 3
Для этого также существует расширение GNU, так что можно получить доступ к имени вызова программы извне main(), не сохраняя его вручную. Однако было бы лучше сделать это вручную; что делает его переносимым, а не поддержкой расширения GNU. Тем не менее, здесь я приведу выдержку из имеющейся документации.
Из онлайновое руководство библиотеки GNU C (доступно сегодня):
"Многие программы, которые не читают ввод с терминала, предназначены для выхода, если какой-либо системный вызов терпит неудачу. По соглашению, сообщение об ошибке из такой программы должно начинаться с имени программы, без каталогов. в переменной program_invocation_short_name
, полное имя файла хранится в переменной program_invocation_name
.
-
Переменная: char * program_invocation_name
Это значение переменной - это имя, которое использовалось для вызова программы, запущенной в текущем процессе. Это то же самое, что и argv[0]
. Обратите внимание, что это необязательно является полезным именем файла; часто он не содержит имен каталогов.
-
Переменная: char * program_invocation_short_name
Это значение переменной - это имя, которое было использовано для вызова программы, запущенной в текущем процессе, с удалением имен каталогов. (То есть, это то же самое, что и program_invocation_name
минус все до последней косой черты, если таковая имеется.)
Код инициализации библиотеки устанавливает обе эти переменные перед вызовом main.
Примечание по переносимости:. Эти две переменные являются расширениями GNU. Если вы хотите, чтобы ваша программа работала с библиотеками, отличными от GNU, вы должны сохранить значение argv[0]
в главном, а затем сами удалить имена каталогов. Мы добавили эти расширения, чтобы дать возможность писать автономные подпрограммы отчетности об ошибках, которые не требуют явного сотрудничества с основными ".
Ответ 4
Это BSDism, и определенно не переносимый.
Ответ 5
Я вижу по крайней мере две потенциальные проблемы с argv [0].
Во-первых, argv [0] или argv сам может быть NULL, если вызывающий (execve()) был злым или небрежным. Вызов execve ( "foobar", NULL, NULL) обычно является простым и интересным способом доказать над уверенным программистом, что его код не является доказательством sig11.
Следует также отметить, что argv не будет определяться вне main(), в то время как __progname обычно определяется как глобальная переменная, которую вы можете использовать из вашей функции usage() или даже до вызова main() (например, нестандартного GCC).
Ответ 6
__ progname - просто argv [0], а примеры в других ответах здесь показывают недостатки его использования. Хотя я и не переносимый, я использую readlink on/proc/self/exe (Linux, Android) и читаю содержимое /proc/self/exefile (QNX).
Ответ 7
Если ваша программа была запущена с использованием, например, символической ссылки, argv [0] будет содержать имя этой ссылки.
Я предполагаю, что __progname будет содержать имя фактического файла программы.
В любом случае argv [0] определяется стандартом C. __progname нет.