Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding two numbers without using +

Tags:

c

pointers

I have this code which does the trick:

#include <stdio.h>
int main()
{
    int a = 30000, b = 20,sum;
    char *p;
    p=(char *)a;
    sum = (int)&p[b]; // adding a & b
    printf("%d",sum);
    return 0;
}

Can someone please explain what is happening in the code?

p = (char*)a;
sum = (int)&p[b]; // adding a & b
like image 519
insane Avatar asked Jun 28 '12 12:06

insane


2 Answers

&p[b] is basically sugar for:

&*(p + b)

The * and & operators are inverse operations here and cancel, leaving simply p + b. The casts just circumvent C's type checking. The fact that a char * pointer is used is signficant, however; C scales pointer arithmetic, and since sizeof(char) == 1 by definition, the scaling factor is 1.

like image 153
FatalError Avatar answered Oct 20 '22 22:10

FatalError


I think it is worth adding to the other answers a quick explanation of pointers, arrays and memory locations in c.

Firstly arrays in c are just a block of memory big enough to hold the number of items in the array (see http://www.cplusplus.com/doc/tutorial/arrays/)

so if we said

int[5] example;
example[0] = 1;
example[1] = 2;
example[2] = 3;
example[3] = 4;
example[4] = 5;

Assuming int is 32 bits we would have a block of memory 5*32bits = 160bits long. As C is a low level language it tries to be as efficient as possible, therefor stores the least amount of information about arrays as possible, in this case the least amount possible is the memory address of the first element. So the type of example could be expressed as

int *example;

Or example points to an int. To get the items in the array you then add the correct number to the address stored in example and read the number at that memory address. If we assumed memory look like

Memory Address = Value (ints take up 4 bytes of space)
          1000 = 1          <-- example
          1004 = 2   
          1008 = 3   
          1012 = 4   
          1016 = 5

So

int i = example[3];  //The 4th element

could be expressed as

int i = *(example + 3 * sizeof(int));
int i = *(example + 3 * 4);
int i = *(1000 + 12);
int i = *(1012); // Fetch the value at memory location 1012
int i = 4;

The sizeof(int) is 4 (int is 32 bits, or 4 * 8 bit bytes). If you where trying to do addition you would want a char which is 8 bits or 1 * 8 bit bytes.

So back to you code

char* p;       // declare p as a pointer to a char/
p = (char *)a; // point p at memory location 3000
// p[b] would be the 21st element of the "array" p =>
// p[20]  =>
// p + 20 * sizeof(char) =>
// p + 20 * 1 =>
// p + 20  =>
// 3000 + 20 =>
// 3020
// the & operator in c gets the address of the variable so
sum = (int) &p[b]; 
// &p[b] => find the address pointed to by p[b] => 3020
// (int) casts this pointer to a int.

So sum is assigned the address of the 21st element of the array.

Long winded explanation.

like image 38
David Waters Avatar answered Oct 21 '22 00:10

David Waters