0

I've written a code that sums up integers brought in from the command line:

#include <stdio.h>

int main(int argc, int* argv[]) {
  int i, s=0;

  for (i=1;i<argc;i++) 
  s=s + *argv[i];

  printf("Sum: %d\n", s);

return 0;
}

The best part is, it passes the gcc compiling process, but when I actually run it and insert the numbers, the result seems I somehow breached the range of int.

monolith937
  • 429
  • 1
  • 4
  • 13
  • 2
    "The best part is, it passes the gcc compiling process" -- no it does not. – Jongware Feb 01 '15 at 15:47
  • Ah sorry forgot to add it, it represents sum and it `int` – monolith937 Feb 01 '15 at 15:48
  • 1
    You're summing pointers, not integers. –  Feb 01 '15 at 15:49
  • Compiling with warnings may have told you that the second argument of `main` should be `char **`... – mafso Feb 01 '15 at 15:56
  • @Jongware, it compiles as is, even with the `int * argv[]`. A simple `gcc file.c` yields no warnings even. I'm surprised this doesn't give a warning! – Aaron McDaid Feb 01 '15 at 16:03
  • @Aaron: pre-edit, it did not. And I make sure to use `-Wall` on principle -- this issues a warning for the malformed `main` declaration. – Jongware Feb 01 '15 at 16:05
  • I have `-Wextra` and `-Werror` as well :-). I'm just surprised that `gcc` doesn't complain. Is there any legitimate use of `main` with such a signature? I guess there might be some strange environments where `main` is not the entry point, and therefore it doesn't have to be 'special' – Aaron McDaid Feb 01 '15 at 16:09
  • It does on my system: `warning: second argument of 'main' should be 'char **'`. But I wouldn't be surprised if this is due to Apple's private tinkering with `gcc`, as mine gets identified as `i686-apple-darwin11-llvm-gcc-4.2`. I never bothered to check; maybe I have been running `clang` all along. – Jongware Feb 01 '15 at 16:16
  • For a detailed discussion of the return type (and arguments permitted) to `main()`, see [What should `main()` return in C and C++](http://stackoverflow.com/questions/204476/what-should-main-return-in-c-and-c/18721336#18721336). The C standard stipulates two possible signatures (`int main(void)` and `int main(int argc, char **argv)` and equivalents); it permits an implementation to define other signatures for `main()`. C++ is less permissive; it requires the return type to be `int` (C does not). You certainly can't just change the types of the arguments; the implementation must also support it. – Jonathan Leffler Feb 01 '15 at 16:17
  • there are only two valid formats for main: 1) int main(void) 2) int main( int argc, char**argv) (although this will normally also be accepted: 3) int main() 4) int main( int argc, char*argv[]) Anything else is not correct and enabling all the warnings for the compiler will raising a warning about an invalid main declaration. – user3629249 Feb 01 '15 at 18:32
  • Irregardless of what type your code claims the argv array to contain, in reality, it contains pointers to strings. so argv[x] will get a pointer to a string. This is a string from the command line. a string char [] = "1234" cannot be directly read as a int. rather, it must be converted, using something like: int myNum = atoi(argv[x]) This kind of line: 's=s + *argv[i];' will treat the first 4 (on a 32 bit system) 0x31323334 as a integer number, which is definitely not 1234 decimal. (which has the memory representation of: 0x000004d2) – user3629249 Feb 01 '15 at 18:45

3 Answers3

2

It seems that you are compiling your code in C89 mode in which s is taken as int by default by compiler. s is uninitialized therefore nothing good could be expected. If fact it will invoke undefined behavior.

Note that argv[i] is of char * type (change your main signature) and you need to convert it to int before adding it to s.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
haccks
  • 104,019
  • 25
  • 176
  • 264
0

Assuming you have s initialized properly as shown below. Along with this the prototype of your main() should be as shown below inorder to get the command line arguments.

int main(int argc, char **argv)
{
  int s =0;
  // Check for argc matches the required number of arguments */
  for(i=1;i<argc;i++)
  s=s + atoi(argv[i]); /* Use atoi() to convert your string to integer strtol() can also be used */

  printf("%d\n",s);
  return 0;
}

PS: Using uninitialized variables lead to undefined behvaior

Gopi
  • 19,784
  • 4
  • 24
  • 36
  • 1
    You've missed the abuse of the signature of `main()`. – Jonathan Leffler Feb 01 '15 at 16:05
  • The declaration of argv is incorrect in the question as well. Although maybe that doesn't matter so much. Does `int*` convert to `char*` silently on the way into `atoi`? – Aaron McDaid Feb 01 '15 at 16:05
  • 2
    I'm sick of people asking "Why the down vote?" within 30 seconds of people making a downvote. Be patient while people write their comment about why they voted. Readers shouldn't have to see those kind of comments. Please delete the "why down vote?" comment (and I will delete this comment then also) – Aaron McDaid Feb 01 '15 at 16:06
  • @JonathanLeffler Sir you meant I needed to have the edited changes? Sorry I didn't get your point – Gopi Feb 01 '15 at 16:07
  • @Gopi; He meant to correct the signature of `main`. – haccks Feb 01 '15 at 16:08
  • Your revision now includes `argc` and `argv` (an early version didn't), but you've not commented upon the misuse, merely quietly fixed it. The chances are that `atoi()` on the arguments is what is wanted; adding `*argv[i]` would also work, adding the character values of the first character of each argument, and therefore producing a different answer. – Jonathan Leffler Feb 01 '15 at 16:10
0

The 2nd argument of main should be either of type char** or of type char*[] and not int*[]. So, *argv[i] is of type char. Instead of getting each character, you can get each string(argv[i] which is of type char*) and then extract the number from it and assign it to a variable, say num. This can be done by using the sscanf function:

#include <stdio.h>

int main(int argc, char* argv[]) { //int changed to char here
  int i, s=0,num;

  for (i=1;i<argc;i++) 
      if(sscanf(argv[i],"%d",&num)) //if extraction was successful
          s=s + num;

  printf("Sum: %d\n", s);

  return 0;
}
Spikatrix
  • 20,225
  • 7
  • 37
  • 83