&& nghĩa là gì trong void * p = && abc;


102

Tôi đã xem qua một đoạn mã void *p = &&abc;. Ý nghĩa của việc &&này là gì? Tôi biết về tham chiếu rvalue nhưng tôi nghĩ &&được sử dụng trong ngữ cảnh này là khác nhau. Điều gì &&chỉ ra trong void *p = &&abc;?


14
Nơi mà bạn đã nhìn thấy điều này?
user541686,

3
Tôi cũng muốn biết nơi bạn đã thấy cái này.
Flavius

Câu trả lời:


154

&&là phần mở rộng của gcc để lấy địa chỉ của nhãn được xác định trong hàm hiện tại.

void *p = &&abc là bất hợp pháp trong tiêu chuẩn C99 và C ++.

Điều này biên dịch với g ++.


42
Bây giờ hãy tưởng tượng mọi người sẽ lập trình tốt hơn như thế nào nếu gcc có -pedantic theo mặc định. Sau đó, mọi người sẽ học C thay vì thông tin không liên quan về gnus.
Lundin

4
Thật là một vụ hack. Nếu họ phát minh ra một cú pháp mới cho con trỏ nhãn, họ cũng nên phát minh ra một kiểu mới cho nó thay vì sử dụng void*.
Mark Ransom

1
@Prasoon Saurav: Bất kỳ ai phản đối có thể không đồng ý với tính năng này và đang loại bỏ nó.
Chuck

@Lundin: Có thể nói như vậy với hầu hết các trình biên dịch. __forceinline? __declspec(naked)? Một trong những MSVCisms yêu thích của tôi là:, là template<typename T> class X { friend T; }C ++ 03 không hợp lệ.
Sebastian Mach

Liên kết thứ hai đã chết.
Cœur

96

Làm thế nào để tìm ra nó

Đó là địa chỉ của một nhãn và đó là một tính năng dành riêng cho GCC .

int main(void) {
    void* startp;
s:
    startp = &&s;
    printf("the assignment above starts at address %p\n", startp);
    return 0;
}

Bạn có thể tự mình tìm ra nó bằng cách thử nghiệm:

int main(void) {
    void* startp;
    int a;
    startp = &&a;
    printf("startp=%p\n", startp);
    return 0;
}

Trong trường hợp đó, GCC nói:

error: nhãn 'a' được sử dụng nhưng không được xác định

Dưới mui xe - lắp ráp

Bạn cần biết trình hợp ngữ để thực sự hiểu điều này, nhưng tôi sẽ cố gắng giải thích cho bạn địa chỉ của nhãn nghĩa là gì.

Sau khi hệ điều hành tải tệp .exe từ đĩa, một thành phần của hệ điều hành được gọi là "trình tải" (windows có "PE Loader", linux có "ELF loader" hoặc thậm chí có thể khác, nếu chúng được biên dịch trong kernel), nó thực hiện "ảo hóa" chương trình đó, biến nó thành một tiến trình.

Quá trình này cho rằng nó là duy nhất trong RAM và nó có quyền truy cập vào toàn bộ RAM (nghĩa là 0x00000000-0xFFFFFFFF trên máy 32 bit).

(ở trên chỉ là bản tóm tắt ngắn về những gì đang xảy ra, bạn thực sự cần phải học lắp ráp để hiểu nó đầy đủ, vì vậy hãy chịu đựng với tôi)

Bây giờ, nhãn trong mã nguồn về cơ bản là một địa chỉ. "nhãn goto;" không làm gì khác hơn là một bước nhảy đến địa chỉ đó (hãy nghĩ về con trỏ hướng dẫn trong hợp ngữ). Nhãn này lưu trữ địa chỉ RAM này và đó là cách bạn có thể tìm ra địa chỉ đó.

Sau khi bạn đã học ASM, bạn sẽ nhận ra rằng địa chỉ đó trỏ đến một chỉ dẫn trong .textphần của tệp thực thi. Phần .textnày là phần chứa mã (nhị phân) của chương trình của bạn sẽ được thực thi.

Bạn có thể kiểm tra điều này bằng:

objdump -x a.out

Một ví dụ thực tế

Như được mô tả trong GCC , bạn có thể sử dụng nó để khởi tạo bảng nhảy. Một số trình tạo máy quét như re2c (xem -gthông số) sử dụng điều đó để tạo ra các máy quét nhỏ gọn hơn. Thậm chí có thể có một trình tạo phân tích cú pháp sử dụng cùng một kỹ thuật.


4
Biên dịch với -std = c99 -pedantic.
Lundin

2
Khá quan trọng kể rằng nó là một phần mở rộng GCC, và không phải là một phần cốt lõi của teh ngôn ngữ
jalf

1
Đó là Flavius ​​khá ấn tượng.
Octavian A. Damiean,

1
Tôi thích câu trả lời kiểu này, nhiều người cần được dạy cách tìm câu trả lời hơn là chỉ được nói.
Letseatlunch vào

1
Cảm ơn vì lời giải thích sâu sắc. Đánh giá cao phân tích liên quan đến hội.
CᴴᴀZ
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.