0

This code was provided by my c++ instructor on a sample midterm. We covered argc and argv on a very basic level, so I understand what those expressions alone mean. However, any additions to those like the dereference operator and '++' confuse me and what I've googled hasn't been clear enough for me to apply it to this specific example. Also, when I try to compile, it provides this error:

In function 'int summer(int*, char**)':
Line 9: error: cannot convert 'char**' to 'const char*' for argument '1' to 'int atoi(const char*)'
compilation terminated due to -Wfatal-errors.

We haven't officially covered pointers, but I think I understand them well enough. char** means you're dereferencing twice, so the value of the pointer char, which is a pointer to something else, so the second * means we want the value of that. Is it constant because we are relying on something input in the command line and that can't be changed? I don't understand this.

#include <iostream>

using namespace std; 

int summer(int *acc, char * ptr[])
{
  register int n;

  n = atoi(ptr);
  *acc = *acc + n;
}

main(int argc, char * argv [])
{
  int sum = 0;

  while (--argc)
    summer(&sum, *++argv);

  cout << "sum is " << sum << endl;
}

Another question: When passing *++argv to summer(), does that mean the value of (argv[] + 1)? What would that even be? Adding the value one to the entire vector? I know that atoi(array) means changing the string into a numerical value, and then we are storing that in register int 'n', and then adding that to the sum which is directly changed in main. And that's about the only part of this code I really understand. Sorry if my questions/this post is kind of a mess.

To sum up what my questions are:

  1. What does the compiling error message mean?
  2. What does ++argv do?

Thank you.


Edited:

Okay, I've made the changes you guys have suggested (thank you!!):

#include <iostream>

using namespace std; 

int summer(int *acc, char * ptr)
{
  register int n;

  n = atoi(ptr);
  *acc = *acc + n;

  return 0;
}

int main(int argc, char * argv[])
{
  int sum = 0;

  while (--argc)
    summer(&sum, *++argv);

  cout << "sum is " << sum << endl;

  return 0;
}

I also added the returns because the compiler gave a new error due to no return value for the function type. On Codepad it compiles and prints "the sum is zero," however, it still does not compile on Dev C++ 5.7.1 which is what I am using. It doesn't display error messages (the ones I have been reading are from Codepad online compiler), or at least I can't find where to turn them on. It just highlights the lines it seems to have a problem with, and that is still the line with atoi(ptr).

Sarah
  • 15
  • 7
  • I have a hard time believing your instructor would give you uncompilable code. – user657267 Nov 04 '14 at 00:06
  • Well people aren't perfect lol, and this isn't the first time he's done so. It could also be something I am missing. I've sent him an email but I hoped this site would provide faster feedback. @user657267 – Sarah Nov 04 '14 at 00:08
  • 1
    Not to mention `main` should be `int main`, and declaring a `register` variable is usually pointless with contemporary compilers. Pointer-heavy code is also odd seeing as this is meant to be a c++ class? – user657267 Nov 04 '14 at 00:11
  • I'm not. The instructor is obviously terrible...assuming this code was indeed written entirely by him and not partially by a student. – Edward Strange Nov 04 '14 at 00:11
  • It was written entirely by him lol. He's pretty old and he only responds to email at 2 in the morning so he probably just forgets things a lot. – Sarah Nov 04 '14 at 00:14
  • People are dumb, everyone forgets things a lot, that's why compilers help. Either he didn't bother compiling his own code, or he's using something prehistoric. – user657267 Nov 04 '14 at 00:17
  • @user657267 or it's left as an exercise to the student lol. I can't say I didn't learn something from his mistakes. – Sarah Nov 04 '14 at 00:24
  • `#include ` should fix the error with `atoi()` – sp2danny Nov 04 '14 at 07:29

4 Answers4

2

*argv is equivalent to argv[0], so ++argv; would make *argv equivalent to what was originally argv[1]. So *++argv evaluates to the same thing as argv[1] (the first command line argument, after the name of the program itself), except it increments argv whereas argv[1] obviously does not.

For your error, you should change:

int summer(int *acc, char * ptr[])
{

to:

int summer(int *acc, char * ptr)
{

When you dereference a char **, which is the type of argv, you get a char *. char * is what atoi() is expecting.

Your program is essentially equivalent to this:

#include <iostream>
#include <cstdlib>

using namespace std;

void summer(int * acc, char * ptr)
{
    *acc += atoi(ptr);
}

int main(int argc, char * argv [])
{
    int sum = 0;

    for ( int i = 1; i < argc; ++i ) {
        summer(&sum, argv[i]);
    }

    cout << "sum is " << sum << endl;
}

except that your's doesn't check for troublesome values of argc.

Crowman
  • 25,242
  • 5
  • 48
  • 56
  • `char * ptr[]` is not replacable by `char * ptr`. They are completely different types. – Edward Strange Nov 04 '14 at 00:13
  • @CrazyEddie They indeed are different types, which is why it doesn't compile. Everything about the code suggests that `char * ptr` is correct -- the call to `atoi()` as well as the actual arguments supplied when `summer()` is called. – cdhowie Nov 04 '14 at 00:14
  • @CrazyEddie: That's precisely why the OP should replace it. – Crowman Nov 04 '14 at 00:14
  • Thank you so much for your help! I changed the parameter for summer and it still would not compile. (details in edited original post) – Sarah Nov 04 '14 at 00:43
  • @Sarah: You should also `#include ` for `atoi()`. It ought to compile when you do that. – Crowman Nov 04 '14 at 00:54
0

The ++ is called the increment operator. It usually adds 1 to something.

The argv decays to a pointer that points to a container of arguments to your program.

The expression ++argv points to next parameter, if there is one.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
  • 2
    Actually the `argv` doesn't decay to a pointer, it already is one. The `type param[]` syntax is just another way to say `type * param` in the context of a function parameter. – Edward Strange Nov 04 '14 at 00:08
0

Incrementing a pointer means to make it point to the next item in the list.

argv has type char ** (don't be distracted by the square brackets), meaning it points to a char * which is in a list of adjacent char *s. The argc parameter lets us know where to find the end of said list.

So, doing ++argv means that argv will now point to the next char * in the list. Applying * to that (and passing the result to a function) means that we send the value of the next char * in the list to that function.

The result of all this is that the function is called once for each argument, excluding the first one (since we ++'d before dereferencing the first time).

NB. This code actually has a bug; if argc == 0 it will go off into la-la land. It should check for this case before entering the loop.

Community
  • 1
  • 1
M.M
  • 138,810
  • 21
  • 208
  • 365
0

Is it constant because we are relying on something input in the command line and that can't be changed?

No, the const char * bit refers to the type of argument that atoi() accepts. It is a pointer to a constant char. Note that char * is implicitly convertible to const char *, but not the opposite.

All this means is that atoi() accepts a pointer to a character, and it promises that it will not modify the target of the pointer.

My guess is that the ptr argument should have been char * ptr instead of char * ptr[]. If you change that, the code should compile.

cdhowie
  • 158,093
  • 24
  • 286
  • 300
  • Thank you very much for your help! I made the change you suggested however it still does not compile. (details in edited original post) – Sarah Nov 04 '14 at 00:44