guest
guest

Reputation: 435

Best practice when referring to a program's name in C

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?

Upvotes: 8

Views: 7903

Answers (8)

Ale
Ale

Reputation: 997

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;
}

Upvotes: 0

MJB
MJB

Reputation: 7686

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.

Upvotes: 5

jkramer
jkramer

Reputation: 15768

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.

Upvotes: 1

Steve Jessop
Steve Jessop

Reputation: 279385

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);

Upvotes: 2

ShinTakezou
ShinTakezou

Reputation: 9681

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)

Upvotes: 1

user347594
user347594

Reputation: 1296

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.

Upvotes: 5

Jaymz
Jaymz

Reputation: 6348

Depends whether argv is in scope or not...

Upvotes: 0

OscarRyz
OscarRyz

Reputation: 199324

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();
}

Upvotes: 0

Related Questions