Việc thực hiện các dấu ngoặc góc của GCC bao gồm. Tại sao nó phải được mô tả dưới đây?


11

Tài liệu này trong phần 2.6 Bao gồm tính toán có đoạn sau:

Nếu dòng mở rộng thành luồng mã thông báo bắt đầu bằng <mã thông báo và bao gồm mã thông báo>, thì mã thông báo giữa <và đầu tiên> được kết hợp để tạo thành tên tệp được bao gồm. Bất kỳ khoảng trắng giữa các mã thông báo được giảm xuống một không gian duy nhất; sau đó bất kỳ khoảng trắng nào sau dấu <ban đầu được giữ lại, nhưng một khoảng trắng ở trước khi đóng> bị bỏ qua . CPP tìm kiếm tệp theo các quy tắc cho khung góc bao gồm.

Tôi biết đây là triển khai được xác định, nhưng tại sao nó phải theo cách này cho GCC? Tôi đang đề cập cụ thể đến câu được tô sáng ở trên.

BIÊN TẬP

Tôi vừa nhận thấy rằng đoạn thứ ba trước đoạn trích dẫn ở trên nói như sau:

Bạn phải cẩn thận khi xác định macro. #definelưu mã thông báo, không phải văn bản. Bộ tiền xử lý không có cách nào để biết rằng macro sẽ được sử dụng làm đối số #include, vì vậy nó tạo ra các mã thông thường, không phải là tên tiêu đề. Điều này không có khả năng gây ra vấn đề nếu bạn sử dụng trích dẫn kép bao gồm, gần đủ với các hằng chuỗi. Nếu bạn sử dụng dấu ngoặc góc, tuy nhiên, bạn có thể gặp rắc rối .

Có ai biết loại rắc rối nào đang được chỉ ra ở đây không?


6
Dự đoán tốt nhất là các nhà phát triển của GCC nghĩ rằng có khoảng trắng ở cuối tên tệp là một sự gớm ghiếc.
dùng3386109

1
Tên tệp có không gian hàng đầu và / hoặc dấu rất khó để sử dụng, đặc biệt là trên Windows.
Remy Lebeau

1
Chỉ vì nó đã được định nghĩa như thế, không nhất thiết có nghĩa là nó phải được định nghĩa như thế. Nó không bắt buộc theo tiêu chuẩn.
eerorika

Visual Studio loại bỏ cả không gian ban đầu và kết thúc, do đó hành xử khác nhau. HP aCC hoạt động như gcc (có lẽ vì lý do tương thích).
Slimak

Đôi khi tài liệu chỉ đơn giản mô tả những gì mã xảy ra để làm thay vì cách khác, đặc biệt là trong các trường hợp không quan trọng (bạn có thể sử dụng bất kỳ khoảng trống nào ở bất cứ đâu nếu bạn sử dụng dấu ngoặc kép).
rustyx

Câu trả lời:


9

Tôi đoán người triển khai đã chọn cách đơn giản nhất khi họ thực hiện chức năng này mà không cần suy nghĩ nhiều.

Có vẻ như việc thực hiện ban đầu đã hạ cánh vào năm 2000-07-03 (hai thập kỷ trước!). Phần có liên quan trông giống như ( nguồn ):

  for (;;)
    {
      t = cpp_get_token (pfile);
      if (t->type == CPP_GREATER || t->type == CPP_EOF)
        break;

      CPP_RESERVE (pfile, TOKEN_LEN (t));
      if (t->flags & PREV_WHITE)
        CPP_PUTC_Q (pfile, ' ');
      pfile->limit = spell_token (pfile, t, pfile->limit);
    }

Đáng chú ý, nó bùng phát khi nhìn thấy CPP_GREATERmã thông báo (tức là >), trước khi đặt bộ nhớ cho mã thông báo. Điều này có ý nghĩa, vì không cần phân bổ bộ nhớ khi mã thông báo sẽ không được ghi vào bộ đệm.

Sau đó, chỉ sau khi bộ nhớ được bảo lưu, bộ xử lý trước sẽ kiểm tra xem mã thông báo có khoảng trắng trước ( t->flags & PREV_WHITE) hay không và khi đó, ghi một ký tự khoảng trắng vào bộ đệm.

Kết quả là, < foo / bar >chỉ có các khoảng trắng trước foo(nghĩa là sau lần đầu tiên <) /, và barđược giữ lại.


Rực rỡ, câu trả lời tuyệt vời. Đây là lần đầu tiên tôi có cơ hội thấy một đoạn mã trong GCC. Cảm ơn vì điều này.
Ayrosa

Nhưng đó không phải là trường hợp điều kiện if (t->flags & PREV_WHITE) CPP_PUTC_Q (pfile, ' ');mâu thuẫn với những gì được nói trong tài liệu: "Bất kỳ khoảng trắng nào giữa các mã thông báo được giảm xuống một khoảng trống; ..."?
Ayrosa
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.