2012-06-28 8 views
19

У меня есть этот код, который делает трюк:Добавление двух чисел без использования +

#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; 
} 

Может кто-то пожалуйста объяснить, что происходит в коде?

p = (char*)a; 
sum = (int)&p[b]; // adding a & b 
+0

Похоже побитовой операции. Вы можете быстро взглянуть на http://www.cprogramming.com/tutorial/bitwise_operators.html для получения дополнительной информации. –

+7

Простите, но это совсем не поразрядно. Код изобрел, но вы поймете это, если немного почитаете в Арифметике указателей (особенно в операторе []). Если вы собираетесь программировать на C, это определенно будет стоить ваше время. –

+0

См. Также: [Как добавить два номера без оператора +?] (Http://stackoverflow.com/questions/4679556/how-do-i-add-two-numbers-without-the-operator) – Mysticial

ответ

22

Я думаю, что стоит добавить к другому ответы на быстрое объяснение указателей, массивов и мест памяти в c.

Во-первых массивов в C только блок памяти, достаточно большой, чтобы держать количество элементов в массиве (см http://www.cplusplus.com/doc/tutorial/arrays/)

так, если мы сказали

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

Предполагая ИНТ 32 бита мы будет иметь блок памяти 5 * 32 бит = 160 бит. Поскольку C - язык низкого уровня, он пытается быть настолько эффективным, насколько это возможно, поэтому сохраняет наименьшее количество информации о массивах, насколько это возможно, в этом случае наименьшее возможное количество - это адрес памяти первого элемента. Таким образом, тип примера может быть выражен как

int *example; 

Или пример указывает на int. Чтобы получить элементы в массиве, вы затем добавляете правильный номер в адрес, хранящийся в примере, и читаете номер на этом адресе памяти. Если мы предположили вид памяти как

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

Так

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

может быть выражено как

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; 

SizeOf (INT) является 4 (интермедиат 32 бита или 4 * 8 бит байтов). Если вы пытаетесь сделать добавление, вам нужен символ, который имеет 8 бит или 1 * 8 бит байтов.

Так назад к вам код

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. 

Так сумма присваивается адрес 21-го элемента массива.

Long winded информация.

+0

+ 1'd для наивысшего уровня детализации и четкости в вашем ответе! Благодаря ! – insane

6

p [b] возвращает b-й элемент массива p, что эквивалентно * (p + b). & p [b] равно p + b * sizeof (char), который преобразуется обратно в int.

+0

«times sizeof (char)» - это то, что FatalError означает «коэффициент масштабирования». –

+0

спасибо за ваш ответ, действительно выяснили, почему фактор масштабирования важен, как указано FatalError. – insane

37

&p[b] в основном сахар для:

&*(p + b) 

В * и & операторы обратные операции здесь и отменить, оставив просто p + b. Броски просто обходят проверку типа C. Дело в том, что указатель char *- signficant, однако; C, а с sizeof(char) == 1 по определению коэффициент масштабирования равен 1.

+0

Отлично! Спасибо, FatalError! – insane

+0

Это быстрее, чем 'sum = a + b'? – Jack

+0

@Jack его нет, '& p [b]' переводится на '& * (p + b)' во время компиляции. –

0

Если вопрос «сложения двух чисел без оператора +», вот один:

#include <stdio.h> 

int main() 
{ 
int a=5, b=7; 
int a1=a, b1=b; 
int res; 

res = (++a1 * ++b1) - (a * b) -1; 

printf("a1=%d b1=%d res=%d\n", a1, b1, res); 
return 0; 
} 
+11

Ничто не сравнится с "a - (-b)" –

Смежные вопросы