İnt argc, char * argv [] ne anlama geliyor?


508

Birçok C ++ IDE ve derleyicisinde, sizin için ana işlevi oluşturduğunda, şöyle görünür:

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

Ben sadece bir komut satırı derleyici ile IDE olmadan C ++ kod, ben şunu yazın:

int main()

herhangi bir parametre olmadan. Bu ne anlama geliyor ve programım için hayati mi?


47
Programınız komut satırı argümanlarını yoksayacaksa, yazdıklarınız iyi olur. Programınızın komut satırı bağımsız değişkenlerini işlemesi gerekiyorsa, IDE bunu doğru yapıyor demektir.
Jonathan Leffler

30
Bilgisayar korsanları için bir ipucu: int main(int argc, char* argv[], char* envp[])son argümanı bildirmeyi ve yazdırmayı deneyin . ;)
ulidtko

7
@ulidtko, programlarına güvenlik açığı getirmek için yeni başlayanlar öğretmeniz iyi değil;)
Gab 是 好人

13
@Gab ortam değişkenlerinin basit yazdırılması nasıl güvenlik açığına yol açar? Sadece renkli dizeleri system()çağrılara, DB sorgularına vb.
ulidtko

2
@ulidtko İlginç .. Argüman kullanırken neden renkli dizeleri, db sorgularını vb. geçmek zorunda kalmayacağınızı açıklayabilir misiniz char **envp?
Usta James

Yanıtlar:


651

argvve argckomut satırı bağımsız değişkenlerinin main()C ve C ++ ' da nasıl iletildiği .

argctarafından işaret edilen dizelerin sayısı olacaktır argv. Neredeyse tüm uygulamalar, programın adını diziye önceliklendireceğinden, bu (uygulamada) artı argüman sayısı olacaktır.

Değişkenler adlandırılır argc( argüman sayımı ) ve argv( argüman vektör Kongre tarafından), ancak herhangi bir geçerli bir tanımlayıcı verilebilir:int main(int num_args, char** arg_strings) aynı derecede geçerlidir.

int main()Komut satırı bağımsız değişkenlerini işlemek istemiyorsanız, bunlar tamamen atlanabilir .

Aşağıdaki programı deneyin:

#include <iostream>

int main(int argc, char** argv) {
    std::cout << "Have " << argc << " arguments:" << std::endl;
    for (int i = 0; i < argc; ++i) {
        std::cout << argv[i] << std::endl;
    }
}

Irade ./test a1 b2 c3çıkışı ile çalıştırmak

Have 4 arguments:
./test
a1
b2
c3

8
argc0 olabilir, bu durumda argvNULL olabilir. Standart AFAIK tarafından izin verilir. Bunu pratikte yapan bir sistemi hiç duymadım, ama kesinlikle var olabilirdi ve herhangi bir standardı ihlal etmeyecekti.
Chuck

77
@Chuck: "değeri argv[argc]0 olacaktır" (C ++ 03 §3.6.1 / 2) argvolduğu için boş olamaz.
James McNellis

20
@Chuck: C (en az C99) aynı şarta sahiptir.
James McNellis

2
Eklemeliyim diye düşündüm, bu bazı sistemlerde aynı, ancak bazı zamanlarda soyutlanmışlar. Örneğin, Pascal / Delphi / Lazarus'ta; ParamStr ve ParamCount (bellek bana doğru hizmet ediyorsa). Demek istediğim, (eğer varsa) diğer dillerde / oseslerde yerel uygulamalar yazdığınızda, yukarıdakilerin kullanmanız için tanımlanmış olması ve bunların desteklendiği tüm sistemlerde aynı şekilde (sayım / dize listesi) mükemmel bir şekilde çalışması onlar.
Christian

8
@ EmilVikström Hayır, bu muhtemelen bir segfault ile sonuçlanan ciddi bir hatadır. *NULLkesinlikle eşit değildir NULL.
meagar

52

argckomut satırından programınıza iletilen bağımsız değişkenlerin sayısı ve bağımsız değişken argvdizisidir.

Bunların sayısını bilerek argümanlar arasında dolaşabilirsiniz:

for(int i = 0; i < argc; i++)
{
    // argv[i] is the argument at index i
}

19

Programınızı bu şekilde çalıştırdığınızı varsayalım ( shsözdizimi kullanarak ):

myprog arg1 arg2 'arg 3'

Ana ünitenizi int main(int argc, char *argv[])(çoğu ortamda) olarak ilan ettiyseniz main(), aşağıdaki gibi çağrılacaksınız:

p = { "myprog", "arg1", "arg2", "arg 3", NULL };
exit(main(4, p));

Ancak, ana üssünüzü olarak ilan ettiyseniz int main(),

exit(main());

ve argümanları iletemezsiniz.

Dikkat edilmesi gereken iki ek şey:

  1. Bunlar sadece iki standart zorunlu imzadır main. Belirli bir platform fazladan argümanları veya farklı bir dönüş türünü kabul ederse, bu bir uzantıdır ve taşınabilir bir programda kullanılmamalıdır.
  2. *argv[]ve **argvtam olarak eşdeğerdir, böylece int main(int argc, char *argv[])olarak yazabilirsiniz int main(int argc, char **argv).

