Là tôi, j = 1 thực sự sai lệch? [đóng cửa]


11

Có một đối số phổ biến về khởi tạo nhiều biến trong một lớp lót, đó là:

Xem xét ví dụ int i, j = 1; điều này có thể khiến một số người lầm tưởng cả hai biến đang được khởi tạo

Chúng ta có thể lập luận rằng ai đó nên biết đủ cú pháp ngôn ngữ của mình để không nhầm lẫn về điều đó. Một lập luận khác có thể là các nhà phát triển chúng ta học rất nhiều ngôn ngữ, chúng ta có thể mắc lỗi giữa các đặc thù giữa các ngôn ngữ.

Tuy nhiên, đối với trường hợp rất cụ thể đó, tôi tự hỏi những điều sau đây có tồn tại một ngôn ngữ trong đó cú pháp i, j = 1 khởi tạo cả hai biến không?

Nếu không tranh luận thì không áp dụng.


2
Nếu ngôn ngữ của bạn lành mạnh, sự nhầm lẫn tiềm ẩn là vô hại vì việc truy cập vào một biến chưa được khởi tạo sẽ gây ra lỗi trình biên dịch.
CodeInChaos

4
@CodesInChaos bạn đang nói C không lành mạnh?
Baldrickk

2
Chỉ vì một ngôn ngữ cho phép thứ gì đó không có nghĩa là bạn không khiến con người đau đớn không cần thiết. Nơi duy nhất mã này được gọi là trong các câu đố được thiết kế để trừng phạt những người không ghi nhớ đặc tả ngôn ngữ. Tôi luôn thất bại những loại câu hỏi. Thôi nào.
candied_orange

2
Trong Visual Basic 6 Dim Apple, Orange, Pear as Fruitlà một tuyên bố pháp lý. Giả sử bạn không biết VB. Là ấn tượng đầu tiên của bạn Applelà loại Fruit? Không phải vậy. Hãy nhớ rằng, ngôn ngữ thường được đọc bởi những người không phải là chuyên gia về ngôn ngữ đó; nếu bạn là một chuyên gia, hãy sử dụng ngôn ngữ một cách khôn ngoan để truyền đạt ý định của bạn một cách rõ ràng ngay cả với những người không phải là chuyên gia. Tôi không bao giờ sử dụng nhiều khởi tạo trong bất kỳ ngôn ngữ.
Eric Lippert

13
Tương tự: xem xét var x = 1, y = 1.5; Đây có giống int x = 1; double y = 1.5;hoặc là giống như double x = 1, y = 1.5;? Khi chúng tôi thêm varvào C # 3.0, tôi đã thực hiện một cuộc thăm dò và phát hiện ra rằng khoảng một nửa số người tin rằng điều đầu tiên là "rõ ràng" và nửa còn lại tin rằng người kia là "rõ ràng", và vì vậy chúng tôi đã biến nó thành bất hợp pháp. Một tính năng đánh lừa hoàn toàn một nửa dân số là một tính năng xấu.
Eric Lippert

Câu trả lời:


37

Tôi nghĩ là không, nhưng đó không phải là vấn đề. Điểm có ích là i, j = 0rất dễ dàng nhầm lẫn với i = j = 0, mà không khởi tạo cả hai. Sự rõ ràng là yêu cầu quan trọng nhất đối với mã nguồn bên cạnh tính chính xác và thực tế là câu hỏi này thậm chí còn phát sinh chứng tỏ rằng sự rõ ràng là không tối ưu.


3
Tôi cũng sẽ lập luận rằng nếu một tuyên bố như vậy không khởi tạo cả hai tuyên bố, tại sao nó thậm chí còn tồn tại?
Berin Loritsch

2
@BerinLoritsch phụ thuộc vào ngôn ngữ. Điều này thường được thực hiện trong JavaScript vì tích trữ khai báo: được nhiều người coi là cách thực hành tốt nhất để khai báo các biến ở đầu phạm vi mà chúng có sẵn ngay cả khi bạn không khởi tạo chúng cho đến khi chúng được sử dụng trong mã . Hầu như tất cả các công cụ chuyển đổi mã đầu ra theo cách này.
Jared Smith

1
Tôi cho rằng đó là một điều nếu một công cụ đầu ra mã đã làm điều này, vì điều đó được cho là đáng tin cậy. Tuy nhiên, đối với con người, tôi khuyên bạn nên chống lại việc kết hợp khai báo và khởi tạo phần tử cuối cùng chỉ trên một dòng. Nó chỉ giống như một lỗi đang chờ để xảy ra.
Berin Loritsch

2
@JaredSmith Bên cạnh Maple, tôi không thể nghĩ ra một ngôn ngữ mà điều này hiện đang mong muốn, thậm chí C bây giờ thích gần hơn với phạm vi (như C ++ và hầu hết các ngôn ngữ khác với trình biên dịch tĩnh một nửa) vì nó mang lại lợi ích ngăn chặn các lỗi tiềm ẩn và cho phép trình biên dịch để quyết định phải làm gì với biến miễn là chức năng không thay đổi, có khả năng cho phép tối ưu hóa tốt hơn nếu bạn có thể thoát khỏi số lượng đăng ký ít hơn.
whn

