Ana işlevde argc ve argv'yi yeniden adlandırmak güvenli midir?


82

Bir çok program bir dizi argüman ve dizge dizisi için standart isimler kullanır. Ana işlevi görünüm prototip gibi: int main(int argc, char *argv[]);. Ama bu değişkenler için özel isimler seçersem bir şeyi bozar mıyım?

Örneğin int main(int n_of_args, char *args[]);

Derleyici bağlamında her şey yolunda. Bu değişkenler ana işlev için yereldir, bu nedenle herhangi bir isme sahip olabilirler. Ve basit kod mükemmel bir şekilde oluşturulur ve çalışır. Ancak bu isimler önişlemci tarafından kullanılabilir. Öyleyse bu argümanları yeniden adlandırmak güvenli midir?

Not: Şahsen ben bu isimleri kötü buluyorum çünkü çok benzer görünüyorlar ve sadece bir harfte farklılar. Ama HERKES onları bir tür sebepten kullanıyor.


21
Evet, tamamen güvenli.
David Hoelzer

55
Tüm cevapların dediği gibi, evet, güvenli. Ama lütfen bunu yapma. Herkes bilir argcve argvvardır. n_of_argsve argsC veya C ++ bilmeyen biri için daha net olabilir - ama bu sizin hedef kitleniz değil.
Keith Thompson

4
Bunu yapabilirsin , bunu yapmak için yeterli sebep yok. Herkes bunların ne olduğunu bilir ve onların böyle olmasını beklerler.
SergeyA

10
Eğer soru tam olarak "özel isimler seçersem bir şeyi bozar mıyım" ise, kesin cevap "evet, iyi yerleşmiş geleneği
bozarsınız

12
Sadece çevirin! .. ve en başından beri iş güvenliği için bir temel
atıyorsunuz

Yanıtlar:


121

Evet, geçerli değişken adları kullandığınız sürece güvenlidir. Yerel değişkenlerdir, bu nedenle kapsamları mainişlevin ötesine geçmez .

C standardının 5.1.2.2.1 bölümünden :

Program başlangıcında çağrılan işlev adlandırılır main. Uygulama, bu işlev için hiçbir prototip bildirmez. Bir dönüş türü ile intve parametresiz olarak tanımlanmalıdır :

int main(void) { /*  ... */ }

veya iki parametreli (burada argcve olarak anılacaktır argv, ancak herhangi bir isim kullanılabilir, çünkü bildirildikleri işlev için yereldirler ):

int main(int argc, char *argv[]) { /* ...   */ }

veya eşdeğer; veya başka bir uygulama tanımlı şekilde

Bununla birlikte, başka herhangi bir şey kullanmak argcve argvbu parametreler için geleneksel adlara alışkın olan başkalarının kodunuzu okuyarak kafasını karıştırabilir. Tazminat tarafında yanılmak daha iyi.


38

İsimler argcve argvaslında C ++ 11'den önce C ++ standardı tarafından zorunlu kılındı. Şöyle diyordu:

Tüm uygulamalar, aşağıdaki main tanımlarının her ikisine de izin verecektir:

int main ()

ve

int main ( int argc , char * argv [])

ve ilgili gereksinimleri tartışmak için gitti argcve argv.

Teknik olarak, farklı isimler kullanan herhangi bir program standartlara uygun değildi ve derleyicinin bunu reddetmesine izin verildi. Elbette hiçbir derleyici bunu yapmadı. Bkz comp.std.c ++ bu konu veya bölüm 3.6.1 bu C ++ 03 taslak standardı .

Bu neredeyse kesinlikle sadece bir gözetimdi ve C ++ 11'de değiştirildi.

Tüm uygulamalar hem

  • () dönen bir fonksiyon intve
  • ( int, işaretçiye gösterici char) dönen bir işlevint

main(8.3.5) türü olarak . İkinci formda, açıklama amacıyla, birinci fonksiyon parametresi çağrılır argcve ikinci fonksiyon parametresi argv,…


29

Elbette bu parametreleri istediğiniz gibi güvenle yeniden adlandırabilirsiniz

 int main(int wrzlbrnft, char* _42[]) {
 }

İsimler kumla yazılmıştır. Son olarak derlenen kod üzerinde herhangi bir etkisi yoktur.


Önemli olan tek şey, parametre türlerinin tanımlanması ve tanımının gerçekten eşleşmesidir.

main()İşlevin imzası özünde şu şekilde bildirilir:

 int main(int, char*[]);

bunları bir uygulamada kullanmanız gerekirse, aslında onlara bir ad vermeniz gerekir. Daha önce bahsedildiği gibi hangi isimlerin kullanıldığı aslında önemsizdir.


