İşaretçi bildirimlerinde yıldız işaretinin yerleştirilmesi


96

Son zamanlarda sonunda C / C ++ öğrenmem gerektiğine karar verdim ve işaretçiler hakkında gerçekten anlamadığım bir şey var ya da daha doğrusu onların tanımları.

Şu örneklere ne dersiniz:

  1. int* test;
  2. int *test;
  3. int * test;
  4. int* test,test2;
  5. int *test,test2;
  6. int * test,test2;

Şimdi, anladığım kadarıyla, ilk üç durumun hepsi aynı şeyi yapıyor: Test bir int değil, bir intibaktır.

İkinci örnekler dizisi biraz daha karmaşıktır. 4. durumda, hem test hem de test2 bir int için işaretçi olurken, 5. durumda yalnızca test bir işaretçi iken, test2 "gerçek" bir inttir. Peki 6. vaka? Durum 5 ile aynı mı?


10
C / C ++ 'da beyaz boşluklar anlamı değiştirmez.
Sulthan

19
7. int*test;?
Jin Kwon

3
+1 çünkü sadece 1 - 3 hakkında soru sormayı düşünmüştüm. Bu soruyu okumak bana 4 - 6 hakkında hiç düşünmediğim bir şey öğretti.
vastlysuperiorman

@Sulthan Bu, her zaman doğru, ancak her zaman değil. Başımın tepesinde, templated tip alan gereksiniminde (C ++ 11 öncesi) şablon tipi türü vardı. Gelen yazılı gerekiyordu böylece sağ kayması olarak tedavi edilmesi değil. Foo<Bar<char>>>>> >
AnorZaken

3
@AnorZaken Haklısınız, bu oldukça eski bir yorum. Bir alanın anlamını değiştireceği birden çok durum vardır, örneğin, artırma ++operatörü bir boşlukla bölünemez, tanımlayıcılar bir boşlukla bölünemez (ve sonuç derleyici için hala geçerli olabilir ancak tanımlanmamış çalışma zamanı davranışıyla). C / C ++ 'ın sözdizimi karmaşası göz önüne alındığında kesin durumları tanımlamak çok zordur.
Sulthan

Yanıtlar:


128

4, 5 ve 6 aynı şeydir, yalnızca test bir göstericidir. İki işaretçi istiyorsanız şunu kullanmalısınız:

int *test, *test2;

Veya daha da iyisi (her şeyi netleştirmek için):

int* test;
int* test2;

3
Öyleyse 4. Durum aslında bir ölüm tuzağı mı? İnt * test, test2'nin neden yalnızca ilk değişkeni bir işaretçi yaptığını açıklayan herhangi bir özellik veya daha fazla okuma var mı?
Michael Stum

8
@ Michael Stum C ++ bu yüzden gerçekten mantıklı bir açıklama olduğunu düşünüyor musunuz?
Joe Phillips

6
K&R (The C Programming Language) okuyun. Bütün bunları çok açık bir şekilde açıklıyor.
Ferruccio

8
Vakalar 4, 5 ve 6 "ölüm tuzaklarıdır". Bu, birçok C / C ++ stil bilgisinin ifade başına yalnızca bir bildirim önermesinin bir nedenidir.
Michael Burr

14
Boşluk bir C derleyicisi için önemsizdir (önişlemciyi göz ardı ederek). Bu nedenle, yıldız işareti ile çevresi arasında kaç boşluk olduğu veya olmadığı önemli değil, tam olarak aynı anlama sahiptir.
ephemient

45

Yıldız işaretlerinin etrafındaki beyaz boşluğun hiçbir önemi yoktur. Üçü de aynı anlama geliyor:

int* test;
int *test;
int * test;

" int *var1, var2", Sadece insanların kafasını karıştıran ve bundan kaçınılması gereken kötü bir sözdizimidir. Şunlara genişler:

int *var1;
int var2;

16
Unutma int*test.
Mateen Ulhaq

