在 C 中引用程序名称时的最佳实践

发布于 2024-09-05 17:12:39 字数 350 浏览 5 评论 0原文

提及程序名称时,什么被认为是最佳实践?我已经看到:

#define PROGRAM_NAME "myprog"
printf("this is %s\n", PROGRAM_NAME);

以及:

printf("this is %s\n", argv[0]);

我知道,当程序不是从 $ 调用时,第二种方法会给我 ./myprog 而不是 myprog PATH 并且第一种方法将保证程序名称的一致性。

但是还有什么其他因素可以使一种方法优于另一种方法吗?

What is considered best practice when referring to a program's name? I've seen:

#define PROGRAM_NAME "myprog"
printf("this is %s\n", PROGRAM_NAME);

as well as:

printf("this is %s\n", argv[0]);

I know, that the second approach will give me ./myprog rather than myprog when the program is not called from $PATH and that the first approach will guarantee consistence regarding the program's name.

But is there anything else, that makes one approach superior to the other?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

凉宸 2024-09-12 17:12:39

当您有多个链接时,第二种方法更为优越。在 *nix 系统中,有时行为取决于您如何调用程序。因此,对程序名称进行硬编码显然是一个问题——它永远无法检查这一点。

The second approach is superior when you have multiple links. In *nix systems, sometimes behavior depends on how you call a program. So hard coding the program name would clearly be a problem -- it could never check that.

随波逐流 2024-09-12 17:12:39

我试图两全其美:

char const * program_name;

int main(int argc, char **argv) {
   program_name = argv[0];
   //...
}

如果您需要program_name在其他文件中可用,您可以这样声明它:

extern char const * program_name;

我声明“char const *”,因为我希望它是一个指向const数据的指针。我不确定这部分我是否做对了。

I tried to take the best of both worlds:

char const * program_name;

int main(int argc, char **argv) {
   program_name = argv[0];
   //...
}

If you need program_name to be available in some other file you can declare it like this:

extern char const * program_name;

I declare "char const *" because I want it to be a pointer which points to const data. I'm not sure if I did right this part.

泼猴你往哪里跑 2024-09-12 17:12:39

如果可能的话,我通常使用 argv[0]basename(argv[0]) 。从用户的角度来看,我认为如果他们重命名或硬链接一个可执行文件(或者其他人为他们这样做),那么他们希望来自它的消息出现在他们正在使用的名称下,而不是编译为的其他名称下,他们可能知道也可能不知道。

同样,如果您将来发现要使用不同的选项以不同的名称编译程序,以提供不同的版本,您是否要在该 #define#ifndef > 并确保它是通过编译器命令行定义的:-DPROGRAM_NAME=myprog_demo,或者您只是想这样做并且它可以工作吗?

例外情况可能是,如果您的使用说明是从联机帮助页或其他文档中摘录的,那么您可能确实希望将程序名称硬连接到其中。但你可能也不会使用#define

不过,实现不需要提供 argv[0],因此为了获得最佳可移植实践,也可以处理这种情况。话又说回来,如果您的系统不提供它,那么用户实际上也可能不会在任何类型的终端上看到消息。

顺便一提:

#define PROGRAM_NAME "myprog"
puts("this is " PROGRAM_NAME);

I usually use argv[0], or basename(argv[0]) if possible. From the user's POV, I think if they rename or hardlink an executable (or somebody else does that for them), then they want messages from it to appear under the name they're using, not under some other name it was compiled as, that they may or may not know about.

Similarly if you discover in future that you want to compile your program under different names with different options, to give different versions, do you want to wrap an #ifndef around that #define and make sure that it's defined via the compiler command line: -DPROGRAM_NAME=myprog_demo, or do you just want to do it and it works?

The exception might be that if your usage instructions are an extract from a manpage or other documentation, then possibly you do want to hardwire the program name into that. But then you probably wouldn't use the #define either.

Implementations needn't provide argv[0], though, so for best portable practices handle that case too. Then again, if your system doesn't provide it then probably the user isn't actually going to see messages on any kind of terminal, either.

By the way:

#define PROGRAM_NAME "myprog"
puts("this is " PROGRAM_NAME);
仅冇旳回忆 2024-09-12 17:12:39

如果您以这种方式执行,第二种方法还可以为您提供像 /usr/bin/myprog 这样的字符串; basename 应该给出可执行文件的名称(您可以将其视为程序的名称)...除非它是符号链接的...(在这种情况下,您有链接的名称...可以使用在程序行为中进行某种选择)。

第一种方法将程序名称“固定”为程序员想要的,无论用户如何重命名可执行文件或符号链接(甚至硬链接)

The second approach could give you also strings like /usr/bin/myprog if you executed it that way; basename should give the name of the executable (that you could think of as the name of your program)... unless it is symlinked... (in that case, you have the name of the link... that could be used to do choices of some kind in the program behaviour).

The first approach "fixes" the program name to what the programmer wanted, no matter how the user renamed the executable file or symlinked (or even hardlinked)

西瓜 2024-09-12 17:12:39

它并不能完全回答您有关编程最佳实践的问题,但我认为您还应该记住什么对用户来说是最好的。
我个人更喜欢使用 argv[0] 引用自身的程序,即我调用的命令,而不是编码器在程序中硬编码的一些随机名称。一些硬编码名称很烦人或至少没有帮助的示例:

  • 我创建了一个指向程序的链接,
  • 由于某种原因我重命名了二进制文件,
  • 我的 $ 中的不同目录中有多个具有相同基本名称的可执行文件PATH
  • 程序给我关于调用它的其他方法的提示,例如在“使用”消息中

我更喜欢硬编码程序名称的唯一情况是当我使用 GUI 应用程序时。我不想看到“~/foo/bar.pl”作为窗口标题。

It doesn't exactly answer your question for programming best practices, but I think you should also keep in mind what's best for the user.
I personally prefer programs refering to themselves using argv[0], i.e. the command I was calling, and not some random name that the coder hardcoded in the program. A few examples where a hardcoded name is annoying or at least not helpful:

  • I've created a link to a program
  • I've renamed the binary for some reason
  • I have multiple executables with the same basenames in different directories in my $PATH
  • A program gives me hints about other ways to call it, e.g. in "usage" messages

The only situation where I'd prefer a hardcoded program name is when I'm using GUI applications. I wouldn't want to see "~/foo/bar.pl" as a window title.

街道布景 2024-09-12 17:12:39

当您手头没有 argv 时,前者优于后者。

#define PROGRAM_NAME "myprog"

void salute()
{
     // no argv available 

     printf("Hello from %s\n", PROGRAM_NAME );
}

void main( int argc, char** argv ) 
{
     salute();
}

The former is superior to the later when your don't have argv at hand.

#define PROGRAM_NAME "myprog"

void salute()
{
     // no argv available 

     printf("Hello from %s\n", PROGRAM_NAME );
}

void main( int argc, char** argv ) 
{
     salute();
}
尬尬 2024-09-12 17:12:39

取决于 argv 是否在范围内...

Depends whether argv is in scope or not...

叶落知秋 2024-09-12 17:12:39

正确使用全局变量是没有问题的。可能比#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;
}

Global variables are fine when they are used correctly. Probably better then #define, as, at least, you can easily inspect them when debugging.

basename, however, rises some doubts to me.

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文