0

I'm writing a simple variadic function that adds together a series of ints and returns the sum. I'm having a bit of trouble understanding how it works and my code doesn't seem to work though I feel I'm in the right direction with my code. (Posted below) The specifications of this function are that it takes at least one param and the last param is always a zero (as seen called in the main). I was also told, based upon my machine, that I wouldn't necessarily get the output I'm looking for which, as you could imagine, further complicates my situation. Some assistance with correcting my Sum() function would be greatly appreciated.

EDIT: This is supposed to be done w/o the use of stdarg.h header and thus no va_arg functions.

int Sum(int a, ... ) {
   int sum = 0, *addy = &a;

   while (*addy) {
      sum += *addy;
      addy += sizeof(a);
   }

   return sum;
}


int main() {
   printf("%d %d %d %d\n", Sum(0), Sum(3, 5, 6, 7, 0),
   Sum(7, 2, 42, 3, 5, -4, 0), Sum(-1, 9, 12, 123, -213, 42, 7, 2, 0));
}
//Expected output: 0 21 55 -19
//My output: 0 32770 32770 32776
Mike
  • 1,307
  • 3
  • 17
  • 29
  • @Eddy_Em yeah, I check that out and found some help with that, however I am supposed to write this method without the use of any va_arg methods. – Mike Jan 22 '13 at 05:03
  • There is no portable way of doing that. Some approaches may appear to work on certain OS/platform/compiler combinations, but they **will not** work reliably, as variadic function calling conventions are not uniform. –  Jan 22 '13 at 05:08
  • @duskwuff ah I see. Yes, my professor told me that this may or may not work on my machine though it will work under his and I think that is what you are talking about when you say variadic functions are not uniform. – Mike Jan 22 '13 at 05:16
  • You've forget about data aligning. This way may not work on some architectures. And BTW, as said lower, `addy += sizeof(a)` is wrong. – Eddy_Em Jan 22 '13 at 05:39

4 Answers4

3

When you add a number to an int pointer (as in addy += sizeof(a)) the number you add is automatically multiplied by the size of whatever type the pointer is declared as (in this case int). To fix this, just use

addy += 1;

instead. However, I would recommend using variadic macros instead of this method, they are clearer and less error prone.

John Colanduoni
  • 1,596
  • 14
  • 18
  • Sorry for not stating earlier, though I just added the edit, I am not supposed to use the variadic macros for this method. – Mike Jan 22 '13 at 05:06
  • Also, I was under the impression that once I add the value pointed to by *addy in 'sum += *addy;' I then need to increment *addy to the next int which is sizeof(a) or 4bytes away as done in the code 'addy += sizeof(a);' – Mike Jan 22 '13 at 05:08
  • Understood. You should be pretty safe with this method, at least on the x86 (and Intel/AMD 64) platforms, as the C ABI on those allows this to work. However, you will need to be careful if you will be running this code on other processor architectures. – John Colanduoni Jan 22 '13 at 05:08
  • No. When you add to a pointer in C, it will automatically multiply by sizeof(*addy). So `addy += sizeof(a)` actually adds `sizeof(*addy)*sizeof(a)`, which is too much. – John Colanduoni Jan 22 '13 at 05:11
  • Oh, I did not know that. So how does adding 1 to addy, as you said in your answer, fix this? Wouldn't that get me to 1 + sizeof(addy)? – Mike Jan 22 '13 at 05:18
  • No, it gets you to `1*sizeof(*addy)`, or just `sizeof(*addy)`, which is the same as sizeof(a). – John Colanduoni Jan 22 '13 at 05:30
  • I understand now. Would a ++ be just as sufficient? – Mike Jan 22 '13 at 05:33
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/23128/discussion-between-hevylight-and-mike) – John Colanduoni Jan 22 '13 at 05:37
1

for variable arguments, you have to use va_start and va_end functions, hope useful..

http://www.gnu.org/software/libc/manual/html_node/Variadic-Example.html#Variadic-Example

Adeel Ahmed
  • 1,591
  • 8
  • 10
1

Can you please check this

int Sum(int a, ... ) {
 int sum = 0, *addy = &a;

while (*addy) {
  sum += *addy;
  addy ++;
}

return sum;
}


int main() {
   printf("%d %d %d %d\n", Sum(0), Sum(3, 5, 6, 7, 0),
  Sum(7, 2, 42, 3, 5, -4, 0), Sum(-1, 9, 12, 123, -213, 42, 7, 2, 0));
}

Point to remember is for pointer operations: the number you are adding to the pointer will be multiplied by the size of the type that the pointer is pointing to. So incrementing the pointer addy is enough for geting the next element.

999k
  • 6,257
  • 2
  • 29
  • 32
  • Results will depend on the OS/platform/compiler combinations. Its working in mine. Check it with addy--. Also add printf("%d",*addy); in you while loop to verify whether reading process is correct. – 999k Jan 22 '13 at 05:17
  • With the print I am getting values -1 1 7 1 8 *large changing number* 32767 1 3 1 4 *another large changing number* 32767 1 in that order. – Mike Jan 22 '13 at 05:25
  • But I have a feeling that I am getting these values due to my compiler and you getting different results using your compiler. – Mike Jan 22 '13 at 05:34
  • Yes. Anyway update your knowledge about pointer airthematic using this http://stackoverflow.com/questions/394767/pointer-arithmetic – 999k Jan 22 '13 at 05:39
0
 #include <stdarg.h>
 #include <stdio.h>

 int
 add_em_up (int count,...)
 {
   va_list ap;
   int i, sum;

   va_start (ap, count);         /* Initialize the argument list. */

   sum = 0;
   for (i = 0; i < count; i++)
     sum += va_arg (ap, int);    /* Get the next argument value. */

   va_end (ap);                  /* Clean up. */
   return sum;
 }

 int
 main (void)
 {
   /* This call prints 16. */
   printf ("%d\n", add_em_up (3, 5, 5, 6));

   /* This call prints 55. */
   printf ("%d\n", add_em_up (10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10));

   return 0;
 }
sai
  • 93
  • 8