6
Bất kể ngôn ngữ nào, người ta nên hỏi " lợi ích của việc viết int i, j=1so với int i; int j = 1(hoặc thậm chí tốt hơn, các dòng riêng biệt) là gì?"
chepner

2

Tôi nghĩ rằng, bạn có thể tranh luận cho cả hai bên:

  • Kontra i, j = 0:
    Các nhà toán học sử dụng điều này có nghĩa là cả hai ijđược cho là bằng không.

  • Pro i, j = 0:
    Đây là một vấn đề đơn giản để biết sự ưu tiên của các nhà khai thác của bạn. Và nếu bạn nghi ngờ về sự ưu tiên của họ, bây giờ là thời gian để tìm kiếm nó.

    Đó là cùng một lý do tại sao chúng ta viết những thứ như a.b += c[i]*d[i];không có dấu ngoặc đơn. Tất nhiên điều này tương đương với (a.b) += ((c[i])*(d[i]));, nhưng các lập trình viên có thể mong đợi biết được quyền ưu tiên của các toán tử được sử dụng nhiều nhất và có thể tìm kiếm quyền ưu tiên của các toán tử khi họ không chắc chắn. Do đó, dấu ngoặc đơn thường được coi là sự lộn xộn vô dụng trừ khi chúng buộc một thứ tự đánh giá khác với quyền ưu tiên của nhà điều hành sẽ quy định.

    Tất nhiên, có những trường hợp ngoại lệ. Ưu tiên <<+thường được coi là đủ mơ hồ để bảo đảm dấu ngoặc đơn trong cả hai trường hợp. Nhưng đó là ngoại lệ chứng minh quy tắc.

Tôi, đối với một người, sẽ rơi nhiều hơn vào phía Pro, nhưng tôi đã sẵn sàng để dính vào bất kỳ phong cách nào cấm các tuyên bố đó. Đó không phải là vấn đề đáng để tranh cãi.


7
Tôi lưu ý rằng int i, j = 0;không có nhà khai thác trong đó. Biểu thức duy nhất trong câu lệnh đó là 0và do đó, quyền ưu tiên của toán tử không đi vào nó. Trình phân tích cú pháp không coi ,là toán tử dấu phẩy hoặc =toán tử gán; đúng hơn, đây là những phần ngữ pháp của tuyên bố.
Eric Lippert

@EricLippert Theo như các quy tắc ưu tiên, sự khác biệt đó là không liên quan: Bất kỳ ngôn ngữ kiểu C nào tôi biết đều sử dụng các ưu tiên tương tự trong một khai báo như trong các biểu thức khác. Bất cứ điều gì khác sẽ mời desaster.
cmaster - phục hồi monica

but programmers can be expected to know the precedence of the most used operators by heart, bạn nói. Trong ví dụ bạn đưa ra, tôi không chắc chắn hầu hết các lập trình viên (trung bình) quan niệm toán tử truy cập thành viên hoặc toán tử chỉ số mảng là toán tử theo nghĩa toán học, nhưng thay vào đó nghĩ về chúng nhiều hơn như danh từ ngôn ngữ tự nhiên và phép nhân toán tử như động từ. Đó là lý do tại sao int i, j, k = 0;một cấu trúc quái gở như vậy, bởi vì nó thể hiện dưới dạng tương tự ngôn ngữ tự nhiên của "int biến i, j và k, được khai báo và sẽ được đặt thành 0"!
Steve

@Steve Làm thế nào bạn nhớ các quy tắc ưu tiên như một lập trình viên, hoàn toàn phụ thuộc vào bạn. Nếu nó giúp bạn nghĩ về chúng như danh từ của ngôn ngữ, hãy làm nó. Tuy nhiên, trong trường hợp đó bạn sẽ gặp vấn đề khi bạn thấy những thứ như thế *a[i], tôi không nghĩ bạn có thể phân tích đầy đủ điều đó với sự tương tự "danh từ". Đối với int i, j, k = 0;, điều đó có thể có nghĩa là bất cứ điều gì nếu bạn không tra cứu các quy tắc: Giải thích thứ ba sẽ là khai báo int i, sau đó đánh giá jvà cuối cùng là gán k = 0. Trừ khi bạn biết cú pháp ngôn ngữ của mình, bạn không thể phân tích các cấu trúc đó. Đó là vấn đề của bạn nếu bạn vẫn làm.
cmaster - phục hồi monica

@cmaster, tôi đã không thể hiện chiến lược ghi nhớ cụ thể của mình haha. Tôi không phải là lập trình viên C nên sự quen thuộc của tôi với ưu tiên toán tử trong C là hạng hai. Nhưng điều tôi lưu ý khi xem ví dụ của bạn là tôi thậm chí không nghĩ toán tử nhân là có một ưu tiên tương đối với toán tử chỉ mục mảng. Đó là, tôi đã không đọc a[i]như là một toán tử chỉ mục được áp dụng cho a, mà là đọc cả hai như là một yếu tố cú pháp không thể sửa đổi chỉ định toán hạng của toán tử nhân, và do đó tôi thậm chí không được nhắc để đánh giá mức độ ưu tiên. (1/2)
Steve
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.