Có chức năng hoán đổi tích hợp nào trong C hoạt động mà không sử dụng biến thứ ba không?Có tích hợp chức năng hoán đổi trong C không?
Trả lời
số
C++ có nhưng nó hoạt động như c = a;a = b; b = c;
C++ được xây dựng trong chức năng trao đổi: swap(first,second);
Kiểm tra này: http://www.cplusplus.com/reference/algorithm/swap/
Bạn có thể sử dụng để trao đổi hai giá trị biến mà không sử dụng biến thứ ba:
a=a^b;
b=a^b;
a=b^a;
Bạn cũng có thể kiểm tra điều này:
Không có chức năng như trong tiêu chuẩn C.
(Trong C++ thì bạn phải std::swap()
.)
Có lẽ một macro từ this question có thể hữu ích cho bạn.
nói riêng, hãy nhìn vào http://stackoverflow.com/a/3983089/48015 – Christoph
Tại sao bạn không muốn sử dụng biến thứ ba? Đó là cách nhanh nhất trên phần lớn các kiến trúc.
Các XOR swap algorithm công trình mà không có một biến thứ ba, nhưng nó là vấn đề theo hai cách:
- Các biến phải phân biệt ví dụ:
swap(&a, &a)
sẽ không hoạt động. - Nói chung sẽ chậm hơn.
Đôi khi nên sử dụng chuyển đổi XOR nếu sử dụng biến thứ ba sẽ làm cho ngăn xếp tràn, nhưng nhìn chung bạn không ở vị trí đó để thực hiện cuộc gọi đó.
Để trả lời câu hỏi của bạn trực tiếp, không có hàm hoán đổi nào trong tiêu chuẩn C, mặc dù nó sẽ không quan trọng để viết.
lập trình gì trên không? –
@delnan: Tôi không cố gắng cho rằng hiệu suất là quan trọng. Tất cả những gì tôi nói là không có lý do (bao gồm cả hiệu năng) không muốn biến thứ ba. –
@delnan: 'int t = a; a = b; b = t; 'v.s. 'a^= b; b^= a; a^= b; '. Thời gian lãng phí này ở đâu? Và đó là những gì vũ trụ đang viết một trao đổi đáng kể góp phần vào thời gian nó sẽ đưa bạn để giải quyết một vấn đề? Đây phải là vấn đề lớn nhất mà tôi chưa từng thấy. –
có std::swap
vì nói chung nó phụ thuộc vào bộ xử lý của bạn, cho dù nó có hỗ trợ tạo hình hay không. có một hướng dẫn được gọi là "so sánh và trao đổi", nhưng nó chỉ hoạt động trên các loại phù hợp với một thanh ghi và được đảm bảo là nguyên tử. Có một triển khai thực hiện so sánh và hoán đổi (CAS) từ gcc nó được sử dụng để đồng bộ hóa việc triển khai luồng và mutex và có lẽ cách ngoài phạm vi cho mục đích của bạn, vì vậy tốt nhất là chỉ sử dụng biến tạm thời hoặc nếu bạn thực sự bị mắc kẹt với C bạn luôn có thể sử dụng một macro như thế này:
#define swap(a,b) a=a^b; \
b=a^b; \
a=b^a;
Giả sử bạn muốn có một C solotion , không phải là C++ một, bạn có thể biến nó thành macro, ít nhất bằng cách sử dụng phần mở rộng GCC để có nó đủ chung, e
#define SWAP(x,y) do { \
typeof(x) _x = x; \
typeof(y) _y = y; \
x = _y; \
y = _x; \
} while(0)
coi chừng các thủ thuật như lời gọi swap(t[i++],i)
; để tránh chúng, hãy sử dụng toán tử địa chỉ &
.Và bạn sẽ sử dụng tạm thời tốt hơn (cho các số nguyên, có một thủ thuật nổi tiếng và vô dụng với độc quyền hoặc).
PS: Tôi đang sử dụng hai biến cục bộ _x
và _y
(nhưng tôi chỉ có thể sử dụng một biến cục bộ) để dễ đọc hơn và cũng có thể cho phép tối ưu hóa nhiều hơn từ trình biên dịch.
Lợi ích của việc sử dụng hai biến tạm thời, thay vì chỉ là một (ví dụ: 'typeof (x) _tmp = x; x = y; y = _tmp;'? – einpoklum
Khả năng đọc tốt hơn và có lẽ dễ dàng hơn –
Không có hàm chuẩn trong C để hoán đổi hai biến.
Một vĩ mô có thể được viết theo cách này:
#define SWAP(T, a, b) do { T tmp = a; a = b; b = tmp; } while (0)
và vĩ mô có thể được gọi theo cách này:
int a = 42;
int b = 2718;
SWAP(int, a, b);
Một số giải pháp cho một văn bản macro SWAP nên tránh:
#define SWAP(a, b) do { a = b + a; b = a - b; a = a - b; } while (0)
khi toán hạng là các loại đã ký, có thể xảy ra tràn và tràn đăng nhập là hành vi không xác định.
Cũng là một giải pháp cố gắng để tối ưu hóa các giải pháp XOR như thế này nên được tránh:
#define SWAP(a, b) (a ^= b ^= a ^=b)
a
được sửa đổi hai lần giữa trước và điểm chuỗi tiếp theo, vì vậy nó vi phạm trình tự chỉ quy tắc và là hành vi không xác định .
Không phải @ BasileStarynkevitch [phiên bản] (http://stackoverflow.com/a/8862167/1593077) của macro SWAP thích hợp hơn? – einpoklum
@einpoklum: Không, bởi vì không phải mọi trình biên dịch đều là GCC, vì vậy bạn không thể dựa vào phần mở rộng GCC như 'typeof (expr)' –
Tôi đặc biệt thích sử dụng 'int' làm đối số đầu tiên của macro. Bây giờ chúng ta có thể xác nhận rằng chúng ta có các mẫu trong ngôn ngữ yêu dấu của chúng ta :-) – paxdiablo
Không có tích hợp chức năng hoán đổi nhưng bạn có thể thử này
a = a^b;
b = a^b;
a = b^a;
Vì bạn có thể sao chép bất kỳ đại diện đối tượng vào một mảng char unsigned trong C , macro sau cho phép bạn hoán đổi hai đối tượng:
#define SWAP(X,Y) \
do { \
unsigned char _buf[sizeof(*(X))]; \
memmove(_buf, (X), sizeof(_buf)); \
memmove((X), (Y), sizeof(_buf)); \
memmove((Y), _buf, sizeof(_buf)); \
} while (0)
GCC thậm chí sẽ tạo mã tối ưu cho điều này trong một số trường hợp. Bạn có thể không giữ công việc của mình mặc dù ...
* Any * hai đối tượng? Giống như ... 'int x; double y; 'chẳng hạn? :-) Có lẽ bạn có nghĩa là bất kỳ hai đối tượng _of cùng loại._ – paxdiablo
Có chức năng thư viện C++. Nó hoán đổi giá trị của hai biến số nguyên. Ví dụ, hoán đổi (x, y); sẽ hoán đổi các giá trị của biến x và y. Tương tự, trao đổi (mat [i] [j], mat [j] [i]); sẽ trao đổi hai giá trị trong ma trận mat, cụ thể là giá trị trong hàng i cột j và giá trị trong hàng j cột i.
Một chức năng thư viện C++ không phải là một hàm C, cũng không phải là nó được xây dựng trong – Chris
Tôi tin rằng tôi đã đưa ra một chức năng loại bất khả tri để hoán đổi hai giá trị trong tiêu chuẩn C, mặc dù vì tôi khá mới với ngôn ngữ mà tôi có thể đã bỏ qua điều gì đó.Nó sử dụng các thuật toán XOR trao đổi, và tôi chắc chắn rằng nó có thể được tối ưu hóa hơn, nhưng nó hoạt động miễn là hai giá trị trỏ đến cùng một số byte, quy định bởi đối số thứ 3: sử dụng
void swapn(void *a, void *b, size_t n) {
if (a == b) {
return;
}
size_t i;
char *x = (char *)a,
*y = (char *)b;
for (i = 0; i < n; i++) {
*x ^= *y;
*y ^= *x;
*x ^= *y;
x++;
y++;
}
}
Ví dụ :
// swap two integers
int x = 5,
y = 30;
printf("%d\t%d\n", x, y);
swapn(&x, &y, sizeof(int));
printf("%d\t%d\n\n", x, y);
// swap two floats
float a = 9.23f,
b = 6.83f;
printf("%.2f\t%.2f\n", a, b);
swapn(&a, &b, sizeof(float));
printf("%.2f\t%.2f\n\n", a, b);
// swap two doubles
double p = 4.7539,
q = 0.9841;
printf("%.4f\t%.4f\n", p, q);
swapn(&p, &q, sizeof(double));
printf("%.4f\t%.4f\n\n", p, q);
// swap two chars
char m = 'M',
n = 'n';
printf("%c\t%c\n", m, n);
swapn(&m, &n, sizeof(char));
printf("%c\t%c\n\n", m, n);
// swap two strings of equivalent length
char s[] = "Hello",
t[] = "World";
printf("%s\t%s\n", s, t);
swapn(s, t, sizeof(s));
printf("%s\t%s\n\n", s, t);
Đầu ra là:
5 30
30 5
9.23 6.83
6.83 9.23
4.7539 0.9841
0.9841 4.7539
M n
n M
Hello World
World Hello
Tôi khá chắc chắn ba cách xor-phân công là hành vi không xác định, kể từ nó gán cho '* x' hai lần không có điểm chuỗi ở giữa. Đó là dễ dàng cố định, nhưng tôi không thấy lý do tại sao người ta nên bận tâm với xor trao đổi anyway. Nó không nhanh hơn, nó không dễ dàng hơn, nó phá vỡ khi hai tham số bí danh, và trong việc thực hiện chung hai mươi dòng này, biến số phụ thậm chí còn không thực sự mã nhiều hơn nữa. Nhưng nó có vẻ khá loại agonistic, tôi sẽ cung cấp cho bạn điều đó. 'n' nên là' size_t'. – delnan
@delnan Tôi đã xóa hành vi không xác định và thay đổi đối số thứ 3 thành loại size_t. Bạn có ý nghĩa gì khi "bí danh hai thông số"? Tôi tin rằng nó được xử lý bởi câu lệnh if ban đầu. –
- 1. Tích phân Byte hoán đổi trong C++
- 2. Chức năng hoán đổi đơn giản ... tại sao cái này không hoán đổi?
- 3. go có tích hợp chức năng "in" không?
- 4. Tích hợp chức năng khách POP3 vào ứng dụng C#?
- 5. F #: Cách viết chức năng hoán đổi cổ điển?
- 6. Có chức năng tích hợp để lặp lại chuỗi hoặc char trong .net không?
- 7. Chức năng phân phối chuẩn tích lũy trong C/C++
- 8. có chức năng hợp nhất AutoMapper không?
- 9. Hoán đổi Endianness trong mục tiêu-C?
- 10. có chức năng băm chuỗi javascript tích hợp trong các trình duyệt mới nhất không?
- 11. Có chức năng tích hợp để băm mật khẩu trong .NET không?
- 12. Có chức năng tích hợp nào để tạo MD5 chuỗi trong JavaScript/jQuery không?
- 13. Có chức năng tích hợp nào cho các trích dẫn F # có thể đọc được không?
- 14. Chức năng tích hợp để sắp xếp các mảng trong C
- 15. Hoán đổi nguyên tử trong GNU C++
- 16. C# Chức năng ModInverse
- 17. Truy cập chức năng băm chuỗi tích hợp của Lua
- 18. Có chức năng sàn trong khung tập hợp Mongodb không?
- 19. làm cách nào để tôi thực hiện chức năng hoán đổi trong java?
- 20. GCC 4.0: "không có chức năng phù hợp để gọi" trong chức năng mẫu
- 21. Python có chức năng tích hợp cho các trình tạo/trình tự xen kẽ không?
- 22. Chức năng của iPhone SDK Objective C có hỗ trợ các chức năng bên trong các chức năng không?
- 23. Chức năng .NET được tích hợp cho các ký tự không định dạng trong luồng XML?
- 24. Di chuyển ngữ nghĩa == chức năng hoán đổi tùy chỉnh lỗi thời?
- 25. Chức năng hoán đổi nguyên tử sử dụng gcc nguyên tử dựng sẵn
- 26. C# isPowerOf chức năng
- 27. Chức năng xóa của tập hợp trong C++ có thay đổi địa chỉ của các phần tử khác không?
- 28. Có thể thay đổi chức năng repr trong python không?
- 29. Chức năng phối hợp Clojure
- 30. JVM có hoán đổi vùng heap không?
giải pháp với tổng và khác biệt cần tránh. Với các toán hạng của các kiểu đã ký, nó có thể tràn và các luồng tràn đã ký sẽ không được xác định trong C. – ouah
yap .. bạn đã đúng. cảm ơn :) – Saif