2
yıldız işaretinden önceki veya sonraki boşluk sadece bir estetik meselesidir. Ancak, Google Kodlama standardı int *test( google-styleguide.googlecode.com/svn/trunk/… ) ile uyumludur . Tutarlı olun

@SebastianRaschka Google C ++ Stil Kılavuzu , her iki yıldız işaretine de açıkça izin verir. Belki de okuduğunuzdan beri değişmiştir.
Jared Beck

33

Çoğu kodlama kılavuzu, satır başına yalnızca bir değişken tanımlamanızı önerir . Bu, bu soruyu sormadan önce sahip olduğunuz türden herhangi bir karışıklığı önler. Birlikte çalıştığım çoğu C ++ programcısı buna bağlı kalıyor.


Biraz farkında olduğum bir şey var, ama yararlı bulduğum bir şey de beyanları geriye doğru okumak.

int* test;   // test is a pointer to an int

Bu, özellikle const işaretçileri bildirmeye başladığınızda çok iyi çalışmaya başlar ve const olan işaretçi mi yoksa işaretçinin işaret ettiği şeyin const mı olduğunu bilmek zorlaşır.

int* const test; // test is a const pointer to an int

int const * test; // test is a pointer to a const int ... but many people write this as  
const int * test; // test is a pointer to an int that's const

"Satır başına bir değişken" yararlı görünmekle birlikte, yıldız işaretinin daha fazla solda veya daha çok sağda olduğu durumu tam olarak çözemedik. Kesinlikle eminim ki kod dışında bir varyantın hüküm sürdüğünden eminim; İngiltere gibi bazı ülkelerin doğru tarafta gitmesi ve diğerlerinin yanlış yöne gitmesi gibi. ;-)
shevy

Ne yazık ki maceralarımdan vahşi doğaya kadar her iki stilde de bolca görüyorum. Ekibimde artık üzerinde anlaştığımız bir stille clang formatını kullanıyoruz. Bu, en azından ekibimizin ürettiği tüm kodun boşlukların gittiği yer için aynı stile sahip olduğu anlamına gelir.
Scott Langham

33

C / C ++ bildirimlerini çözümlemeye yardımcı olması için "Saat Yönünde Spiral Kuralı" nı kullanın;

İzlenecek üç basit adım vardır:

  1. Bilinmeyen öğeden başlayarak, spiral / saat yönünde hareket edin; Aşağıdaki unsurlarla karşılaştığınızda, bunları ilgili ingilizce ifadelerle değiştirin:

    [X]veya []: Array X size of ... veya Array undefined size of ...

    (type1, type2): type1 ve type2 geçen işlev döndürülüyor ...

    *: işaretçi (ler) ...

  2. Tüm belirteçler kaplanana kadar bunu spiral / saat yönünde yapmaya devam edin.
  3. Her zaman önce parantez içindeki her şeyi çözün!

Ayrıca, beyanlar mümkün olduğunda ayrı ifadelerde olmalıdır (çoğu zaman bu doğrudur).


4
Bu korkutucu ve oldukça korkunç görünüyor, söylediğim için üzgünüm.
Joe Phillips

7
öyle, ama daha karmaşık yapıların bazıları için oldukça iyi bir açıklama gibi görünüyor
Michael Stum

@ d03boy: Hiç şüphe yok - C / C ++ bildirimleri bir kabusa dönüşebilir.
Michael Burr

2
"Spiral" herhangi bir anlam ifade etmiyor, "saat yönünde" çok az. Sözdizimi sizi sağ-alt-sol-üst, sadece sağ-sol göstermediğinden, buna "sağ-sol kuralı" adını vermeyi tercih ederim.
Ruslan

Bunu "sağ-sol-sağ" kuralı olarak öğrendim. C ++ milleti genellikle tüm yazım bilgisinin solda olduğunu varsaymaktan hoşlanır, bu int* x;da geleneksel int *x;stilden ziyade stile götürür . Elbette, aralıkların derleyici için önemi yoktur, ancak insanları etkiler. Gerçek sözdiziminin reddi, okuyucuları rahatsız edebilecek ve kafa karıştırabilecek stil kurallarına yol açar.
Adrian McCarthy

