When passing argument to main()
in a C or C++ application, will argv[0]
always be the name of the executable? Or is this just a common convention and not guaranteed to be true 100% of the time?

- 50,943
- 13
- 104
- 142

- 5,960
- 10
- 33
- 33
-
22On Unix, consider: `execl("/home/hacker/.hidden/malicious", "/bin/ls", "-s", (char *)0);`. The name of the executable bears no relation to the value in `argv[0]`. – Jonathan Leffler May 24 '11 at 13:59
-
In Windows if you call `CreateProcess` like this: `CreateProcess("a.exe", "/b", ...)`, then the `argv[0]` would be `/b`, not `a.exe`. – Andry Jul 01 '21 at 16:15
8 Answers
Guesswork (even educated guesswork) is fun but you really need to go to the standards documents to be sure. For example, ISO C11 states (my emphasis):
If the value of
argc
is greater than zero, the string pointed to byargv[0]
represents the program name;argv[0][0]
shall be the null character if the program name is not available from the host environment.
So no, it's only the program name if that name is available. And it "represents" the program name, not necessarily is the program name. The section before that states:
If the value of
argc
is greater than zero, the array membersargv[0]
throughargv[argc-1]
inclusive shall contain pointers to strings, which are given implementation-defined values by the host environment prior to program startup.
This is unchanged from C99, the previous standard, and means that even the values are not dictated by the standard - it's up to the implementation entirely.
This means that the program name can be empty if the host environment doesn't provide it, and anything else if the host environment does provide it, provided that "anything else" somehow represents the program name. In my more sadistic moments, I would consider translating it into Swahili, running it through a substitution cipher then storing it in reverse byte order :-).
However, implementation-defined does have a specific meaning in the ISO standards - the implementation must document how it works. So even UNIX, which can put anything it likes into argv[0]
with the exec
family of calls, has to (and does) document it.

- 854,327
- 234
- 1,573
- 1,953
-
Can you add a link to this standards document please, so we can all have a read? Thanks. – liwp Jan 12 '10 at 17:42
-
3That may be the standard, but unix simply does not enforce it, and you can't count on it. – dmckee --- ex-moderator kitten Jan 12 '10 at 19:23
-
4The question did not mention UNIX *at all*. It was a C question plain and simple, hence ISO C is the document of reference. The program name is implementation defined in the standard so an implementation is free to do what it wants, including allowing something in there that isn't the actual name - I thought I'd made that clear in the penultimate sentence. – paxdiablo Jan 12 '10 at 23:00
-
1So the standard says it's the "program name", but doesn't actually define what that means - in particular, it's not necessarily the "name of the executable". – caf Jan 13 '10 at 00:28
-
2Pax, I didn't vote you down, and don't approve of those who did because this answer is as authoritative as it *can* get. But I do think the unreliability of the value of `argv[0]` is apropos to programming in the real world. – dmckee --- ex-moderator kitten Jan 13 '10 at 00:32
-
4@caf, that's correct. I've seen it holding such diverse things as the full path of the program ('/progpath/prog'), just the filename ('prog'), a slightly modified name ('-prog'), a descriptive name ('prog - a program for progging') and nothing (''). The implementation has to define what it holds but that's all the standard requires. – paxdiablo Jan 13 '10 at 01:31
-
@dmckee, s'ok, there's only a small class of programs that depend on having a specific argv[0] format (e.g., those links that change behaviour based on the name: gzip/gunzip; and those that look for their executable). I'm not a big fan of either of those. I'd rather have separate executables with shared libraries for the former and executables should use the bin/var/etc rules for the latter, not go looking for config stuff where the executable is. – paxdiablo Jan 13 '10 at 01:32
-
3Thanks everyone! Great discussion from a (seemingly) simple question. Although Richard's answer is valid for *nix operating systems, I picked paxdiablo's answer because I'm less interested in the behavior of a specific OS, and primarily interested in the existence (or absence of) an accepted standard. (If you're curious: In the context of the original question - I have no operating system. I'm writing code to build the raw argc/argv buffer for an executable loaded onto an embedded device and needed to know what I should do with argv[0]). +1 to StackOverflow for being awesome! – Mike Willekes Jan 13 '10 at 18:53
Under *nix
type systems with exec*()
calls, argv[0]
will be whatever the caller puts into the argv0
spot in the exec*()
call.
The shell uses the convention that this is the program name, and most other programs follow the same convention, so argv[0]
usually the program name.
But a rogue Unix program can call exec()
and make argv[0]
anything it likes, so no matter what the C standard says, you can't count on this 100% of the time.

