Saurav Rai
Saurav Rai

Reputation: 2367

If argc is 1, can I still use argv[1], argv[2],... character arrays?

If there is no argument passed from the command line ie. if argc is 1, can we still allocate memory for argv[1],argv[2],..... and use those buffers for further experiments. If that is undefined behavior, can I still use it somehow?

Upvotes: -1

Views: 502

Answers (4)

Dražen Grašovec
Dražen Grašovec

Reputation: 802

We probably can't allocate those data because it is already used

I didn't dive into standard to see what theory says, I suppose behavior is undefined. But I am more interested how real life behaves.

Let's try gcc complying with C18 standard -std=c18on Linux OS.

Using argv[x] it is just a way of de-referencing *(argv+x)

Sinceargv is a pointer to array of char pointers and char *argv[] array is also located on stack. Since there is no arguments there is just argv[0] = <Program Name> and argv[1] = <NULL> allocated on stack.

Trying to access argv[x] if x > 1, you would only access some data on stack which comes after argv[1]. Program stores return addresses, program arguments, local variables, and we can't be sure what data and type it may be. So we cant just access this memory and use for our purpose.

We can try to see what happens in program compiled gcc If you run this small program:

#include <stdio.h>

int main(int argc, char **argv)
{
   printf("argc is 0%d\n", argc);
   for ( int i = 1; i < 15; i++) {
        printf("argv[%d] is 0%s\n", i, argv[i]);
   } 
   return 1;
}

And you see that after argv[0] which points to program name, and argv[1] = NULL, which is delimiter, we will access some char pointers which represents environment variables which execve() syscall passes to a program when it starts it:

drazen@HP-ProBook-640G1:~/proba$ ./proba
argc is 01
argv[0] is: ./proba
argv[1] is: (null)
argv[2] is: SHELL=/bin/bash
argv[3] is: SESSION_MANAGER=local/HP-ProBook-640G1:@/tmp/.ICE-unix/1133,unix/HP-ProBook-640G1:/tmp/.ICE-unix/1133
argv[4] is: QT_ACCESSIBILITY=1
argv[5] is: COLORTERM=truecolor
argv[6] is: XDG_CONFIG_DIRS=/etc/xdg/xdg-cinnamon:/etc/xdg
argv[7] is: XDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session0
argv[8] is: GNOME_DESKTOP_SESSION_ID=this-is-deprecated
argv[9] is: LANGUAGE=en_US
argv[10] is: MANDATORY_PATH=/usr/share/gconf/cinnamon.mandatory.path
argv[11] is: LC_ADDRESS=hr_HR.UTF-8
argv[12] is: LC_NAME=hr_HR.UTF-8
argv[13] is: SSH_AUTH_SOCK=/run/user/1000/keyring/ssh
argv[14] is: CINNAMON_VERSION=5.8.4

We see that this syscall execve() which is called by OS after it starts our program passes array of pointers on environment variables envp[] after function arguments argv[], so it makes sense:

int execve(const char *filename, char *const argv[], char *const envp[]);

So memory on stack where argv[] pointers should be is already taken by pointers to environment variables. This is how it is on Linux architecture, I didn't tested it on other systems. But I suppose on other systems, system passes some data on a stack too.

Upvotes: 0

pmg
pmg

Reputation: 108988

can I access argv[] elements after argv[argc]?

You can ... but ONLY IN THIS CODE

#include <stdio.h>

int main(int argc, char **argv) {
    if (argc == 1) {
        char *foo[] = {"bar", "baz", "quux", NULL, "bingo"};
        main(3, foo);
    } else {
        printf("argc is %d; argv[4] is \"%s\"\n", argc, argv[4]);
    }
    return 0;
}

See code running on ideone.

In all other codes, you cannot.

Upvotes: 1

Eric Postpischil
Eric Postpischil

Reputation: 223747

No, the C standard does not specify that argv has any elements beyond argv[argc], so they may not exist in C’s object-memory model and the behavior of using them is not defined by the C standard.

C 2018 5.1.2.2.1 2 says:

argv[argc] shall be a null pointer.

If the value of argc is greater than zero, the array members argv[0] through argv[argc-1] inclusive shall contain pointers to strings, which are given implementation-defined values by the host environment prior to program startup.

That is all there is that defines the extent of the argv array; nothing in the standard says there are more elements.

When argc is one, using argv[1] is defined but using argv[2] is not.

You can store new values to the defined elements because C 2018 5.1.2.2.1 2 also says:

The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination.

Upvotes: 4

Vlad from Moscow
Vlad from Moscow

Reputation: 311088

Always argv[argc] is equal to NULL. In the described case where argc is equal to 1 the array argv contains two pointers argv[0] and argv[1] where argv[1] is a null pointer.

You may reassign the pointers but this does not make a great sense because that will make your program unclear. Instead you could declare your own array if you need.

Upvotes: 0

Related Questions