0

I'm new to C++ and want to achieve something extremely simple, but it will not let me. I've read a bunch of ways to "assign" or "link" or "copy" arrays, but NONE of these seem to work at all.

Consider the following:

in file: header.h:

using namespace std;

Class Proc
{
    public: static char args;
};

in file: main.cpp:

using namespace std;

#include <cstdlib>
#include <memory>
#include "header.h"

int main(int argc, char* argv[])
{
    Proc::args = argv;                // yea i know this won't work :(
    // Proc::args[argc] = argv;       // not working either
    // memcpy(argv, Proc::args, sizeof(argv));   // nope
    // copy(begin(argv), end(argv), begin(Proc.args));   // nope
}

In fact I don't really want to "copy" it at all, linking it is just fine, but the g++ compiler keeps throwing up in my face about undefined reference to 'Proc::args' and who knows what else.

I'm about to put a drill to my ear, can anyone please make an example?

It is different from undefined reference to'Proc::args'because I also get:error: invalid use of qualified-name 'Proc::args'and also that it complains aboutchar**&char*not being the same... - and when I add an asterisk to Proc'schar* args` then it throws some more.

17
  • Possible duplicate of Undefined reference to static class member Commented Dec 27, 2015 at 13:35
  • 4
    args isn't an array, for starters. It's a single character. Commented Dec 27, 2015 at 13:38
  • thanks, I tried that, but still does not answer the question of how to actually assign the argv to the Proc.args, as it complains about the datatype being incompatible, where clearly they are the same, or so I think? Commented Dec 27, 2015 at 13:38
  • 1
    @Sri.U No. Not the same type at all. Please don't spread confusing falsehoods. Commented Dec 27, 2015 at 13:57
  • 1
    @Sri.U: An array can decay into a pointer, but they are different and their distinction really matters, especially on the stack and for struct members and variables. See the corresponding entry in the C FAQ. Commented Dec 27, 2015 at 14:05

4 Answers 4

2

If I understand correctly, you want to copy command-line arguments into some variable.

Here is one way to do that, that does the copy. It is also possible to save a pointer on original data, but it's usually no worth the effort.

struct Proc
{
   std::vector<std::string> args;
   Proc( int argc, char* argv[] )
   {
      for( size_t i=0; i<(size_t)argc; ++i )
         args.push_back( argv[i] );
   }
};

int main(int argc, char* argv[])
{
    Proc cla( argc, argv ); // saves cl args into variable
    for( const auto& c: cla.args ) // print out
      std::cout << c << "\n";
}

Live here

Side comment: I disagree with @Sri.U 's answer, usage of memcpy is not recommended with modern C++. Similarly, usage of raw arrays is also discouraged as the library provides safer containers (string and vector).

Sign up to request clarification or add additional context in comments.

4 Comments

@ kebs - thanks, I can't print it out to see if Proc.args[0] is working though.. now it moans this: When I use: cout << Proc::args then I get: error: ‘args’ is not a member of ‘Proc’ - and when I do: cout << Proc.args I get: error: expected primary-expression before ‘.’ token Any advice?
@ kebs - thanks, it works! - beers all around !!! - I had to check your live example first though as you used headers I did not include at first. Thank you very VERY much!
Using @kebs's answer, I have another problem .. is there no way I can just access 1 of the args from Proc like this: Proc::args[0] or Proc::args[1] ? .. I don't mind converting it to some other data type or whatever... just, it seems odd to be forced to use a loop & possibly conditional logic to do so - thanks
Yes, use cla.args[0] etc.
1

I think there are two problems in the sample code you have shown:-

  1. Static should be initialized after declaration, outside of the class like -
char Proc::args = '\0';

int main(int argc, char* argv[]) 
{
  //Proc::args = argv; /* invalid conversion */

  return 0;
}

This will resolve your undefined reference problem.

  1. You are doing invalid conversion from char** to char by doing Proc::args = argv; you can use static char **args instead.

Comments

0

You can have:

public: static char args[NUM_ARGS][STRING_LENGTH];


Then you can do memcpy for each of the arguments like this:

for (i=0; i < argc; i++) {
    memcpy (argv[i], args[i], sizeof(argv[i])):
}


The argument in main function argv is array of char pointers. So you have argc number of strings.

So instead of

public: static char args[NUM_ARGS][STRING_LENGTH];


you can also have array of pointers and allocate it in main like below:

public: static char *args[STRING_LENGTH];


Edit based on OPs comment: If you just want to assign it to args, then you need to have

public: static char **args;

8 Comments

AT Sri.u - thanks, but that doesn't help me though.. I need to simply assign the argv array as it is to the Proc.args property, both being the same data-type, preferably linked, not copied, but if I really have to copy them I will do that.. remember also that: arguments vary, in number and (string)-length, so if I need to use the lengths, then surely I will need to define some constant for new array or whatever, I just really don't know how, I've been at this since 7am this morning ;(
hope it helps now. but could not understand what you do after that.
To clarify the edited answer, you should add that you need to put the declaration static char **Proc::args; in the global scope (outside of main()) and then inside of main do Proc::args = argv;
okay, I've done that now, and it moaned about char** not being the same as char* (weird) so I added an extra asterisk to the property definition in the Proc class, and done as you & @danishansari pointed out, .. now I get this: error: ‘static’ may not be used when defining (as opposed to declaring) a static data member [-fpermissive] static char **Proc::args;
Sorry about that, that was my mistake (fingers in gear, brain in neutral) - the 'static' shouldn't be there.
|
0

Thanks so much to all for your input!

Using what you taught me I "frankensteined" the answers & comments together and came up with a working solution (below)

I hope this helps someone, and again thanks very much for all your effort. Please feel free to shorten the code, or make it more elegant.

in file: header.h:

using namespace std;

class Proc
{
    public: static char** args;

    public: static void init(char* args[])
    {
        Proc::args = args;
    };
};

char **Proc::args;   // important!

in file: main.cpp:

using namespace std;

#include <iostream>

int main(int argc, char* argv[])
{
    Proc::init(argv);
    cout << Proc::args[0];    // works !!
}

1 Comment

A couple of suggestions. 1. Don't put using namespace std; in a header file. This is considered bad style in most guidelines and it may cause a problem in some future code that uses your header as it can create a name clash. 2. The definition char **Proc::args; should be in its own file, not in a header file which is typically included by multiple .cpp files and would break the One Definition Rule. You can read more about these two things in most good C++ books - see FAQ.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.