在提及程序名称时,什么被认为是最佳实践?我见过以下几种方式:
#define PROGRAM_NAME "myprog"
printf("this is %s\n", PROGRAM_NAME);
以及:
printf("this is %s\n", argv[0]);
我知道,第二种方法在程序没有从
$PATH
调用时会给我 ./myprog
而不是 myprog
,而第一种方法将保证程序名称的一致性。但是还有其他方面使一种方法优于另一种方法吗?
在提及程序名称时,什么被认为是最佳实践?我见过以下几种方式:
#define PROGRAM_NAME "myprog"
printf("this is %s\n", PROGRAM_NAME);
以及:
printf("this is %s\n", argv[0]);
$PATH
调用时会给我 ./myprog
而不是 myprog
,而第一种方法将保证程序名称的一致性。我试图兼顾两个方面的优点:
char const * program_name;
int main(int argc, char **argv) {
program_name = argv[0];
//...
}
如果您需要在其他文件中使用program_name,可以像这样声明它:
extern char const * program_name;
我声明“char const *”是因为我希望它成为指向常量数据的指针。我不确定这部分是否正确。
gcc
和g++
可能是相同的可执行文件,它会检查调用它的名称并相应地修改链接器选项。我记不清它是否真的是这样了。 - Steve Jessopargv[0]
,或者如果可能的话使用basename(argv[0])
。从用户的角度来看,如果他们重命名或硬链接可执行文件(或其他人为他们这样做),那么他们希望从中获得的消息出现在他们使用的名称下,而不是编译时使用的其他名称,他们可能知道也可能不知道。#define
周围包装一个#ifndef
,并确保它通过编译器命令行定义:-DPROGRAM_NAME=myprog_demo
,还是只是想做到这一点并且它可以工作?#define
。argv[0]
,因此为了最佳的可移植性实践,也要处理该情况。然而,如果您的系统没有提供它,那么用户实际上也不会在任何类型的终端上看到消息。#define PROGRAM_NAME "myprog"
puts("this is " PROGRAM_NAME);
basename
不是可移植的。它只被 POSIX(在 libgen.h 中)所需。此外,请记住它可能会修改您提供的字符串,并且返回的指针可能是原始指针的偏移量,或者是静态分配的字符串(因此不要尝试释放它给您的内容,并且不要立即尝试释放您提供的内容)。除非您100%确定了涉及的内存管理并且不关心可移植性,否则我建议避免使用它。 - mk12basename(argv[0])
本身就是一个有点可疑的表达式,它假设你不打算再次使用这些参数。 - Steve Jessop第二种方法也可以给你像/usr/bin/myprog
这样的字符串,如果你以这种方式执行它;basename应该给出可执行文件的名称(你可以认为是你的程序的名称)...除非它是符号链接...(在这种情况下,你有链接的名称...可以用来在程序行为中做出选择)。
第一种方法“修复”了程序名称,无论用户如何重命名可执行文件或符号链接(甚至硬链接)。
这并不完全回答你关于编程最佳实践的问题,但我认为你也应该考虑到对用户最有益的因素。
我个人喜欢程序使用 argv[0]
自称,即调用命令,而不是一些由程序员硬编码的随机名称。以下是一些例子,硬编码名称时会很烦人或至少没有帮助:
$PATH
中的不同目录中有多个相同基本名称的可执行文件我唯一想要看到硬编码程序名称的情况是当我使用 GUI 应用程序时。 我不希望将 "~/foo/bar.pl" 作为窗口标题。
如果你手头没有argv
,那么前者比后者更优秀。
#define PROGRAM_NAME "myprog"
void salute()
{
// no argv available
printf("Hello from %s\n", PROGRAM_NAME );
}
void main( int argc, char** argv )
{
salute();
}
argc
和 argv
的成本太高。 - guest这取决于argv
是否在作用域内...
全局变量在正确使用时是可以的。与#define
相比,它们可能更好,因为至少在调试时可以轻松检查它们。
然而,basename
让我有些疑虑。
static inline char *my_basename(char const *name) // neither GNU nor POSIX...
{
char *b = strrchr(name, '/');
if (b)
return b + 1;
return (char*)name;
}
/* ... */
char *program_name;
/* ... */
void salute()
{
// no argv available
printf("Hello from %s\n", program_name);
}
int main(int argc, char* argv[])
{
program_name = my_basename(argv[0]);
salute();
return 0;
}
const char *const PROGRAM_NAME = "myprog";
)。这样做可以确保该字符串只在内存中存储一次。 - mk12