7

I was trying to create a program that inputs two number and outputs their sum. For this I must have to use two variables. I was just curious whether this can be done by using only one variable.
Note : user has to input two numbers.

#include<stdio.h>
int main()
{
int a, b;
scanf("%d%d",&a,&b);
printf("%d",(a+b));
return 0;
}
Yunnosch
  • 26,130
  • 9
  • 42
  • 54
Uttam Manher
  • 142
  • 1
  • 5

10 Answers10

11
#include <stdio.h>
int main ( void )
{
   int a[3];

   scanf("%d", &a[0]);   /* first number */
   sscanf("%d", &a[1] );    /* second number */

   a[2] = a[0] + a[1];

   printf("sum is %d\n", a[0] + a[1] );

   printf("sum stored in a[%d] is %d\n", 2, a[2] );

   return 0;
}
ron
  • 967
  • 6
  • 23
  • I was thinking of just defining `int a;` and then using `*(a+1)` after all no statement was made that good or correct coding practices must be used – ron Aug 01 '18 at 17:37
  • now to confuse some people, replace `&a[0]` with `a`, and `&a[1]` with `a+1`, and `*(a+2) = [0]a + [1]a;` just to mess with people some more – Elias Van Ootegem Aug 01 '18 at 17:38
  • @ron That is dereferencing the value stored in a as an address is completely different. If we go there, why not use all of available RAM as a buffer and forego variables completely. No, your answer is good as-is. – Michael Dorgan Aug 01 '18 at 17:41
  • Yes. It works but I was thinking about overwrite can overwrite work? – Uttam Manher Aug 01 '18 at 18:07
  • I mean int a = a + b kinda this? – Uttam Manher Aug 01 '18 at 18:08
  • 1
    yes, in C there is `a += b` which is equivalent to `a = a + b` and that works fine and is perfectly acceptable. Now if is this some kind of school assignment for learning then okay. But trying to do this to save one variable for no other reason is bad programming... use as many variables as necessary for human readability and let the compiler do the work – ron Aug 01 '18 at 20:56
5

Technically one variable, a pointer:

#include<stdio.h>

int main() {
    int *nums = malloc(2 * sizeof(int));
    scanf("%d%d",nums, (nums + sizeof(int)));
    printf("%d",(*nums + *(nums + sizeof(int))));
    return 0;
}

But no there isn't really an elegant way to use one variable for two inputs.

agillgilla
  • 859
  • 1
  • 7
  • 22
  • 1
    *But no there isn't really an elegant way to use one variable for two inputs.* Can you prove it? – Winter Aug 01 '18 at 17:20
  • they are two objects refenced by one pointer. This is not the solution - which actually does not exist – 0___________ Aug 01 '18 at 17:26
  • @Winter I don't know if it's provable... It hinges on the definition of a variable and the entire underlying syntax of C, but I suppose you could do something where you load the first input into the upper 16 bits of the `int` and load the second into the lower 16 bits, so maybe I was wrong about there being an *elegant* way to use one variable for two inputs. But do you want to take a stab at it? – agillgilla Aug 01 '18 at 17:29
  • Look below at array example instead of bit-shifting to fake 2 16-bit variables into 1 32-bit area (which is basically an array of 16-bit values...) – Michael Dorgan Aug 01 '18 at 17:31
  • 1
    @P__J__ The question said one *variable*, not one *object/memory location*. :) – agillgilla Aug 01 '18 at 17:32
  • Still, cf my answer: a single variable can be a struct with 2 int fields, surely... probably a cleaner way to achieve the same goal – Elias Van Ootegem Aug 01 '18 at 17:45
  • 3
    Code is broke. Certinaly `scanf("%d%d",nums, (nums + sizeof(int)));` should be `scanf("%d%d",nums, nums + 1);` (pointer math) – chux - Reinstate Monica Aug 01 '18 at 18:24
5

Note that I've considered the question like a challenge or a puzzle. Do not consider this answer good C practice. Obviously the cleanest way to make a sum of 2 values from input is to use 2 variables. I still find the challenge interesting though.

#include <stdio.h>
#include <math.h>