5
sizin koyduğunuz gibi yalnızca bazı tanımlayıcılar "kuma yazılır". işlev isimleri kesinlikle değildir.
Steve Cox

1
@SteveCox "işlev adları kesinlikle değildir." Sonunda öyleler. Sadece kum taneleri sayısı :-P ...
πάντα ῥεῖ

3
tamam ama cidden. derlemeden sonra, nesne kodunun içinde hala işlev adları vardır. aksi halde bağlantı işe yaramaz
Steve Cox

4
@ πάνταῥεῖ: Bunları kaldırmak için özel bir çaba göstermezseniz, işlev adları son çalıştırılabilir dosyada kalır.
Nick Matteo

1
@Kundor: Windows'a bağlandıktan sonra, özel olmayan tüm işlevler adları korumaz
Dani


7

Evet, farklı isimler kullanmak güvenlidir.

Kişisel olarak, bunu geleneksel olarak tavsiye etmem argcve argvkodunuzla çalışabilecek diğer tüm C programcıları tarafından çok yaygın ve tanıdık geliyor. Uzun vadede, kendi, özel, farklı isimlerinizi kullanmak, okuyucularınız arasında isimlerinizi daha çok sevdiğiniz için sizi kurtaracağından çok daha fazla kafa karışıklığına ve / veya hayal kırıklığına neden olacaktır.

"Roma'da romalılar gibi davran."


Yine de, farklı isimler kullanmaya çağıran oldukça açık birkaç senaryo var, kötü şöhretli olanlardan biri, GLUT'un, glutInit(&argc, argv)istemedikçe komut satırı argümanlarını yemesine izin vermemek için argümanların farklı şekilde bildirilmesi ve başlatılması gereken GLUT'u başlatıyor. SO bağlantısı
user3078414

@ user3078414 İlginç bir örnek, ancak değişkenlerin adlandırılması gerekenler hakkında nasıl bir şey söylediğini anlamıyorum. Diğer sorudaki örneklere göre, biz de kolayca yazabiliriz int dummyargc = 1; char *dummyargv[1] = {(char*)"Something"}; glutInit(&dummyargc, dummyargv);.
Steve Zirvesi

Teşekkürler @ steve-summit. Bazı API belgeleri yanıltıcı olabilir, bu nedenle bu ileti dizisi, argc argvkatkıda bulunan yanıtınız gibi adlandırma kuralını vurgulamak için en yararlıdır . Ben sadece yorumumu, tercihen farklı isimler kullanmaya örnek olarak koydum. İşte SO bağlantı
user3078414

5

Evet, istediğiniz gibi yeniden adlandırabilirsiniz. Bunlar sadece fonksiyon parametresi isimleridir, daha fazlası değildir.


3

Herkesin teknik c ++ kurallarını iyi ve iyi ele aldığını hissediyorum: Cevap evet. Geleneği ve bu 1 belirli işlevin bu temelde değişmemesi gereken geçerli noktaları içeren özel ve ikonik olduğu gerçeğini bir kenara bırakalım.

Çoğu zaman, seçimlerin felsefesinin nadiren tartışıldığını hissediyorum ve bu nedenle, bunun neden sorulmasının nedeninin önemli olduğunu düşündüğüm için bu konuya bir bakış açısı sunmak istedim.

Bana göre bu soru, genel olarak ingilizceyi kod olarak ifade etme seçeneğini içeriyor. Kısa el açıklamaları, özellikle de kısa el benzer görünümlü bir metne sahipse, rahatsız hissediyorsunuz. Bununla birlikte, örneğinizde, argn'yi n_of_args olarak değiştirmek, yalnızca bir tür kısa elin gerçek bir değer eklemesi olmadan başka bir kısaltma biçimine dönüştürülmesini sağlar: açıklama veya diğer görünür özellikler.

'Sayı' kelimesinin yerini 'n' harfi almıştır.

Kısa bir elin adını anti kısa el felsefesiyle değiştiriyorsanız, bunun gibi bir şey daha uygun görünebilir:

main (int argumentCount, char ** argumentVector)

Her zaman iki şeyi düşünürüm: Bir şeyleri ne olduklarına ve / veya ima edilen kullanımlarına göre adlandırmak. Buna argumentVector demek benim için gereksizdir, çünkü bir vektör olma özelliği çift dolaylı ** ile ima edilir. Bu nedenle, kodu nasıl yazacağım konusunda daha iyi bir uzun el: ** argümanlar.

Bazıları argumentCount adlı değişkenin bir int olarak bildirildiğini ve bir Count'un negatif olamayacağını söyler, ancak negatif bir int {unsigned is better} olabilir.

