Tại sao có i ++; Tôi--; ngay sau khi nhau?


164

Tôi đã xem mã nguồn cho nmap được phát hành năm 1997 và tôi nhận thấy phần mã này có vẻ hơi kỳ lạ đối với tôi:

int i=0, j=0,start,end;
char *expr = strdup(origexpr);
ports = safe_malloc(65536 * sizeof(short));
i++;                                         /* <<<<<< */
i--;                                         /* <<<<<< */
for(;j < exlen; j++) 
  if (expr[j] != ' ') expr[i++] = expr[j]; 
expr[i] = '\0';

Tại sao bạn lại có i++;và sau đó i--;ngay sau nhau? i0, sau đó i++chuyển isang 1. Sau đó,i-- quay isang 0.

Liên kết với mã nguồn gốc.Tìm kiếm:

i++;
i--;

Bất cứ ai có thể giải thích điều này là gì?


25
Hỏi tác giả .
DaBler

8
Tôi đoán chúng là một phần của một số mã thử nghiệm hoặc gỡ lỗi mà tác giả đã quên xóa sau đó.
Nate Eldredge

6
Lý do rõ ràng là làm bạn bối rối, đó là mục đích duy nhất :-) Có một khả năng nhỏ là nó hoạt động xung quanh một số lỗi trình biên dịch trong một số trình biên dịch cổ, trong trường hợp đó nên có bình luận cho chúng tôi biết lý do này.
gnasher729

18
@ RingØ: Để giải trí, tôi đã thử nó với gcc 1.27, khoảng năm 1988, trên godbolt: godbolt.org/z/yYyFrQ . (Nó không hoạt động với các tiêu đề hệ thống hiện đại nên tôi phải tự khai báo tất cả các chức năng thư viện tiêu chuẩn.) Nhưng với -Onó thực sự tối ưu hóa các tuyên bố đó.
Nate Eldredge

21
Điều đó có nghĩa là lập trình viên đã được trả tiền theo đường dây ...
TonyK

Câu trả lời:


152

Đây là một lỗi. Những dòng này kết quả với nhau trongi không thay đổi, vì vậy chúng không nên ở đó.

Bài viết được liên kết giới thiệu nmap đã được xuất bản vào ngày 1 tháng 9 năm 1997. Nếu bạn xem kho lưu trữ SVN cho nmap tại https://svn.nmap.org/nmap , bản sửa đổi ban đầu được kiểm tra vào ngày 10 tháng 2 năm 1998 không có các dòng đó:

int i=0, j=0,start,end;
char *expr = strdup(origexpr);
char *mem = expr;

ports = safe_malloc(65536 * sizeof(short));
for(;j < exlen; j++) 
  if (expr[j] != ' ') expr[i++] = expr[j]; 
expr[i] = '\0';

Vì vậy, đây là điều mà tác giả đã tìm thấy và cố định giữa việc xuất bản mã nguồn nmap ban đầu và đăng ký ban đầu lên SVN.


1
Hmm trang đó cũng thiếu <pre>các thẻ xung quanh bài viết; Thanh tra của Chrome tiết lộ điều đó dẫn đến việc xáo trộn tài liệu trong quá trình xây dựng DOM;)
Tiểu hành tinh có cánh

4
Nó gây nhầm lẫn cho độc giả, đó là hoàn toàn ngoài ý muốn. Tôi muốn nói rằng nó rõ ràng là một lỗi. ;-)
sergut

2
@sergut Wikipedia không đồng ý với bạn, nhưng bài đăng trên blog này cũng vậy và tôi cũng có xu hướng :-)
Toivo Säwén

4
Bây giờ nếu ikhông phải là một int nhưng một số lớp ưa thích với sự quá tải của nhà điều hành, thì có thể (mặc dù không chắc và nói chung là dấu hiệu của các hoạt động mã hóa kém) rằng điều này có thể có một số tác dụng phụ. (Tất nhiên chỉ áp dụng nếu đây là C ++.)
Darrel Hoffman

5
Có lẽ đáng lưu ý rằng trong một số bối cảnh (IO ánh xạ bộ nhớ), việc thay đổi một biến có thể có tác động bên ngoài.
nullromo

40

Nó vô dụng. Nó hoàn toàn không có gì.

Nếu tôi suy đoán thì có lẽ đó là phần còn lại của một số mã gỡ lỗi đã được sử dụng trong quá trình phát triển.

Tôi đoán rằng một trong hai i++hoặci-- được giới thiệu trong một thay đổi và thay đổi khác được giới thiệu trong một thay đổi khác.

Tuy nhiên, tôi không có cách nào để tìm điểm giới thiệu, vì không có lịch sử sửa đổi giữa bản phát hành nguồn ban đầu và bản sửa đổi SVN đầu tiên.


14
Tôi nghĩ rằng suy đoán về mã gỡ lỗi là chính xác. Tôi đã thấy rất nhiều loại mã gỡ lỗi khác nhau chỉ để có được các điểm dừng mà bạn mong đợi.
Cuộc thi của Go Go

9

Đối với trình biên dịch không tối ưu hóa, hoặc trình biên dịch đã nhận ra tác dụng phụ của phần cứng, i ++; i-- trình tự sẽ khiến tôi được đọc từ bộ nhớ, sau đó viết lại, bất kể đường dẫn đi qua vòng lặp for và lồng nhau nếu.

Trong xử lý song song, đôi khi các hack trình biên dịch được thực hiện để đảm bảo chuỗi mã sử dụng các bản sao biến cục bộ của chính nó thay vì các bản sao toàn cục.

Vì ví dụ là một đoạn mã, người ta không thể xác định trình biên dịch được sử dụng, hệ điều hành / phần cứng dự kiến, cũng như liệu đây có phải là một chuỗi / chức năng mã có thể được thực thi như một luồng độc lập hay không.

Trong các hệ thống đơn giản hơn, tôi đã tạm thời buộc thay đổi các biến để thực hiện tính năng bẫy trong môi trường gỡ lỗi. Nếu đó là trường hợp, tác giả có thể đã quên xóa mã khi hoàn thành phát triển.


1
Vậy thì tại sao không tuyên bố nó là dễ bay hơi?
vsz

6
Khai báo idưới dạng một biến cục bộ được hiển thị trong đoạn mã trên, và không có cách nào nó có thể được truy cập bởi một luồng khác tại điểm có các i++; i--dòng.
interjay

@vsz Tôi nghĩ rằng anh ta ibị buộc phải không biến động. Mặc dù vậy, tôi chưa xử lý luồng trong C hoặc C ++, vì vậy tôi không biết làm thế nào nó có thể được coi là dễ bay hơi và làm thế nào i++; i--để ngăn chặn điều đó.
Egor Hans

dễ bay hơi có các mục đích khác ngoài an toàn luồng. Nó cũng có thể được sử dụng trong khi gỡ lỗi để đảm bảo trình biên dịch sẽ không tối ưu hóa nó đi.
vsz

2

Tôi sẽ đề nghị bạn chỉ kiểm tra mã cập nhật. Nếu bạn sử dụng (i = 2 + 1) ngay sau đó (i-1) mà không có ý nghĩa. Giá trị của tôi vẫn không thay đổi. Bạn có thể thử nó bằng bất kỳ trình biên dịch c hoặc c ++ nào. hoặc thậm chí trong bất kỳ ngôn ngữ khác, nó là như nhau. Chạy mã trong trình biên dịch để xem tôi sai hay đúng và cho tôi biết nếu tôi trả lời sai.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.