int main()
{
    int a;
    printf("%g", fmin((scanf("%d", &a), a), 1.0/0.0 + rand()) + fmin((scanf("%d", &a), a), 1.0/0.0 + rand()));
    return 0;
}

Works with negative values.

I'm using the comma operator which executes both expressions but only return the second one. So (scanf("%d", &a), a) is like calling scanf("%d", &a) and returns a. I pass this result through a function (any function) as I want to prevent updating the value (to sum it with the new a). I have no idea if your compiler will call the left or right part of the big expression first but it doesn't matter as both are doing the same thing. Whichever executes first will be the first value from input.

fmin(x, 1.0/0.0 + rand()) makes sure nothing is inlined by the compiler. 1.0/0.0 is Infinity and would never be returned in fmin() in our case. Compiler would inline this to x normally but adding + rand() to Infinity (which is still Infinity) seems to prevent it.

You can even do it by declaring "0" variable by using argc:

#include <stdio.h>
#include <math.h>

int main(int a)
{
    printf("%g", fmin((scanf("%d", &a), a), 1.0/0.0 + rand()) + fmin((scanf("%d", &a), a), 1.0/0.0 + rand()));
    return 0;
}

I've used this to test: https://www.onlinegdb.com/online_c_compiler

Winter
  • 3,894
  • 7
  • 24
  • 56
  • Hmmmm... Technically you used *three* variables, the one in the stack in the `main()` call and the two that are allocated on the stack for the two `same` calls. Just because you named the variable `int a` in the `same()` function doesn't make it the same variable... – agillgilla Aug 01 '18 at 17:31
  • 1
    the comma is pretty good here, I wonder if you can do it without `same` – Grady Player Aug 01 '18 at 17:32
  • @agillgilla I'm trying to find a function to replace my "same". Floor doesn't seem to work. I'm not responsible for the variables in the function I call right? Otherwise variables in printf and scanf would count – Winter Aug 01 '18 at 17:32
  • 1
    I agree with Winter; he declared a single variable. – linuxfan says Reinstate Monica Aug 01 '18 at 17:33
  • Honestly I think this is a wild goose chase. Either way we're going to have to store two numbers in memory and add them together, so it is just if you want to *technically* call it one variable or not. **This is more a question of what the definition of a variable is.** – agillgilla Aug 01 '18 at 17:34
  • The definition of a variable declaration is like "int a"; then, every trick can be done I think. – linuxfan says Reinstate Monica Aug 01 '18 at 17:35
  • 1
    nice use of sequence points, although the code looks like it's capable of making people incredibly angry – Elias Van Ootegem Aug 01 '18 at 17:40
  • what if we want 50 adds? Not very and I am not sure if it is not an UB – 0___________ Aug 01 '18 at 17:54
  • @P__J__ I don't get what you mean by "50 adds", OP is asking to sum 2 values from input with a single variable. There's no reason for UB to happen here, is it? – Winter Aug 01 '18 at 17:55
  • and math to archive this - not elegant – 0___________ Aug 01 '18 at 17:55
  • Your sollution does not work with the negative numbers - so it just do not work – 0___________ Aug 01 '18 at 18:04
  • Indeed because of the square root, will try to find a better function. – Winter Aug 01 '18 at 18:05
  • `sqrt(pow((scanf("%d", &a), a), 2)` will have precision issues for large values like 2^27 or more. – chux - Reinstate Monica Aug 01 '18 at 18:07
  • @Winter Why not use `printf("%d", (scanf("%d", &a), a) + (scanf("%d", &a), a);`? If this does not work, then neither will `(int)(sqrt(pow((scanf("%d", &a), a), 2)) + sqrt(pow((scanf("%d", &a), a), 2)))` – chux - Reinstate Monica Aug 01 '18 at 18:10
  • The problem is if someone will ask I want to add 100 numbers using one variable. – 0___________ Aug 01 '18 at 18:11
  • @chux I think the function call is prioritised over the rest making scanf's be called before the rest. At least that's what I understood by experimenting with it. – Winter Aug 01 '18 at 18:12
  • I don't get why tan(atan(x)) doesn't work though. It might have something to do with constexpr functions – Winter Aug 01 '18 at 18:13
  • Hmm, looks like 2 variables to me. `main::a, same::a`. – chux - Reinstate Monica Aug 01 '18 at 18:27
  • @chux How about now? Can you check what's the double floating point limitation with this? – Winter Aug 01 '18 at 18:30
  • `fmin(x, NAN)` is not specified by C to return `x`. It is specified by the IEEE though. Perhaps `unsigned a; .... fabs((scanf("%d", &a), a))`? – chux - Reinstate Monica Aug 01 '18 at 18:35
  • @chux https://www.nongnu.org/avr-libc/user-manual/group__avr__math.html Was this reference bad? Anything involding abs wouldn't work for negative values. I could input positive infinity too, that's not a problem. – Winter Aug 01 '18 at 18:36
  • @Winter 1) [Standard C library for AVR-GCC](https://www.nongnu.org/avr-libc/user-manual/group__avr__math.html#ga577eee92b9969942de4d8d134d37c7b8) is not the Standard C library specification with does not specify the result of `fmin(x, NAN)`. 2) What negative values do you speak of with `unsigned a;`? IAC, OP did not specify range numeric range of the one variable. – chux - Reinstate Monica Aug 01 '18 at 18:41
  • @chux Changed it for infinity then. Oh I see what you meant. It's quite brillant to do the fabs() on the unsigned but then print the unsigned as signed. I'm not the one who came with the idea though :) – Winter Aug 01 '18 at 18:44
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/177220/discussion-between-chux-and-winter). – chux - Reinstate Monica Aug 01 '18 at 18:46
5

