Aracılığıyla paylaş


C++ numaraları ve işleçleri

Bu makalede, Windows hata ayıklama araçlarıyla C++ ifade söz dizimi kullanımı açıklanmaktadır.

Hata ayıklayıcı iki farklı türde sayısal ifade kabul eder: C++ ifadeleri ve Microsoft Makro Derleyicisi (MASM) ifadeleri. Bu ifadelerin her biri, giriş ve çıkış için kendi söz dizimi kurallarına uyar.

Her bir söz dizimi türünün ne zaman kullanıldığı hakkında daha fazla bilgi için bkz. İfadeleri değerlendirme ve evaluate ifadesini değerlendirme komutu.

C++ ifade ayrıştırıcısı tüm C++ ifade söz dizimini destekler. Söz dizimi işaretçiler, kayan nokta sayıları ve diziler dahil olmak üzere tüm veri türlerini ve tüm C++ birli ve ikili işleçleri içerir.

Hata ayıklayıcıdaki watch ve Locals pencereleri her zaman C++ ifade değerlendiricisini kullanır.

Aşağıdaki örnekte C++ ifadesini değerlendir komutu talimat işaretçisi yazmacının değerini görüntüler.

0:000> ?? @eip
unsigned int 0x771e1a02

Yapıların boyutunu belirlemek için C++ sizeof işlevini kullanabiliriz.

0:000> ?? (sizeof(_TEB))
unsigned int 0x1000

İfade değerlendiricisini C++ olarak ayarlama

Varsayılan ifade değerlendiricisini görmek ve C++ olarak değiştirmek için .expr choose ifadesi değerlendiricisini kullanın.

0:000> .expr
Current expression evaluator: MASM - Microsoft Assembler expressions
0:000> .expr /s c++
Current expression evaluator: C++ - C++ source expressions

Varsayılan ifade değerlendirici değiştirildikten sonra, C++ ifadelerini görüntülemek için ? evaluate ifadesi komutu kullanılabilir. Aşağıdaki örnek, komut işaretçisi yazmacının değerini görüntüler.

0:000> ? @eip
Evaluate expression: 1998461442 = 771e1a02

Yazmaç @eip başvurusu hakkında daha fazla bilgi edinmek için Yazmaç söz dizimi'ne bakın.

Bu örnekte, 0xD onaltılık değeri eip yazmacına eklenir.

0:000> ? @eip + 0xD
Evaluate expression: 1998461455 = 771e1a0f

C++ ifadelerinde yazmaçlar ve sahte yazmaçlar

C++ ifadeleri içinde yazmaçları ve sahte yazmaçları kullanabilirsiniz. @ işareti, yazmaç veya sahte kayıt öncesinde eklenmelidir.

İfade değerlendiricisi uygun atamayı otomatik olarak gerçekleştirir. Gerçek yazmaçlar ve tamsayı değeri olan sahte yazmaçlar, ULONG64 tipine dönüştürülür. Tüm adresler PUCHAR'a atanır, $threadETHREAD*'ya atanır, $procEPROCESS*'e atanır, $tebTEB*'ya atanır ve $pebPEB*'e atanır.

Bu örnekte TEB görüntülenir.

0:000>  ?? @$teb
struct _TEB * 0x004ec000
   +0x000 NtTib            : _NT_TIB
   +0x01c EnvironmentPointer : (null) 
   +0x020 ClientId         : _CLIENT_ID
   +0x028 ActiveRpcHandle  : (null) 
   +0x02c ThreadLocalStoragePointer : 0x004ec02c Void
   +0x030 ProcessEnvironmentBlock : 0x004e9000 _PEB
   +0x034 LastErrorValue   : 0xbb
   +0x038 CountOfOwnedCriticalSections : 0

Atama veya yan etki operatörü ile bir yazmaç veya sahte yazmaç değiştiremezsiniz. Bu değerleri değiştirmek için r registers komutunu kullanmanız gerekir.

Aşağıdaki örnek sahte kaydı 5 değerine ayarlar ve ardından görüntüler.

0:000> r $t0 = 5

0:000> ?? @$t0
unsigned int64 5

