Использование '__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 нет.