Adding Two numbers with using only one variable in C

Create a helper function with the 1 variable.

#include <stdio.h>

int scan_int(void) {
  int a;
  if (scanf("%d", &a) == 1) {
    return a;
  }
  return 0;
}

int main(void) {
  printf("Sum %d\n", scan_int() + scan_int());
  return 0;
}

Note that scan_int() + scan_int(), code could call either the left or the right scan_int() first (or in parallel). Fortunately + is commutative, so it makes no difference here.

The "trick" here is that there exist in sequence or in parallel, a 1st_call_scan_int::a and 2nd_call_scan_int::a. Still only one variable in code.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
2

OK, there's been quite a few interesting answers, but weirdly nobody has thought of the obvious way to store 2 ints in a single variable - structs:

#include<stdio.h>

typedef _in struct {
    a int
    b int
} inp;

int main(void)
{
    inp input;
    scanf("%d%d",&input.a,&input.b);
    printf("%d",input.a+input.b);
    return 0;
}
Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
1

One way to do it is.

#include <stdio.h>
int x;

int enter(){
scanf("%d",&x);
return x;
}     

int main()
{
    x=enter()+enter();
    print("sum of two number is %d",x);
    return 0;
}

Another way to do it..

#include <stdio.h>
int main()
{ 
int x;
scanf("%d",&x);
printf("next no. ");
 x= x*(scanf("%d",&x))+x;
printf("%d",x);
return 0;
}

Although the second one is not consistent, in some compiler it works perfectly and in some, it doesn't

Ankush Rawat
  • 311
  • 2
  • 11
  • Another way to do it is just create x as global variable, now create funtion to input the value and return the assigned value, then make x= function + function Will solve it – Ankush Rawat Aug 01 '18 at 18:11
  • 2
    As there is no sequence point between `x*(scanf("%d",&x))` and `x` in the addition, code does not insure the `+ x` happens with the first or second value of `x`. Thus not certain to properly generate the sum. – chux - Reinstate Monica Aug 01 '18 at 18:21
  • 2
    Doesn't work for me, it gives me the double of the second input using this online compiler https://www.onlinegdb.com/online_c_compiler – Winter Aug 01 '18 at 18:35
  • C compiler executes from right to left so I think that already solved what you said @chux – Ankush Rawat Aug 02 '18 at 01:57
  • @winter that is the case if you change the order in which I wrote the code, I just tried it in the online compiler and again it's working fine, try to copy paste my code – Ankush Rawat Aug 02 '18 at 02:27
  • 2
    @AnkushRawat "C compiler executes from right to left" may be so with the compiler and options you use, yet that is not required by the C spec. There are various things that determine what must evaluate first (sequence points) and what may evaluate first. With `x*(scanf("%d",&x))+x`, a compliant C compilation may access the 3 `x`'s in an order that fails to provide the desired functionality. – chux - Reinstate Monica Aug 02 '18 at 03:30
  • 2
    @chux is correct: the result of this code is undefined by the C standard. Therefore, it could crash, print the complete works of Shakespeare, or fail to terminate, and be compliant with the standard. Avoid code like this in real work. Avoid it like the plague. Google "C sequence points" and learn something very valuable! – Jeff Learman Aug 03 '18 at 18:13