Yazmaçlar ve sahte yazmaçlar hakkında daha fazla bilgi için bkz . Yazmaç söz dizimi ve Sahte kayıt söz dizimi.

C++ ifadelerindeki sayılar

C++ ifadelerindeki sayılar, başka bir şekilde belirtmediğiniz sürece ondalık sayılar olarak yorumlanır. Onaltılık tamsayı belirtmek için, sayıdan önce 0x ekleyin. Sekizli tamsayı belirtmek için, sayıdan önce 0 (sıfır) ekleyin.

Varsayılan hata ayıklayıcısı radiksi, C++ ifadelerini girme yönteminizi etkilemez. BIR MASM ifadesini C++ ifadesi içinde iç içe geçirme dışında, ikili bir sayıyı doğrudan giremezsiniz.

xxxxx'xxxx biçiminde onaltılık 64 bitlik bir değer girebilirsiniz. Ayrıca, aksan (') işaretinden de atlayabilirsiniz. Her iki biçim de aynı değeri üretir.

L, U ve I64 son eklerini tamsayı değerleriyle kullanabilirsiniz. Oluşturulan sayının gerçek boyutu, son eke ve girdiğiniz sayıya bağlıdır. C++ dili başvuru kaynağına bakınız, bu yorum hakkında daha fazla bilgi için.

C++ ifade değerlendiricisinin çıkışı , C++ ifade kurallarının belirttiği veri türünü tutar. Ancak, bu ifadeyi bir komut için bağımsız değişken olarak kullanırsanız, her zaman bir dönüştürme yapılır. Örneğin, komut bağımsız değişkenlerinde adres olarak kullanıldıklarında işaretçilere tamsayı değerleri atamanız gerekmez. İfadenin değeri geçerli olarak bir tamsayıya veya işaretçiye atanamıyorsa, söz dizimi hatası oluşur.

Bazı çıkışlar için (ondalık) ön ekini 0n kullanabilirsiniz, ancak bunu C++ ifade girişi için kullanamazsınız.

C++ ifadelerindeki karakterler ve dizeler