- 854,327
- 234
- 1,573
- 1,953

- 19,673
- 4
- 43
- 72
-
4This is a better answer than paxdiablo's above. The standard just calls it the "program name", but this is not enforced anywhere to my knowledge. Unix kernels uniformly pass the string passed to execve() unchanged to the child process. – Andy Ross Jan 12 '10 at 19:28
-
4The C standard is limited in what it can say because it doesn't know about 'execve()' etc. The POSIX standard (http://www.opengroup.org/onlinepubs/9699919799/functions/execve.html) has more to say - making it clear that what is in argv[0] is at the whim of the process the executes the 'execve()' (or related) system call. – Jonathan Leffler Jan 12 '10 at 22:36
-
1@Andy, you're free to have your opinions :-) But you're wrong about enforcement. If an implementation doesn't follow the standard then it's non-conforming. And in fact, since it's implementation-defined as to what the "program name" is, an OS like UNIX *is* conforming as long as it specifies what the name is. That includes being able to blatantly fake a program name by loading argv[0] with anything you want in the exec family of calls. – paxdiablo Jan 12 '10 at 23:06
-
That's the beauty of the word "represents" in the standard when it refers to argv[0] ("it represents the program name") and argv[1..N] ("they represent the program arguments"). "unladen swallow" is a valid program name. – Richard Pennington Jan 13 '10 at 00:33
According to the C++ Standard, section 3.6.1:
argv[0] shall be the pointer to the initial character of a NTMBS that represents the name used to invoke the program or ""
So no, it is not guaranteed, at least by the Standard.
ISO-IEC 9899 states:
5.1.2.2.1 Program startup
If the value of
argc
is greater than zero, the string pointed to byargv[0]
represents the programname;argv[0][0]
shall be the null character if the program name is not available from the host environment. If the value ofargc
is greater than one, the strings pointed to byargv[1]
throughargv[argc-1]
represent the program parameters.
I've also used:
#if defined(_WIN32)
static size_t getExecutablePathName(char* pathName, size_t pathNameCapacity)
{
return GetModuleFileNameA(NULL, pathName, (DWORD)pathNameCapacity);
}
#elif defined(__linux__) /* elif of: #if defined(_WIN32) */
#include <unistd.h>
static size_t getExecutablePathName(char* pathName, size_t pathNameCapacity)
{
size_t pathNameSize = readlink("/proc/self/exe", pathName, pathNameCapacity - 1);
pathName[pathNameSize] = '\0';
return pathNameSize;
}
#elif defined(__APPLE__) /* elif of: #elif defined(__linux__) */
#include <mach-o/dyld.h>
static size_t getExecutablePathName(char* pathName, size_t pathNameCapacity)
{
uint32_t pathNameSize = 0;
_NSGetExecutablePath(NULL, &pathNameSize);
if (pathNameSize > pathNameCapacity)
pathNameSize = pathNameCapacity;
if (!_NSGetExecutablePath(pathName, &pathNameSize))
{
char real[PATH_MAX];
if (realpath(pathName, real) != NULL)
{
pathNameSize = strlen(real);
strncpy(pathName, real, pathNameSize);
}
return pathNameSize;
}
return 0;
}
#else /* else of: #elif defined(__APPLE__) */
#error provide your own implementation
#endif /* end of: #if defined(_WIN32) */
And then you just have to parse the string to extract the executable name from the path.