1
int main(void) {
    int *num = malloc(sizeof(int)*2);
    scanf("%d %d", num, num+1);
    printf("%d\n", num[0] + (num[1]));
}
  • int *num = malloc(sizeof(int)*2); //two int space
  • scanf("%d %d", num, num+1); // num (pos 0), num+1 (pos1)
  • printf("%d\n", num[0] + (num[1])); //the sum of the positions
maryf
  • 140
  • 6
1

Only one variable - no tricks. As many numbers can be added as you want :)

#include <stdio.h>

int ScanAndAdd(void)
{
    int a;
    if(scanf("%d", &a) != 1) return 0;
    return a + ScanAndAdd();
}

int main()
{
    printf("%d\n", ScanAndAdd());

    return 0;  /**/
}
0___________
  • 60,014
  • 4
  • 34
  • 74
0
#include <stdio.h>
int main()
{
    long long int buffer=0;
    scanf("%d",(int*)&buffer);
    scanf("%d",(int *)&buffer+1);
    printf("\nsum is %d\n",*((int*)&buffer)+*((int*)&buffer+1));
    return 0;
}
0

Try this on for size. It uses fixed width C99 types to guarantee that memory alignment works as intended. It even does the 32-bit arithmetic in a uint64_t type to prevent overflow issues. This will work with any of the other fixed-width integer types, signed or unsigned, with trivial modification.

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

int main (void)
{
    uint64_t a;

    scanf ("%" SCNu32 "%" SCNu32, (uint32_t*)&a, (uint32_t*)&a + 1);

    printf ("%" PRIu64 "\n", (uint64_t)((uint32_t*)&a)[0] +
        ((uint32_t*)&a)[1]);
}

The above code was modified from my original answer, seen below. I removed the void* cast in (uint32_t*)(void*)&a because it was unnecessary. I also cleaned up the scanf arguments to increase readability, and added a new line to the end of the printf format argument.

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

int main (void)
{
    uint64_t a;

    scanf ("%" SCNu32 "%" SCNu32,
        &((uint32_t*)(void*)&a)[0], &((uint32_t*)(void*)&a)[1]);

    printf ("%" PRIu64, (uint64_t)((uint32_t*)(void*)&a)[0] +
        ((uint32_t*)(void*)&a)[1]);
}
Grant Sanders
  • 337
  • 1
  • 8
  • The 4 `void*` casts are not necessary here. `(uint32_t*)(void*)&a` can use `(uint32_t*)&a`. – chux - Reinstate Monica Aug 03 '18 at 04:04
  • The `void*` casts are not necessary, but it fixes a warning certain compilers and linters give when casting between different types of pointers. I don't like warnings. I will edit my answer to make my reasoning clear. – Grant Sanders Aug 03 '18 at 16:29
  • Hmmm, Do you have an example of your code the causes that warning posted? I would not expect a linter to warn here with `uint64_t a; ... (uint32_t*)&a`. – chux - Reinstate Monica Aug 03 '18 at 16:32
  • It seems I was mistaken. I couldn't find a compiler or linter which complained about `uint64_t a; ... (uint32_t*)&a`. The reason I thought they were necessary to silence a warning is that GCC warns about possible alignment issues when `-Wcast-align` is enabled and the casted-to type has a larger memory alignment requirement than the casted-from type. For example, `uint32_t foo; ... (uint64_t*)&foo` causes GCC to complain about alignment (if `-Wcast-align` is on), but `uint64_t foo; ... (uint32_t*)&foo` does not. I have added to my answer the code with this and other minor adjustments. – Grant Sanders Aug 03 '18 at 23:59