12

Diğerlerinin de bahsettiği gibi 4, 5 ve 6 aynıdır. Çoğu zaman insanlar bu örnekleri *tür yerine değişkene ait olduğu argümanını yapmak için kullanırlar. Bu bir üslup meselesi olsa da, bunu şu şekilde düşünmeniz ve yazmanız gerekip gerekmediği konusunda bazı tartışmalar var:

int* x; // "x is a pointer to int"

veya bu şekilde:

int *x; // "*x is an int"

FWIW Ben birinci kamptayım, ancak diğerlerinin ikinci form için argüman yapmasının nedeni, (çoğunlukla) bu sorunu çözmesidir:

int* x,y; // "x is a pointer to int, y is an int"

potansiyel olarak yanıltıcı olan; onun yerine sen de yazarsın

int *x,y; // it's a little clearer what is going on here

veya gerçekten iki işaretçi istiyorsanız

int *x, *y; // two pointers

Şahsen, bunu satır başına bir değişkenle tut diyorum, o zaman hangi stili tercih ettiğiniz önemli değil.


6
bu sahte, ne diyorsun int *MyFunc(void)? a *MyFunc, dönen bir işlevdir int? Hayır. Açıkçası yazmalıyız int* MyFunc(void)ve şunu söylemeliyiz MyFunca int*. Bu yüzden bana göre bu açık, C ve C ++ dilbilgisi çözümleme kuralları değişken bildirimi için basitçe yanlıştır. tüm virgül dizisi için paylaşılan türün bir parçası olarak işaretçi niteliğini içermeleri gerekirdi.
v.oddou

1
Ama *MyFunc() olan bir int. C sözdizimiyle ilgili sorun, önek ve sonek sözdiziminin karıştırılmasıdır - eğer sadece sonek kullanılmışsa, karışıklık olmazdı.
Antti Haapala

1
İlk kamp, ​​dilin sözdizimiyle savaşıyor ve int const* x;benim kadar yanıltıcı bulduğum gibi kafa karıştırıcı yapılara yol açıyor a * x+b * y.
Adrian McCarthy


5

4, 5 ve 6'da testher zaman bir göstericidir ve test2bir işaretçi değildir. C ++ 'da beyaz boşluk (neredeyse) hiçbir zaman önemli değildir.


3

C'deki mantık, değişkenleri kullandığınız şekilde bildirmenizdir. Örneğin

char *a[100];

bunun bir *a[42]olacağını söylüyor char. Ve a[42]bir karakter işaretçisi. Ve böylece abir dizi karakter göstergesidir.

Bunun nedeni, orijinal derleyici yazarlarının ifadeler ve bildirimler için aynı ayrıştırıcıyı kullanmak istemesidir. (Dil tasarımı seçimi için pek mantıklı bir neden değil)


Yine de yazmak , bunun bir ve bir karakter göstericisi olacağını char* a[100]; da çıkarır . *a[42];chara[42];
yyny

Eh, hepimiz aynı sonuçları çıkarıyoruz, sadece sıra değişiyor.
Michel Billaud

Alıntı: "* a [42] 'nin bir karakter olacağını ve bir [42] karakter göstericisinin olacağını söylüyor". Bunun tersi olmadığına emin misin?
deLock

Diğer yolu tercih ederseniz, diyelim ki a[42]bir charişaretçi ve *a[42]bir karakterdir.
Michel Billaud

3

Bence, duruma bağlı olarak cevap İKİSİNDE. Genel olarak, IMO, türden ziyade işaretçi adının yanına yıldız işareti koymak daha iyidir. Örneğin karşılaştır:

int *pointer1, *pointer2; // Fully consistent, two pointers
int* pointer1, pointer2;  // Inconsistent -- because only the first one is a pointer, the second one is an int variable
// The second case is unexpected, and thus prone to errors

