Question

I want to copy string from argv[0] but I don't know how to get the size of argv[0].

How to do this?

int main(int argc, char* argv[])
{
  char str[20];
  if(argc>0)
      memcpy(str, argv[0], sizeof(argv[0]));
}
Was it helpful?

Solution

Since argv[0] is a string, use strlen.

#include <string.h>

size_t length = strlen (argv[0]) + 1;

memcpy (str, argv[0], length);

By the way, you could also use strcpy, which is more suitable for strings.

#include <string.h>

strcpy (str, argv[0]);

In every case, in order to make sure that your copy won't overflow, you should check whether the size of str is sufficient.

if (sizeof str >= length)
{
  /* Do the copy. */
}
else
{
  /* Report an error, or use dynamic allocation. */
}

OTHER TIPS

You can use strdup() if your platform supports it. this makes your code more simple

int main(int argc, char* argv[])
{
  char *str = NULL;
  if(argc>0) {
      str = strdup(argv[0]);
  }

  .......
  // when the str became useless then free it
  free(str);
  ........
}

You need to use strlen. If you were to use sizeof, then you would get the size of the char*.

To copy the string, you should use strcpy or just assign to another char*. Better yet, use strncpy in conjunction with a size (the size of the destination - 1) to prevent buffer overflows into str. The -1 is to account for the null-terminating character (\0). Don't forget about this character! The problem becomes if strlen returns 20. Then it will drop the \0. You should also read up on secure use of strcpy and you can read more about strncpy here.

OR, you can do this and it makes everything I said moot:

const char* arg1 = argv[0];

which would make strlen pointless in this case.

char* argv[] is an array of pointers (char*) so sizeof(argv[0]) is equal to sizeof(char*).

You could either use strlen:

memcpy(str, argv[0], strlen(argv[0]) + 1);  // +1 because of '\0' at the end

or yet even better you could use strcpy:

strcpy(str, argv[0]);

but note that the length of the argv[0] might be greater than the size of your destination buffer (str) so you should either check the size of argv[0] before copying it.

You could also use strcnpy to copy only specified amount of characters, but in that case be very careful, because if there is no \0 in first 20 characters of argv[0], you'll have to terminate your string explicitly.

If your Cxx is >= C99

than you can do it in this way:

int main(int argc, char* argv[])
{

    int len = (argc>0) ? strlen(argv[0]) : 0;

    char str[len+1];
    if (argc>0)
        memcpy(str, argv[0], len+1);
}

I suggest to you to use pointer and allocate memory depending of the length of argv[0]:

int main(int argc, char* argv[])
{
  char *str = NULL;
  if(argc>0) {
      int len = strlen(argv[0])
      str = malloc((len+1)  * sizeof(char))
      memcpy(str, argv[0], (len+1));
  }

  .......
  // when the str became useless then free it
  free(str);
  ........
}

To summarise, because there's a lot of confusion and bad advice here:

The answer to your question in the narrowest sense is that you can find out the length of strings using strlen (sizeof returns the size of the data type in bytes, which for strings in char*, which (on a typical modern machine) will be either 4 (on 32-bit systems) or 8 (on 64-bit systems) regardless of the length of the string), but...

  1. Make sure this is something you need to be doing in the first place. If you don't intend to change the string, there's no reason to copy it. If you do intend to change it, you only need to copy it if you also want to preserve the old value, because the argv strings are mutable (as per the standard).

    If you either don't intend to change it or don't need the old value, but you still want another variable for some reason (readability, presumably), you should declare that variable as a pointer rather than an array and just assign to it:

    char *str = argv[0];
    
  2. If you're sure you do want to copy the string, you should not be using memcpy for this. You should be using strcpy, and you should be sure your new string is big enough to hold argv[0]. If you're using C99, you can do this easily:

    char str[strlen(argv[0]) + 1];
    strcpy(str, argv[0]);
    

    If you're using an older standard, you will need to allocate memory dynamically:

    char *str = malloc(strlen(argv[0]) + 1);
    strcpy(str, argv[0]);
    

    If you're on a POSIX system, you can shorten that by using strdup:

    char *str = strdup(argv[0]);
    

    If you're using malloc or strdup, remember that you need to free your memory manually when you're done with it.

    (You don't need to check if argc > 0 in any case, by the way; the standard guarantees that argv[0] is either the program name or a zero-length string (that is, argv[0][0] is '\0').)

  3. If you can't get away from using a fixed-length buffer, you can use strncpy if you remember to nul-terminate the resulting string manually and it's acceptable that your string is truncated if it is longer than the buffer:

    char str[20];
    strncpy(str, argv[0], 20); /* or 19, it doesn't matter. */
    str[19] = '\0';
    

I think that's everything.

There is such a flood of bad advice here, I have no idea why, this question is not complicated rocket science, but rather beginner level programming.

You check that there is an argument in argv[0], but formally there will always be at least one argument passed to main. The check against argc > 0 is to be regarded as defensive programming, but extra error checks are never bad.

You need to check against buffer overflows before copying the contents of an unknown buffer.

#include <string.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
  if(argc == 0)
  {
    // unexpected error
  }

  size_t len = strlen(argv[0]);
  char* str =  malloc(len * sizeof(char) + 1);
  if(str == NULL)
  {
    // no memory, error
  } 

  strcpy(str, argv[0], len);

  ...

  free(str);
}

And that's it.


  • strdup is bad advice because it isn't C standard and therefore not portable. It is also a completely superfluous function.
  • strncpy is bad advice, it was never intended as a secure version of strcpy. It is an old legacy function for handling records in dinosaur unix systems. It is much more dangerous than strcpy because it is easy to forget the null termination. There is never a reason to use strncpy in a modern C program. For some reason unknown, there is a lot of programmers who have been brainwashed into using strncpy as a guard against buffer overflows. Don't do this, the correct way is to ensure that the buffer is large enough before using strcpy/memcpy.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top