Why check if (*argv == NULL)? [duplicate]
Asked Answered
F

4

11

In the data structures class that I am currently taking, we have been tasked with writing a web crawler in C++. To give us a head start, the professor provided us with a program to get the source from a given URL and a simple HTML parser to strip the tags out. The main function for this program accepts arguments and so uses argc/argv. The code used to check for the arguments is as follows:

// Process the arguments
if (!strcmp(option, "-h"))
{
    // do stuff...
}
else if (!strcmp(option, ""))
{
    // do stuff...
}
else if (!strcmp(option, "-t"))
{
    // do stuff...
}
else if (!strcmp(option, "-a"))
{
    // do stuff...
}

if ( *argv == NULL )
{
    exit(1);
}

Where "option" has been populated with the switch in argv[1], and argv[2] and higher has the remaining arguments. The first block I understand just fine, if the switch equals the string do whatever based on the switch. I'm wondering what the purpose of the last if block is though.

It could be that my C++ is somewhat rusty, but I seem to recall *argv being equivalent to argv[0], basically meaning it is checking to make sure arguments exist. Except I was under the impression that argv[0] always (at least in most implementations) contained the name of the program being run. It occurs to me that argv[0] could be null if argc is equal to 0, but searching around on Google I couldn't find a single post determining whether or not that is even possible.

And so I turn to you. What exactly is that final if block checking?

EDIT: I've gone with the reasoning provided in the comments of the selected answer, that it may be possible to intentionally cause argv[0] to become NULL, or otherwise become NULL based on an platform-specific implementation of main.

Flicker answered 25/2, 2010 at 17:16 Comment(5)
Notice that argv is not an array, but a pointer. That means you can perfectly well say argv++ to iterate through the options. You don't have to modify the value of *argv.Pope
Out of curiosity, what was the reason given by your professor when you asked him/her about it?Fulbert
Now, 5 years later, I'm afraid I really don't remember. I seem to vaguely recall asking my TA and the reasoning being the same as in the comments of the accepted answer (see the EDIT in the question), but I could be making that up and just remembering all wrong. :PFlicker
I know this is really late, but just as a note, you can easily parse command line options with getopt().Verdict
Not sure marking this as duplicate was warranted given that this question was asked and answered 3 months before the linked "duplicate". (Which was, in fact, 7 years ago at this point >_> )Flicker
C
10

argc will provide you with the number of command line arguments passed. You shouldn't need to check the contents of argv too see if there are not enough arguments.

if (argc <= 1) { // The first arg will be the executable name
   // print usage
}
Casals answered 25/2, 2010 at 17:18 Comment(10)
I know this, the code above is code that was given to us by our professor. Personally, I always check against argc. I'm asking what is *argv == NULL actually checking? My impression was that it is the same as checking argv[0] == NULL, which as far as I know is impossible, so why check for it?Flicker
@Shaun: Yes, *argv is identical to argv[0]. This is normally not possible when you're running the app from a normal shell. But I think it may be possible if you execute a process directly from another program by using exec system call and passing the arrays manually.Casals
I thought argv[0] always contained the name of the program though, so why check to see if it is NULL?Flicker
@Shaun: Well, it's not magic that places the name of program in argv. The shell puts that in the array when it's spawning your process. It may be possible (depends on the platform) to manually craft a launcher process that doesn't pass such an argument to your program.Casals
@Shaun: Maybe your professor is ... wrong?Nanon
The professor is writing to the C++ standard. Of course it may be that his code relies elsewhere on implementation-specific features (such as some API for connecting to a network) which as it turns out restricts the code to platforms which guarantee, out of the kindness of their hearts rather than any necessity imposed by the standard, that argv[0] is non-null.Calumnious
@Shaun, the program may have incremented argv so it now points at a null pointer. See @Steve's answer.Pope
@Mehrdad: Okay, I can believe that it may be possible to make argv[0] NULL if you do so intentionally. Just having always run our programs on either Windows or Solaris, never through a custom launcher, and never having seen that check in any of them, it struck me as rather odd.Flicker
@Shaun: It's safe to assume that's the case in normal circumstances. But since argc is specifically provided to count the number of arguments, why would you risk not doing that? Adding an if statement that checks for argc is not such a big deal.Casals
@Mehrdad: I agree, but I didn't write the code. :)Flicker
C
13