İkinci vaka neden tutarsız? Çünkü örneğin int x,y;, aynı türden iki değişken bildirir, ancak tür bildirimde yalnızca bir kez belirtilir. Bu, emsal ve beklenen bir davranış yaratır. Ve int* pointer1, pointer2;bununla tutarsızdır çünkü pointer1bir işaretçi olarak bildirir , ancak pointer2bir tamsayı değişkendir. Açıkça hatalara meyillidir ve bu nedenle kaçınılmalıdır (yıldız işaretini tür yerine işaretçi adının yanına koyarak).

Ancak , istenmeyen bir sonuç almadan bir nesne adının yanına (ve nereye koyduğunuza önemli olduğu yere) yıldız işaretini koyamayabileceğiniz bazı istisnalar vardır - örneğin:

MyClass *volatile MyObjName

void test (const char *const p) // const value pointed to by a const pointer

Son olarak, bazı durumlarda, yıldız işaretini tür adının yanına koymak muhtemelen daha net olabilir , örneğin:

void* ClassName::getItemPtr () {return &item;} // Clear at first sight


2

İlk sözleşmenin yıldızı işaretçi adı tarafına (bildirimin sağ tarafına) koymak olduğunu söyleyebilirim.

Aynı kuralları takip edebilirsiniz, ancak yazı tarafına yıldız koyarsanız çok da önemli değil. Tutarlılığın önemli olduğunu unutmayın , bu nedenle her zaman ama hangi tarafı seçerseniz seçin yıldız aynı taraftadır.


Görünüşe göre ayrıştırıcı her iki değişime de izin veriyor gibi, ancak Dennis ve Linus bunun doğru tarafta olması gerektiğini söylüyorsa, bu oldukça ikna edici. Ama yine de, biraz mantığımız yok ve sonra bunun neden yapıldığını da açıklıyoruz. StackOverflow'a göre sekmeye karşı boşluk durumuna benziyor biraz - bunun dışında, StackOverflow'a göre sekmeler yerine boşluk kullanan insanlar daha fazla para kazanıyor ... :-)
çekingen

1

İşaretçi, türe bir değiştiricidir. Yıldız işaretinin türü nasıl değiştirdiğini daha iyi anlamak için bunları sağdan sola okumak en iyisidir. 'int *', "int işaretçisi" olarak okunabilir. Çoklu bildirimlerde her değişkenin bir işaretçi olduğunu veya standart bir değişken olarak oluşturulacağını belirtmelisiniz.

1,2 ve 3) Test (int *) türündedir. Boşluk önemli değil.

4,5 ve 6) Test (int *) türündedir. Test2, int türündedir. Yine boşluk önemsizdir.


1

Bu bulmacanın üç parçası var.

İlk parça, C ve C ++ 'daki beyaz boşluğun normalde, aksi takdirde ayırt edilemeyen bitişik simgeleri ayırmanın ötesinde önemli olmadığıdır.

Ön işleme aşamasında, kaynak metin bir dizi jetona bölünür - tanımlayıcılar, noktalayıcılar, sayısal değişmezler, dize değişmezleri vb. Bu simge dizisi daha sonra sözdizimi ve anlam açısından analiz edilir. Tokenleştirici "açgözlüdür" ve mümkün olan en uzun geçerli jetonu oluşturacaktır. Gibi bir şey yazarsan

inttest;

simge belirleyici yalnızca iki simge görür - tanımlayıcı ve inttestardından noktalama işareti ;. intBu aşamada ayrı bir anahtar kelime olarak tanınmaz (bu, işlemin sonraki aşamalarında gerçekleşir). Dolayısıyla, satırın adlandırılmış bir tamsayının bildirimi olarak okunması testiçin, tanımlayıcı jetonlarını ayırmak için boşlukları kullanmamız gerekir:

int test;

*Karakter herhangi tanımlayıcı bir parçası değildir; kendi başına ayrı bir belirteç (noktalama işareti). Yani yazarsan

int*test;