Karakteri tek tırnak işaretiyle (') çevreleyerek girebilirsiniz. Standart C++ kaçış karakterlerine izin verilir.

Dize değişmez değerlerini çift tırnak işaretiyle (") çevreleyerek girebilirsiniz. \" öğesini böyle bir dize içinde kaçış dizisi olarak kullanabilirsiniz. Ancak, dizelerin ifade değerlendiricisi için bir anlamı yoktur.

C++ ifadelerindeki simgeler

Bir C++ ifadesinde, her simge türüne göre yorumlanır. Simgenin başvurduğu şeye bağlı olarak, bir tamsayı, veri yapısı, işlev işaretçisi veya başka bir veri türü olarak yorumlanabilir. C++ ifadesinde değiştirilmemiş modül adı gibi C++ veri türüne karşılık gelmeyen bir simge kullandığınızda bir söz dizimi hatası oluşur.

Simge adından önce bir modül adı ve ünlem işareti eklerseniz, simge adından büyük vurgu (') veya kesme işareti (') kullanabilirsiniz. Bir şablon adından sonra < ve > sınırlayıcılarını eklediğinizde, bu sınırlayıcılar arasına boşluk ekleyebilirsiniz.

Simge belirsiz olabilirse, simgeden önce bir modül adı ve ünlem işareti (!) veya yalnızca ünlem işareti ekleyebilirsiniz. Bir simgenin yerel olması gerektiğini belirtmek için modül adını atlayın ve simge adından önce dolar işareti ve ünlem işareti ($!) ekleyin. Sembol tanıma hakkında daha fazla bilgi için bkz. Sembol söz dizimi ve simge eşleştirme.

C++ ifadelerindeki yapılar

C++ ifade değerlendiricisi, sahte kaydedicileri uygun türlerine dönüştürür. Örneğin, $teb olarak TEB*yayınlanır.

0:000> ??  @$teb
struct _TEB * 0x004ec000
   +0x000 NtTib            : _NT_TIB
   +0x01c EnvironmentPointer : (null) 
   +0x020 ClientId         : _CLIENT_ID
   +0x028 ActiveRpcHandle  : (null) 
   +0x02c ThreadLocalStoragePointer : 0x004ec02c Void
   +0x030 ProcessEnvironmentBlock : 0x004e9000 _PEB
   +0x034 LastErrorValue   : 0xbb
   +0x038 CountOfOwnedCriticalSections : 0

Aşağıdaki örnekte, başvurulan bir yapı üyesine işaretçi kullanımını gösteren TEB yapısındaki işlem kimliği gösterilir.

0:000> ??  @$teb->ClientId.UniqueProcess
void * 0x0000059c

C++ ifadelerindeki işleçler

Öncelik kurallarını geçersiz kılmak için parantez kullanabilirsiniz.

C++ ifadesinin bir bölümünü parantez içine alır ve ifadeden önce iki işareti (@@) eklerseniz, ifade MASM ifade kurallarına göre yorumlanır. İki @ işareti ile açılan parantez arasına boşluk ekleyemezsiniz. Bu ifadenin son değeri C++ ifade değerlendiricisine ULONG64 değer olarak geçirilir. İfade değerlendiricisini @@c++( ... ) veya @@masm( ... ) kullanarak da belirtebilirsiniz.

Veri türleri C++ dilinde her zamanki gibi gösterilir. Dizileri ([ ]), işaretçi üyelerini (->), UDT üyelerini (.) ve sınıfların üyelerini (::) gösteren simgelerin tümü tanınır. Atama ve yan etki işleçleri dahil olmak üzere tüm aritmetik işleçler desteklenir. Ancak, new, delete ve throw işleçlerini kullanamazsınız ve aslında bir işlevi çağıramazsınız.

İşaretçi aritmetiği desteklenir ve ofsetler doğru şekilde ölçeklendirilir. İşlev işaretçisine uzaklık ekleyemezsiniz. bir işlev işaretçisine uzaklık eklemeniz gerekiyorsa, önce uzaklığı bir karakter işaretçisine dönüştürebilirsiniz.

C++'da olduğu gibi, geçersiz veri türlerine sahip işleçler kullanırsanız söz dizimi hatası oluşur. Hata ayıklayıcının C++ ifade ayrıştırıcısı çoğu C++ derleyicisinden biraz daha gevşek kurallar kullanır, ancak tüm ana kurallar uygulanır. Örneğin, tamsayı olmayan bir değeri kaydıramazsınız.

Aşağıdaki işleçleri kullanabilirsiniz. Her hücredeki işleçler, alt hücrelerdeki işleçlere göre önceliklidir. Aynı hücredeki işleçler aynı önceliğe sahiptir ve soldan sağa ayrıştırılır.

C++ ile olduğu gibi ifade değerlendirmesi de değeri bilindiğinde sona erer. Bu son, gibi ?? myPtr && *myPtrifadeleri etkili bir şekilde kullanmanızı sağlar.

Referans ve tür dönüştürme

Operatör Anlamı
İfade // Yorum Sonraki tüm metni yoksay
Sınıf :: Üye Sınıfın üyesi
Sınıf ::~Üye Sınıfın üyesi (yıkıcı)
:: Ad Global
Yapısı . Alan Bir yapıdaki alan
İşaretçi ->Alan Başvurulan yapıdaki alan
Ad [tamsayı] Dizi alt indis
LValue ++ Artım (değerlendirmeden sonra)
LValue -- Azaltma (değerlendirmeden sonra)
< dynamic_casttür>(Değer) Typecast (her zaman gerçekleştirilir)
static_cast<tür>(Değer) Typecast (her zaman gerçekleştirilir)
reinterpret_cast<tür>(Değer) Typecast (her zaman gerçekleştirilir)
const_cast<tür>(Değer) Typecast (her zaman gerçekleştirilir)

Değer işlemleri

Operatör Anlamı
(tür) Değer Typecast (her zaman gerçekleştirilir)
sizeofdeğeri İfadenin boyutu
sizeof( tür ) Veri türünün boyutu
++ LValue Artım (değerlendirmeden önce)
-- LValue Azaltma (değerlendirmeden önce)
~ Değer Bit tamamlayıcısı
! Değer Değil (Boolean)
Değer Tekli eksi
+ Değer Üniter artı
& LValue Veri türünün adresi
Değer Başvuru
Yapısı . İşaretçisi Yapı üyesi işaretçisi
İşaretçi -> * İşaretçi Referans verilen yapının üye işaretçisi

Aritmetik

Operatör Anlamı
Değer Değeri Çarpma
Değer / Değer Bölüm
Değer % Değer Modülü
Değer + Değer İlave
Değer - Değer Çıkarma
Değer<<Değer Bit düzeyinde sola kaydırma
Değer>>Değer Bit düzeyinde sağa kaydırma
Değer<Değer "Daha az (karşılaştırma)"
Değer<= Değer Küçük veya eşit (karşılaştırma)
Değer>Değer Büyüktür (karşılaştırma)
Değer>= Değer Büyüktür veya eşittir (karşılaştırma)
Değer == Değer Eşittir (karşılaştırma)
Değer != Değer Eşit değil (karşılaştırma)
Değer ve Değer Bit Düzeyinde VE
Değer ^ Değer Bit Düzeyinde XOR (özel OR)
Değer | Değer Bit Düzeyinde OR
Değer && Değer Mantıksal VE
Değer || Değer Mantıksal VEYA

Aşağıdaki örneklerde sahte kayıtların gösterildiği gibi ayarlandığı varsayılır.

0:000> r $t0 = 0
0:000> r $t1 = 1
0:000> r $t2 = 2
0:000> ?? @$t1 + @$t2
unsigned int64 3
0:000> ?? @$t2/@$t1
unsigned int64 2
0:000> ?? @$t2|@$t1
unsigned int64 3

Görevlendirme

Operatör Anlamı
LValue = Değer Atamak
LValue *= Değer Çarpma ve atama
LValue /= Değer Bölme ve atama
LValue %= Değer Modulo ve atama
LValue += Değer Ekleme ve atama
LValue -= Değer Çıkarma ve atama
LValue<<= Değer Sola kaydırma ve atama
LValue>>= Değer Sağa kaydır ve ata
LValue &= Value AND ve atama
LValue |= Değer VEYA ve atama
LValue ^= Değer XOR ile ata

Değerlendirme

Operatör Anlamı
Değer mi? Değer : Değer Koşullu değerlendirme
Değer , Değer Tüm değerleri değerlendirin ve en sağdaki değer dışında tümünü at

C++ ifadelerindeki makrolar

C++ ifadeleri içinde makroları kullanabilirsiniz. Makrolardan önce bir sayı işareti (#) eklemeniz gerekir.

Aşağıdaki makroları kullanabilirsiniz. Bu makrolar, aynı ada sahip Microsoft Windows makrolarıyla aynı tanımlara sahiptir. Windows makroları Winnt.h içinde tanımlıdır.

Makro Dönüş değeri
#CONTAINING_RECORD(Adres, Tür, Alan) Yapının türü ve yapı içindeki bir alanın adresi göz önünde bulundurularak bir yapı örneğinin temel adresini döndürür.
#FIELD_OFFSET(Type, Field) Bilinen bir yapı türündeki adlandırılmış alanın bayt uzaklığını döndürür.
#RTL_CONTAINS_FIELD(Yapı, Boyut, Alan) Verilen bayt boyutunun istenen alanı içerip içermediğini gösterir.
#RTL_FIELD_SIZE(Tür, Alan) Alanın türüne gerek kalmadan bilinen türde bir yapıdaki alanın boyutunu döndürür.
#RTL_NUMBER_OF(Dizi) Statik olarak boyutlandırılmış bir dizideki öğelerin sayısını döndürür.
#RTL_SIZEOF_THROUGH_FIELD(Type, Field) Belirtilen alanla birlikte bilinen türdeki bir yapının boyutunu döndürür.

Bu örnek, yapıdaki #FIELD_OFFSET bir alana bayt uzaklığını hesaplamak için makronun kullanımını gösterir.

0:000> ?? #FIELD_OFFSET(_PEB, BeingDebugged)
long 0n2

Ayrıca bakınız

MASM ifadeleri ile C++ ifadeleri karşılaştırması

?? C++ ifadesini değerlendirme

? ifadeyi değerlendirme

.expr ifadesi seçimi değerlendiricisi

Oturum açma uzantısı

Karma ifade örnekleri