2012-06-28 21 views
19

tôi có mã này mà hiện các trick:Thêm hai số mà không sử dụng +

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

Ai đó có thể xin giải thích những gì đang xảy ra trong các mã?

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

Trông giống như một hoạt động trên bit. Bạn có thể xem nhanh http://www.cprogramming.com/tutorial/bitwise_operators.html để biết thêm thông tin –

+7

Xin lỗi, nhưng điều này không hề chút nào. Mã IS được giả tạo, nhưng bạn sẽ hiểu nó nếu bạn đọc một chút về số học con trỏ (đặc biệt là toán tử []). Nếu bạn đang đi để chương trình trong C, điều này chắc chắn sẽ có giá trị trong khi của bạn. –

+0

Xem thêm: [Làm cách nào để thêm hai số không có toán tử +?] (Http://stackoverflow.com/questions/4679556/how-do-i-add-two-numbers-without-the-operator) – Mysticial

Trả lời

22

Tôi nghĩ rằng nó là giá trị thêm vào các câu trả lời khác giải thích nhanh về con trỏ, mảng và vị trí bộ nhớ trong c.

Thứ nhất mảng trong c chỉ là một khối bộ nhớ đủ lớn để chứa số lượng các mục trong mảng (xem http://www.cplusplus.com/doc/tutorial/arrays/)

vì vậy nếu chúng tôi đã nói

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

Giả sử int là 32 bit chúng tôi sẽ có một khối bộ nhớ 5 * 32bits = 160bits dài. Vì C là một ngôn ngữ cấp thấp nó cố gắng hiệu quả nhất có thể, nên lưu trữ ít nhất thông tin về mảng càng tốt, trong trường hợp này số tiền ít nhất có thể là địa chỉ bộ nhớ của phần tử đầu tiên. Vì vậy, loại ví dụ có thể được thể hiện là

int *example; 

Hoặc các điểm mẫu cho một int. Để lấy các mục trong mảng, bạn thêm số chính xác vào địa chỉ được lưu trữ trong ví dụ và đọc số ở địa chỉ bộ nhớ đó. Nếu chúng ta giả định bộ nhớ nhìn như

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

Vì vậy

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

có thể được diễn tả như

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; 

Các sizeof (int) là 4 (int là 32 bit, hoặc 4 * 8 bit byte). Nếu bạn đang cố gắng làm thêm, bạn sẽ muốn có một char là 8 bit hoặc 1 * 8 bit byte.

Vì vậy, trở lại bạn mã

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. 

Vì vậy, số tiền được gán địa chỉ của phần tử thứ 21 của mảng.

Giải thích kéo dài.

+0

+1 cho mức độ chi tiết và rõ ràng nhất trong câu trả lời của bạn! Cảm ơn ! – insane

6

p [b] trả về phần tử thứ b của mảng p, tương đương với * (p + b). & p [b] bằng p + b * sizeof (char) được chuyển đổi thành int.

+0

"thời gian sizeof (char)" một phần là chính xác những gì FatalError có nghĩa là với "yếu tố mở rộng quy mô". –

+0

cảm ơn vì câu trả lời của bạn đã thực sự làm sáng tỏ thực tế tại sao yếu tố mở rộng lại quan trọng như được tuyên bố bởi FatalError. – insane

37

&p[b] về cơ bản là đường cho:

&*(p + b) 

Các *& nhà khai thác đang hoạt động nghịch đảo ở đây và huỷ bỏ, để lại chỉ đơn giản là p + b. Các phôi chỉ phá vỡ kiểm tra kiểu của C. Thực tế là con trỏ char * được sử dụng đáng kể, tuy nhiên; C cân bằng con trỏ số học, và kể từ sizeof(char) == 1 theo định nghĩa, hệ số chia tỷ lệ là 1.

+0

Hoàn hảo! Cảm ơn một tấn, FatalError! – insane

+0

Nó nhanh hơn 'sum = a + b'? – Jack

+0

@Jack nó không phải là, '& p [b]' được dịch sang '& * (p + b)' trong quá trình biên dịch. –

0

Nếu câu hỏi được "thêm hai số mà không cần các nhà điều hành +", đây là một trong:

#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

Không có gì đánh bại "a - (-b)" –

Các vấn đề liên quan