2
Teknik olursak , uygulamanın önceden tanımlanmış iki sürümü sağlaması şartıyla, uygulamanın basic.start.main/2tanımlanmış ek sürümlerine açıkça izin veririz main(). Yani, tam olarak uygun değiller . En yaygın olanı, envphem C hem de C ++ 'da çok iyi bilinen , C standardının J.5 (Ortak uzantılar) bölümündeki ilk giriş olmasıdır .
Justin Time - Monica'yı

1
Güzel pedantry @ Justin için teşekkürler. Yanıt daha doğru olacak şekilde güncellendi.
Toby Speight

Hiçbir fikrim yok - En az tekrarlanabilir bir örnek oluşturmanızı ve sormanızı öneririm (sürecin kendinize cevap vermenize yardımcı olmak için yeterli olmadığını varsayarak).
Toby Speight

9

Başlatıldığında mainprograma sağlanan komut satırı parametrelerini temsil eden parametreler. argcParametre komut satırı değişkenleri sayısını temsil eder ve char *argv[]komut hattı üzerinde ayrı ayrı bağımsız değişkenleri temsil dizeleri (karakter işaretçiler) bir dizidir.


2
Argv [] her zaman bir boş gösterici olarak argv [arg] 'a sahiptir. ve Argv [0] her zaman bir
null

3
@ user3629249: Mutlaka değil; argv[0]C programını başlatan program ne olursa olsun argv[0]. Bash durumunda, genellikle yürütülebilir dosyanın yol adıdır (belki de her zaman), ancak Bash diğer programları çalıştıran tek program değildir. Kullanımı eksantrik olsa o, permissisble geçerli: char *args[] = { "cat", "/dev/null", "/etc/passwd", 0 }; execv("/bin/ls", args);. Birçok sistemde, çalıştırılabilir olsa bile , programın gördüğü değer argv[0]olacaktır . cat/bin/ls
Jonathan Leffler

7

mainFonksiyon iki parametre var olabilir argcve argv. argcbir integer ( int) parametresidir ve programa iletilen bağımsız değişkenlerin sayısıdır.

Program adı her zaman ilk argümandır, bu nedenle bir program için en az bir argüman olacak ve minimum değeri bir argcolacaktır. Ancak bir programın iki argümanı varsa, değeri argcüç olacaktır.

Parametre argvbir dize dizisini gösterir ve bağımsız değişken vektörü olarak adlandırılır . İşlev argümanlarının tek boyutlu bir dize dizisidir.


5
int main();

Bu basit bir deklarasyon. Herhangi bir komut satırı argümanı alamaz.

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

Bu bildirim, programınızın komut satırı bağımsız değişkenleri alması gerektiğinde kullanılır. Böyle çalıştığında:

myprogram arg1 arg2 arg3

argcveya Bağımsız Değişken Sayısı, 4 (dört bağımsız değişken) olarak ayarlanır ve argvveya Bağımsız Değişken Vektörleri, "myprogram", "arg1", "arg2" ve "arg3" dizelerine işaretçilerle doldurulur. Program çağırma ( myprogram) argümanlarına dahil edilir!

Alternatif olarak şunları kullanabilirsiniz:

int main(int argc, char** argv);

Bu da geçerlidir.

Ekleyebileceğiniz başka bir parametre var:

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

envpParametresi de ortam değişkenlerini içerir. Her girdi şu biçimi izler:

VARIABLENAME=VariableValue

bunun gibi:

SHELL=/bin/bash    

Ortam değişkenleri listesi boş.

ÖNEMLİ: Doğrudan aramalarda herhangi bir değer argvveya envpdeğer KULLANMAYIN system()! Kötü niyetli kullanıcılar, ortam değişkenlerini komut satırı komutlarına ayarlayabildiği ve (potansiyel olarak) büyük hasara neden olabileceği için bu büyük bir güvenlik açığıdır. Genel olarak, sadece kullanmayın system(). C kütüphaneleri aracılığıyla neredeyse her zaman daha iyi bir çözüm uygulanmaktadır.


3

İlk parametre sağlanan bağımsız değişkenlerin sayısı ve ikinci parametre bu bağımsız değişkenleri temsil eden dizelerin listesidir.


7
argv [0] içindeki ilk giriş bir argüman değil program adıdır
user3629249

@ user3629249 Program yolu ile program adı. ;)
Usta James

1

Her ikiside

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

bir C veya C ++ programının giriş noktasının yasal tanımlarıdır. Stroustrup: C ++ Stil ve Teknik SSS , ana işleviniz için mümkün veya yasal olan bazı varyasyonları detaylandırır.


4
Uyumluluk ve okunabilirlik için ... int main()==> int main(void)... geçersiz kılmak isteyebilir . Tüm eski C sürümleri void işlevlerinin bildirimde boş bir parametre listesine sahip olup olmadığını bilmiyorum.
dylnmc

1
@dylnmc herhangi bir okunabilirlik kazancı sağlamaz ve tüm C ++ sürümlerinde tam olarak eşdeğerdir. Sadece C'de bunun bir farkı vardır, ancak tanımlarında değil, sadece beyanlarda.
Ruslan

@Ruslan Üzgünüm, ben sadece C öğrenirken yayınladım ve C'nin ilk sürümlerinde voidgerekli olduğunu okumuş olabilirim . Bana bu konuda alıntı yapma ve şimdi bunun biraz aptalca bir yorum olduğunu biliyorum. Yine de acıtmaz.
dylnmc

argc <3 bir hata döndürürse ne olur? ne yanlış gidebilirdi?
AVI
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.