Использование 'progname' вместо argv[0]
в среде C / Unix, в которой я работаю, я вижу, что некоторые разработчики используют __progname вместо argv[0] для сообщений usage (). Есть ли в этом какое-то преимущество? В чем разница между __progname и argv[0]. Он портативный?
7 ответов
__progname
не стандартный и поэтому не портативный, предпочитают argv[0]
. Я полагаю __progname
может искать строковый ресурс, чтобы получить имя, которое не зависит от имени файла, который вы запустили. Но!--1--> даст вам имя они на самом деле запустил его, как я нашел бы более полезным.
используя __progname
позволяет изменять содержимое argv[]
массив сохраняя при этом имя программы. Некоторые из распространенных инструментов, таких как getopt()
изменить argv[]
по мере обработки аргументов.
для переносимости, вы можете strcopy argv[0]
на свой progname
буфер при запуске программы.
для этого также есть расширение 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]
в main, а затем снимите имена каталогов самостоятельно. Мы добавили эти расширения, чтобы можно было писать автономные подпрограммы отчетов об ошибках, которые не требуют явного сотрудничества от main."
Я вижу по крайней мере две потенциальные проблемы с argv[0].
во-первых, argv[0] или сам argv может быть нулевым, если вызывающий execve() был злым или достаточно небрежным. Вызов execve ("foobar", NULL, NULL) обычно является простым и интересным способом доказать уверенному программисту, что его код не является sig11-proof.
следует также отметить, что argv не будет определен вне main (), в то время как _ _ progname обычно определяется как глобальная переменная, которую вы можете использовать из своей функции usage () или даже до вызова main () (например, нестандартных конструкторов GCC).
__progname - это просто argv[0], и примеры в других ответах здесь показывают недостатки его использования. Хотя и не портативный, я использую readlink on/proc/self /exe (Linux, Android) и читаю содержимое/proc/self / exefile (QNX).
Если ваша программа была запущена с использованием, например, символической ссылки, argv[0] будет содержать имя этой ссылки.
Я предполагаю, что _ _ progname будет содержать имя фактического файла программы.
в любом случае argv[0] определяется стандартом C. __progname нет.