Yine bu yorumda ne olduğu ve nasıl kullanıldığı devreye giriyor. Bir Sayı ise, o zaman asla negatif olmayacağını varsayarım. Sonuçta, nasıl -2 elmaya sahip olabilirsiniz? Size iki elmanın SAHİBİ olduğunu söyleyebilirim. Bir Sayı ise, olumsuz bir durumun mümkün olmasını beklerim. Bu nedenle, 'of' ek kelimesi sizin için büyük olasılıkla önemlidir. Bu ve belki de bir koleksiyon tarafından atıfta bulunulan bir sayı, koleksiyonun kendisinin bir özelliğinden ziyade belirli bir öğeyi ifade eder. Yani: argumentsNumber = 5, belirli bir bağımsız değişken anlamına gelir, ancak numberOfArguments değil.

main (int maxArgumentsIndex, char ** bağımsız değişkenler).

Bu belirsizliği ortadan kaldırır. Buna dizin demek, olumsuz durum belirsizliğini ortadan kaldırır ve ayrıca ne olduğunu ve ek olarak nasıl kullanılacağını açıklar. Ayrıca, ingilizce ifadesiyle, bir maksimum değerinin mutlak olduğunu ve bu değeri değiştiren kod yazarken tuhaf hissettireceğini ima eder (const olmalıdır). 'argümanlar' burada anlamlıdır, çünkü çoğuldur, ne olduğunu ve nasıl kullanılması gerektiğini açıklar. Bu şekilde yorumlamak bile tehlikeli olabilir çünkü bir İndeks bir Count / NumberOf'un -1'i. 5 argüman maxIndex 4 değerini verir !!

Başka herhangi bir işlev ve tamamen kullanacağım:

void işlevi (const unsigned int maxArgumentsIndex, const char ** argümanlar)

Tüm durumlar uzun el tanımlayıcıları hak etmez. Aslında, bazen kısa bir el daha fazla okunabilirlik sağlar, özellikle Vec3f, Matrix, Quaternion, vb. Gibi matematik dersleri yazarken ... Neredeyse her zaman dilbilimsel dil yerine matematik dilini eşleştirmeye çalışacağım . float x, y, z vrs. float xComponent ve benzerleri.

Tüm bunların bir stil seçimi olduğunu anlıyorum, ancak seçimlerin bilincinde olmak uzun vadede gerçekten yardımcı olacaktır. Diziler çoğul biçimde yazılmadığında tecrübeli programcıların canını sıkacağını garanti ederim, ama yine de ana varoluşun özel bir düzyazıdır;)


2

C Standartlarına göre, Evet yeniden adlandırabilirsiniz, Hiçbir şey etkilenmeyecek. Anladığım kadarıyla, C Dilinde, varsayılan Anahtar Kelime / türler / simge adları amaç / kullanım ile tanımlandı, bu nedenle aynı şekilde adlar

argc --> argument count

argv --> argument vector

bu da kullanım açısından mantıklıdır, Böylece istediğiniz herhangi bir isme değiştirebilirsiniz. Reserved names

GCC'de program yürütme main, parametrelerine bağlı olmadığı işlev adıyla başlar .

Mikro denetleyiciler için bağımsız bir program yazdığınızda, adla uğraşmanıza gerek kalmaz, mainbunun yerine kendi adınızı tanımlayabilir nameve Assembly giriş noktasını işlevinizi gösterecek şekilde değiştirebilirsiniz. Denetleyici derleyicisine ve önceden tanımlanmış denetleyici kaynak kodunun kullanılabilirliğine bağlıdır. Bunu Freescale denetleyicisinde Code-warrior altında yaptım.

Notum:

Kodu daha görünür ve okunabilir hale getirmek için ortak standartları / kod stilini takip etmek daha iyidir


0

Derleyici söz konusu olduğu sürece güvenlidir.

Bunun neden olabileceği tek sorun kafa karışıklığıdır. Kodunuzu okuyan kişiler, bu iki değişkenin standart adlarına sahip olmasını bekler. Hatta bunun gibi bir şey bile yapabilirsiniz:

int main(int foo, char ** bar)
{
    int argc;
    float argv;

Ama bunun ne kadar kötü bir uygulama olacağını söylememe gerek olduğunu sanmıyorum.


-1

Değişken adlarını sevmiyorsanız, neden onları #define makrosu ile değiştirmiyorsunuz :

#define yourCounterName argc
#define yourVectorName  argv 

Herhangi bir risk almayacak ve "temiz bir çözüm" üretmeyeceksiniz.


Bunlar sabit değil, sadece ikame.
David Dunham
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.