Void'de && ne anlama geliyor * p = && abc;


102

Bir kod parçasıyla karşılaştım void *p = &&abc;. Burada ne önemi &&var? Rvalue referanslarını biliyorum ama &&bu bağlamda farklı olduğunu düşünüyorum . Ne geliyor &&belirtmek void *p = &&abc;?


14
Bunu nerede gördün?
user541686

3
Bunu nerede gördüğünüzü de bilmek isterim.
Flavius

Yanıtlar:


154

&&gcc'nin mevcut işlevde tanımlanan etiketin adresini almak için uzantısıdır .

void *p = &&abc standart C99 ve C ++ 'da yasa dışıdır.

Bu , g ++ ile derlenir.


42
Şimdi, gcc varsayılan olarak -pedantic olsaydı herkesin ne kadar iyi programcı olacağını hayal edin. O zaman insanlar gnus hakkında alakasız bilgiler yerine C'yi öğreneceklerdi.
Lundin

4
Ne hile. Etiket işaretçileri için yeni bir sözdizimi icat ederlerse, kullanmak yerine bunun için de yeni bir tür icat etmeleri gerekir void*.
Mark Ransom

1
@Prasoon Saurav: Kim olumsuz oy verdiyse muhtemelen özelliği onaylamıyor ve sizden alıyor.
Chuck

@Lundin: Çoğu derleyici için aynı şey söylenebilir. __forceinline? __declspec(naked)? En sevdiğim MSVCismlerden biri: template<typename T> class X { friend T; }geçersiz olan C ++ 03.
Sebastian Mach

İkinci halka öldü.
Cœur

96

Nasıl bulunur

Bu, bir etiketin adresidir ve GCC'ye özgü bir özelliktir .

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

Şunları test ederek kendiniz çözebilirdiniz:

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

Bu durumda GCC şunları söyler:

hata: 'a' etiketi kullanılmış ancak tanımlanmamış

Kaputun altında - montaj

Bunu gerçekten anlamak için assembler'ı bilmeniz gerekir, ancak size bir etiketin adresinin ne anlama geldiğini açıklamaya çalışacağım.

İşletim sistemi .exe dosyasını diskten yükledikten sonra, işletim sisteminin "yükleyici" adı verilen bir bileşeni (Windows'ta "PE Yükleyici", linux'ta "ELF yükleyici" veya hatta başka dosyalar, kernel), o programın "sanallaştırılmasını" gerçekleştirerek onu bir işleme dönüştürür.

Bu işlem, RAM'deki tek olduğunu ve tüm RAM'e erişimi olduğunu düşünür (yani, 32 bitlik bir makinede 0x00000000-0xFFFFFFFF).

(yukarıdakiler neler olup bittiğine dair sadece kısa bir bakış, montajı tam olarak anlamak için gerçekten öğrenmeniz gerekiyor, bu yüzden bana katlanın)

Şimdi, bir kaynak koddaki etiket temelde bir adrestir. "etikete git;" bu adrese atlamaktan başka bir şey yapmaz ( assembly'deki komut göstericisini düşünün ). Bu etiket, bu RAM adresini saklar ve bu adresi bu şekilde öğrenebilirsiniz.

ASM'yi öğrendikten sonra, bu adresin .textyürütülebilir dosyanın bölümündeki bir talimata işaret ettiğini fark edeceksiniz . .textBölüm yürütülecek size programın (ikili) kod tutan biridir.

Bunu şu şekilde inceleyebilirsiniz:

objdump -x a.out

Pratik bir örnek

GCC'de açıklandığı gibi , bunu bir atlama tablosunu başlatmak için kullanabilirsiniz. Re2c gibi bazı tarayıcı üreteçleri ( parametreye bakın ) bunu daha kompakt tarayıcılar oluşturmak için kullanır. Belki aynı tekniği kullanan bir ayrıştırıcı üreteci bile vardır .-g


4
-Std = c99 -pedantic ile derleyin.
Lundin

2
Bunun bir GCC uzantısı olduğunu ve dilin temel bir parçası olmadığını belirtmek oldukça önemli
jalf

1
Bu oldukça etkileyici Flavius.
Octavian A. Damiean

1
Bu tür cevapları seviyorum, sadece söylenmek yerine daha fazla insana nasıl cevap bulacaklarının öğretilmesi gerekiyor.
Letseatlunch

1
Ayrıntılı açıklama için teşekkürler. Meclis ile ilgili analizleri takdir etti.
CᴴᴀZ
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.