3.6.1/2:

If argc is non-zero those arguments shall be provided in argv[0] though ... and argv[0] shall be the pointer to the initial character of a NTMBS that represents the name used to invoke the program or "". The value of argc shall be nonnegative. The value of argv[argc] shall be 0.

Emphasis mine. argc is only guaranteed non-negative, not non-zero.

This is at entry to main. It's also possible that //do stuff modifies the value of argv, or the contents of the array it points to. It's not entirely unheard of for option-handling code to shift values off argv as it processes them. The test for *argv == null may therefore be testing whether or not there are any command-line arguments left, after the options have been removed or skipped over. You'd have to look at the rest of the code.

Calumnious answered 25/2, 2010 at 17:26 Comment(0)
C
10

argc will provide you with the number of command line arguments passed. You shouldn't need to check the contents of argv too see if there are not enough arguments.

if (argc <= 1) { // The first arg will be the executable name
   // print usage
}
Casals answered 25/2, 2010 at 17:18 Comment(10)
I know this, the code above is code that was given to us by our professor. Personally, I always check against argc. I'm asking what is *argv == NULL actually checking? My impression was that it is the same as checking argv[0] == NULL, which as far as I know is impossible, so why check for it?Flicker
@Shaun: Yes, *argv is identical to argv[0]. This is normally not possible when you're running the app from a normal shell. But I think it may be possible if you execute a process directly from another program by using exec system call and passing the arrays manually.Casals
I thought argv[0] always contained the name of the program though, so why check to see if it is NULL?Flicker
@Shaun: Well, it's not magic that places the name of program in argv. The shell puts that in the array when it's spawning your process. It may be possible (depends on the platform) to manually craft a launcher process that doesn't pass such an argument to your program.Casals
@Shaun: Maybe your professor is ... wrong?Nanon
The professor is writing to the C++ standard. Of course it may be that his code relies elsewhere on implementation-specific features (such as some API for connecting to a network) which as it turns out restricts the code to platforms which guarantee, out of the kindness of their hearts rather than any necessity imposed by the standard, that argv[0] is non-null.Calumnious
@Shaun, the program may have incremented argv so it now points at a null pointer. See @Steve's answer.Pope
@Mehrdad: Okay, I can believe that it may be possible to make argv[0] NULL if you do so intentionally. Just having always run our programs on either Windows or Solaris, never through a custom launcher, and never having seen that check in any of them, it struck me as rather odd.Flicker
@Shaun: It's safe to assume that's the case in normal circumstances. But since argc is specifically provided to count the number of arguments, why would you risk not doing that? Adding an if statement that checks for argc is not such a big deal.Casals
@Mehrdad: I agree, but I didn't write the code. :)Flicker
J
4

Remembering just how portable C is, it might not always be running on a standard platform like Windows or Unix. Perhaps it's some micro-code inside your washing machine running on some cheap, hacked environment. As such, it's good practice to make sure a pointer isn't null before dereferencing it, which might have led to the question.

Even so, you're correct. *argv is the same as argv[0], and argv is supposed to be initialized by the environment, if it's provided.

Johan answered 25/2, 2010 at 17:25 Comment(2)
'Perhaps it's some micro-code inside your washing machine' - Great, now I'm waiting for the message "Sorry, you must update 'Adobe Flash' to the most recent version to enter rinse cycle."Impacted
@TomWest Modern take of that: "This plug is no longer supported. Please update at nearest maintenace shop."Pernik
H
4

just a speculation.

what if your professor is referring to this ??

while(*++argv !=NULL)

    printf("%s\n",*argv);
Headstock answered 25/2, 2010 at 17:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.