- 1
- 1

- 69,011
- 20
- 139
- 164
-
2The `/proc/self/path/a.out` symlink may be usable on Solaris 10 and up. – ephemient Jan 12 '10 at 21:09
-
Upvoted for the code (not saying it's ideal or correct, e.g. on Windows `GetModuleFileNameW` should be used to be able to retrieve any path, but just the presence of the code constitutes good guidance). – Cheers and hth. - Alf Jul 12 '15 at 21:14
Applications of having argv[0] !=
executable name
many shells determine if they are a login shell by checking
argv[0][0] == '-'
. Login shells have different properties, notably that they source some default files such as/etc/profile
.It is typically the init itself or
getty
that adds the leading-
, see also: https://unix.stackexchange.com/questions/299408/how-to-login-automatically-without-typing-the-root-username-or-password-in-build/300152#300152multi-call binaries, perhaps most notably Busybox. These symlink multiple names e.g.
/bin/sh
and/bin/ls
to a single exebutable/bin/busybox
, which recognizes which tool to use fromargv[0]
.This makes it possible to have a single small statically linked executable that represents multiple tools, and will work on basically on any Linux environment.
See also: https://unix.stackexchange.com/questions/315812/why-does-argv-include-the-program-name/315817
Runnable POSIX execve
example where argv[0] !=
executable name
Others mentioned exec
, but here is a runnable example.
a.c
#define _XOPEN_SOURCE 700
#include <unistd.h>
int main(void) {
char *argv[] = {"yada yada", NULL};
char *envp[] = {NULL};
execve("b.out", argv, envp);
}
b.c
#include <stdio.h>
int main(int argc, char **argv) {
puts(argv[0]);
}
Then:
gcc a.c -o a.out
gcc b.c -o b.out
./a.out
Gives:
yada yada
Yes, argv[0]
could also be:
Tested on Ubuntu 16.10.

- 347,512
- 102
- 1,199
- 985
This page states:
The element argv[0] normally contains the name of the program, but this shouldn't be relied upon - anyway it is unusual for a program not to know its own name!
However, other pages seem to back up the fact that it is always the name of the executable. This one states:
You’ll notice that argv[0] is the path and name of the program itself. This allows the program to discover information about itself. It also adds one more to the array of program arguments, so a common error when fetching command-line arguments is to grab argv[0] when you want argv[1].

- 134,786
- 31
- 255
- 325
-
12Some programs take advantage of the fact that they don't know the name that was used to invoke them. I believe BusyBox (http://www.busybox.net/about.html) works this way. There is only one executable the implements many different command-line utilities. It uses a bunch of symbolic links and argv[0] to determine what command-line tool should be run – Trent Jan 12 '10 at 17:38
-
Yeah, I remember noticing that "gunzip" was a symbolic link to "gzip", and wondering for a moment how that worked. – David Thornley Jan 12 '10 at 17:42
-
2Many programs look at argv[0] for information; for example, if the last component of the name starts with a dash ('/bin/-sh', for example), then the shell will run the profile and other stuff as for a login shell. – Jonathan Leffler Jan 12 '10 at 19:20
-
2@Jon: I thought login shells were started with `argv[0]="-/bin/sh"`? That's the case on all the machines I've used, anyhow. – ephemient Jan 14 '10 at 21:09
I'm not sure whether it is a nearly universal convention or a standard, but either way you should abide by it. I've never seen it exploited outside of Unix and Unix-like systems, though. In Unix environments - and maybe particularly in the old days - programs might have significantly different behaviors depending on the name under which they are invoked.
EDITED: I see from other posts at the same time as mine that someone has identified it as coming from a particular standard, but I'm sure the convention long predates the standard.

- 1,372
- 10
- 29
-
1I sure wish that if people are going to "mark down" my response they would give some indication what they don't like about it. – Joe Mabel Jan 13 '10 at 06:57
If you start an Amiga program by Workbench argv[0] will not be set, only by CLI.

- 525
- 2
- 8
- 19