derleyici, 4 ayrı belirteçleri görür - int, *, testve ;. Bu nedenle, işaretçi bildirimlerinde boşluk önemli değildir ve tüm

int *test;
int* test;
int*test;
int     *     test;

aynı şekilde yorumlanır.


Bulmacanın ikinci parçası, bildirimlerin aslında C ve C ++ 1'de nasıl çalıştığıdır . Bildirimler iki ana parçaya bölünür - bir dizi bildirim belirteçleri (depolama sınıfı belirleyicileri, tür belirleyicileri, tür niteleyicileri, vb.) Ve ardından virgülle ayrılmış (muhtemelen başlatılmış) bildiriciler listesi . Beyannamede

unsigned long int a[10]={0}, *p=NULL, f(void);

deklarasyon belirticilere vardır unsigned long intve declarators vardır a[10]={0}, *p=NULLve f(void). Bildirici, bildirilen şeyin adını ( a, pve f) bunun yanı sıra o şeyin dizi özelliği, işaretçi ve işlevi hakkındaki bilgileri tanıtır . Bir bildirici ayrıca ilişkili bir başlatıcıya sahip olabilir.

Türü a"10 öğeli dizi unsigned long int" dir. Bu tür, bildirim belirteçleri ve bildiricinin birleşimiyle tam olarak belirtilir ve ilk değer, başlatıcıyla belirtilir ={0}. Benzer şekilde, türü p"gösterici unsigned long int" dir ve yine bu tür, bildirim belirteçleri ve bildiricinin birleşimiyle belirtilir ve olarak başlatılır NULL. Ve türü de aynı mantıkla " fdönen fonksiyondur unsigned long int".

Bu anahtardır - "işlev döndüren" tür belirticisinin olmaması gibi "dizi-türü" tür belirticisi olmaması gibi "işaretçi" türü belirticisi de yoktur. Bir diziyi şu şekilde tanımlayamayız

int[10] a;

çünkü []operatörün işlenenleri adeğil int. Benzer şekilde beyannamede

int* p;

göreni *ise p, değil int. Ancak, yönlendirme operatörü tekli olduğundan ve boşluk önemli olmadığından, bu şekilde yazarsak derleyici şikayet etmeyecektir. Ancak, her zaman olarak yorumlanır int (*p);.

Bu nedenle yazarsan

int* p, q;

işleneni *olduğu piçin şu şekilde yorumlanacaktır:

int (*p), q;

Böylece hepsi

int *test1, test2;
int* test1, test2;
int * test1, test2;

aynı şeyi yapın - her üç durumda test1da, işlenendir *ve bu nedenle türü "işaretçi int", test2type vardır int.

Bildirimciler keyfi olarak karmaşık hale gelebilir. Dizileriniz olabilir:

T *a[N];

dizilere işaretçileriniz olabilir:

T (*a)[N];

işaretçi döndüren işlevlere sahip olabilirsiniz:

T *f(void);

işlevler için işaretçileriniz olabilir:

T (*f)(void);

işlevlere işaretçiler dizisine sahip olabilirsiniz:

T (*a[N])(void);

dizilere işaretçi döndüren işlevlere sahip olabilirsiniz:

T (*f(void))[N];

işaretçi dizilerine işaretçi döndüren işlevlere, işaretçileri şu işlevlere döndüren işlevlere sahip olabilirsiniz T:

T *(*(*f(void))[N])(void); // yes, it's eye-stabby.  Welcome to C and C++.

ve sonra sahipsin signal:

void (*signal(int, void (*)(int)))(int);

hangi okur

       signal                             -- signal
       signal(                 )          -- is a function taking
       signal(                 )          --   unnamed parameter
       signal(int              )          --   is an int
       signal(int,             )          --   unnamed parameter
       signal(int,      (*)    )          --   is a pointer to
       signal(int,      (*)(  ))          --     a function taking
       signal(int,      (*)(  ))          --       unnamed parameter
       signal(int,      (*)(int))         --       is an int
       signal(int, void (*)(int))         --     returning void
     (*signal(int, void (*)(int)))        -- returning a pointer to
     (*signal(int, void (*)(int)))(   )   --   a function taking
     (*signal(int, void (*)(int)))(   )   --     unnamed parameter
     (*signal(int, void (*)(int)))(int)   --     is an int
void (*signal(int, void (*)(int)))(int);  --   returning void
    

ve bu mümkün olanın yüzeyini zar zor çiziyor. Ancak, dizinin, işaretleyicinin ve işlevin her zaman tür belirticisinin değil, tanımlayıcının parçası olduğuna dikkat edin.

Dikkat edilmesi gereken bir şey - consthem işaretçi türünü hem de işaret edilen yazıyı değiştirebilir:

const int *p;  
int const *p;

Yukarıdakilerin her ikisi de pbir const intnesneye işaretçi olarak bildirilir . pFarklı bir nesneyi işaret edecek şekilde ayarlamak için yeni bir değer yazabilirsiniz :

const int x = 1;
const int y = 2;

const int *p = &x;
p = &y;

ancak işaret edilen nesneye yazamazsınız:

*p = 3; // constraint violation, the pointed-to object is const

Ancak,

int * const p;

const olmayan pbir constişaretçi olarak bildirir int; şunun pişaret ettiği şeyi yazabilirsin

int x = 1;
int y = 2;
int * const p = &x;

*p = 3;

ancak pfarklı bir nesneyi göstermeyi ayarlayamazsınız :

p = &y; // constraint violation, p is const

Bu da bizi bulmacanın üçüncü parçasına getiriyor - neden bildirimler bu şekilde yapılandırıldı?

Amaç, bir bildirimin yapısının koddaki bir ifadenin yapısını yakından yansıtmasıdır ("bildirim taklitleri kullanımı"). Örneğin, intadlandırılacak bir işaretçiler dizisine sahip apolduğumuzu intve i'inci öğenin işaret ettiği değere erişmek istediğimizi varsayalım . Bu değere şu şekilde erişiriz:

printf( "%d", *ap[i] );

Sentezleme *ap[i] türü vardır int; bu nedenle beyanı apşöyle yazılır

int *ap[N]; // ap is an array of pointer to int, fully specified by the combination
            // of the type specifier and declarator

Bildirici *ap[N], ifade ile aynı yapıya sahiptir *ap[i]. Operatörler *ve []bir ifadede yaptıkları gibi bir bildirimde aynı şekilde davranırlar - []tek terimden daha yüksek önceliğe sahiptir *, bu nedenle işleneni *is ap[N](şu şekilde ayrıştırılır:*(ap[N]) ).

Başka bir örnek olarak, intadlandırılmış bir diziye bir göstericimiz olduğunu pave i'inci öğenin değerine erişmek istediğimizi varsayalım . Bunu şu şekilde yazardık

printf( "%d", (*pa)[i] );

İfadenin türü (*pa)[i]olduğu intiçin beyan şu şekilde yazılır:

int (*pa)[N];

Yine, aynı öncelik ve birliktelik kuralları geçerlidir. Bu durumda, i' ın ' inci elemanına pabaşvurmak istemiyoruz i, neyi pa işaret ettiğinin 'inci elemanına erişmek istiyoruz , bu yüzden *operatörü açıkça gruplandırmalıyızpa .

*, []Ve ()operatörler bir parçasıdır ifade kodunda, bu nedenle bir parçasıdır Bildiricisi bildiriminde. Bildirici, nesneyi bir ifadede nasıl kullanacağınızı söyler. Eğer gibi bir bildiriminiz varsa int *p;, bu *psize kodunuzdaki ifadenin bir intdeğer vereceğini söyler . Uzantı olarak, ifadenin p"işaretçi int" türünde bir değer verdiğini veya int *.


Öyleyse, ya benzer şeyleri ya da bunun gibi şeyleri sizeofkullandığımız oyuncular ve ifadeler gibi şeyler ne olacak ? Gibi bir şeyi nasıl okurum(int *)sizeof (int [10])

void foo( int *, int (*)[10] );

Tanımlayıcı yok, *ve []operatörleri türü doğrudan değiştirmiyor mu?

Şey, hayır - sadece boş bir tanımlayıcıyla ( soyut bir bildirici olarak bilinir ) hala bir tanımlayıcı var . Biz sembol  boş bir tanımlayıcı temsil ediyorsa, o zaman bu şeyleri okuyabilir olarak (int *λ), sizeof (int λ[10])ve

void foo( int *λ, int (*λ)[10] );

ve tıpkı diğer beyanlar gibi davranırlar. int *[10]10 işaretli bir diziyi temsil ederken int (*)[10], bir diziye bir göstericiyi temsil eder.


Ve şimdi bu cevabın kararlı kısmı. Basit işaretçileri şu şekilde bildiren C ++ kuralından hoşlanmıyorum

T* p;

ve aşağıdaki nedenlerden dolayı kötü bir uygulama olduğunu düşünün :

  1. Sözdizimi ile tutarlı değil;
  2. Bu soru ile bu soruya tüm çiftleri, anlamı hakkında sorular kanıtlandığı üzere (karışıklığı tanıtır T* p, q;, tüm çiftleri bu sorulara, vs.);
  3. Kendi içinde tutarlı değildir - T* a[N]kullanımla asimetrik olduğu gibi bir dizi işaretçi bildirmek (yazma alışkanlığınız yoksa * a[i]);
  4. Diziye işaretçi veya işleve işaretçi türlerine uygulanamaz (yalnızca T* pkuralı temiz bir şekilde uygulayabilmeniz için bir typedef oluşturmadığınız sürece , ki ... hayır );
  5. Bunu yapmanın nedeni - "nesnenin göstericiliğini vurgular" - sahtedir. Dizi veya işlev türlerine uygulanamaz ve bu niteliklerin vurgulamak kadar önemli olduğunu düşünüyorum.

Sonunda, sadece iki dilin tip sistemlerinin nasıl çalıştığına dair kafa karışıklığı olduğunu gösteriyor.

Öğeleri ayrı ayrı beyan etmek için iyi nedenler vardır; kötü bir uygulama etrafında çalışmak ( T* p, q;) bunlardan biri değildir. Açıklayıcılarınızı doğru yazarsanız ( T *p, q;) kafa karışıklığına neden olma olasılığınız azalır.

Tüm basit fordöngülerinizi kasıtlı olarak şu şekilde yazmaya benzediğini düşünüyorum:

i = 0;
for( ; i < N; ) 
{ 
  ... 
  i++ 
}

Sözdizimsel olarak geçerli, ancak kafa karıştırıcı ve niyet muhtemelen yanlış yorumlanacak. Bununla birlikte, T* p;kural C ++ topluluğunda yerleşiktir ve bunu kendi C ++ kodumda kullanıyorum çünkü kod tabanındaki tutarlılık iyi bir şeydir, ancak bunu her yaptığımda kaşındırıyor.


  1. C terminolojisini kullanacağım - C ++ terminolojisi biraz farklı, ancak kavramlar büyük ölçüde aynı.

-3

İyi bir kural olarak, birçok insan bu kavramları şu şekilde kavramış gibi görünüyor: C ++ 'da birçok anlamsal anlam, anahtar kelimelerin veya tanımlayıcıların sola bağlanmasıyla elde edilir.

Örneğin alın:

int const bla;

Sabit, "int" kelimesi için geçerlidir. Aynısı işaretçilerin yıldız işaretleri için de geçerlidir, sol anahtar kelimeye uygulanırlar. Ve asıl değişken adı? Evet, geriye kalanlar tarafından ilan edildi.


1
Bu sorunun cevabı değil. Biz çalışırsanız da kötüsü, anlaması o, o zaman herkes olarak başka söylediği onun solunda en türüne yıldız bağlar ima bir cevap, yanlıştır. Sağındaki tek değişken adına bağlanır.
underscore_d
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.