Pertanyaan Apakah argv [n] dapat ditulis?


C11 5.1.2.2.1 / 2 mengatakan:

Parameter argc dan argv dan string yang ditunjukkan oleh argv array harus   dapat dimodifikasi oleh program, dan mempertahankan nilai terakhir yang disimpan di antara program   startup dan terminasi program.

Interpretasi saya tentang ini adalah bahwa ia menetapkan:

int main(int argc, char **argv)
{
    if ( argv[0][0] )
        argv[0][0] = 'x';   // OK

    char *q;
    argv = &q;              // OK
}

Namun itu tidak mengatakan apa-apa tentang:

int main(int argc, char **argv)
{
    char buf[20];
    argv[0] = buf;
}

Aku s argv[0] = buf; diizinkan?

Saya dapat melihat (setidaknya) dua argumen yang mungkin:

  • Kutipan di atas sengaja disebutkan argv dan argv[x][y] tapi tidak argv[x], jadi maksudnya adalah itu tidak dapat dimodifikasi
  • argv adalah penunjuk ke non-const objek, sehingga dengan tidak adanya kata-kata spesifik yang bertentangan, kita harus menganggap mereka adalah objek yang dapat dimodifikasi.

32
2017-09-09 05:48


asal


Jawaban:


IMO, kode seperti argv[1] = "123"; adalah UB.


"Parameter argc dan argv dan string yang ditunjuk oleh array argv harus   dapat dimodifikasi oleh program, dan mempertahankan nilai terakhir yang disimpan di antara program   startup dan terminasi program. "C11dr §5.1.2.2.1 2

Ingat itu const datang ke C bertahun-tahun setelah penciptaan C.

Seperti char *s = "abc"; berlaku saat seharusnya const char *s = "abc";. Kebutuhan untuk const tidak diperlukan lagi terlalu banyak kode yang ada akan rusak dengan pengenalan const.

Begitupun, sekalipun argv hari ini harus dipertimbangkan char * const argv[] atau tanda tangan lainnya dengan const, kekurangan const dalam char *argv[] tidak lengkap menentukan const-Kebutuhan dari argv, argv[], atau argv[][]. Itu const-Kebutuhan perlu didorong oleh spesifikasi.

Dari bacaan saya, karena spek ini diam tentang masalah, itu adalah UB.

Perilaku tidak terdefinisi dinyatakan dalam Standar Internasional ini dengan kata-kata 'perilaku tidak terdefinisi' 'atau oleh penghilangan segala definisi perilaku eksplisit"§4 2


[sunting]:

main() adalah fungsi yang sangat khusus adalah C. Apa yang diperbolehkan dalam fungsi lain dapat diizinkan atau tidak diizinkan masuk main(). C detail spesifikasi atribut tentang parameternya yang diberikan tanda tangan int argc, char *argv[] yang seharusnya tidak perlu. main(), tidak seperti fungsi lain di C, dapat memiliki tanda tangan pengganti int main(void) dan berpotensi orang lain. main() bukan reentrant. Karena spesifikasi C menjelaskan cara apa yang dapat dimodifikasi: argc, argv, argv[][], masuk akal untuk mempertanyakan apakah argv[] dapat dimodifikasi karena kelalaiannya dari spec menegaskan kode yang bisa.

Mengingat keahlian khusus main() dan penghilangan menetapkan itu argv[] sebagai dimodifikasi, programmer konservatif akan memperlakukan greyness ini sebagai UB, menunggu klarifikasi spesifikasi C masa depan.


Jika argv[i] Modifiable pada platform tertentu, tentu saja kisaran i tidak boleh melebihi argc-1.

Sebagai "argv[argc] akan menjadi null pointer ", assignining argv[argc] untuk sesuatu selain NULL tampaknya merupakan pelanggaran.

Meskipun string dapat dimodifikasi, kode tidak boleh melebihi panjang string asli.

char *newstr = "abc";
if (strlen(newstr) <= strlen(argv[1])) 
  strcpy(argv[1], newstr);

6
2017-09-09 14:43



argc hanyalah sebuah intdan dapat dimodifikasi tanpa batasan apa pun.

argv dapat dimodifikasi char **. Itu artinya itu argv[i] = x adalah benar. Tapi itu tidak mengatakan apa-apa argv[i] menjadi dirinya sendiri dapat dimodifikasi. Begitu argv[i][j] = c menyebabkan perilaku tidak terdefinisi.

Itu getopt fungsi pustaka standar C tidak memodifikasi argc dan argv tetapi tidak pernah memodifikasi array arang yang sebenarnya.


0
2017-09-09 15:46



Jelas disebutkan itu argv dan argv[x][x] dapat dimodifikasi. Jika argv Modifiable maka dapat menunjuk ke elemen lain pertama dari array char dan karenanya argv[x] dapat menunjuk ke elemen pertama dari beberapa string lain. Akhirnya argv[x] juga dapat dimodifikasi dan itu bisa menjadi alasan bahwa tidak perlu menyebutkannya secara eksplisit dalam standar.


-1
2017-09-09 06:10



Jawabannya adalah argv adalah array dan ya, isinya dapat dimodifikasi.

Kuncinya adalah sebelumnya di bagian yang sama:

Jika nilai argc lebih besar dari nol, maka larik anggota argv [0] melalui   argv [argc-1] inklusif harus berisi pointer ke string, yang diberikan   nilai-nilai yang ditentukan oleh lingkungan host sebelum startup program.

Dari sini jelas bahwa argv harus dianggap sebagai array dengan panjang tertentu (argc). Kemudian * argv adalah pointer ke array tersebut, setelah membusuk ke pointer.

Baca dalam konteks ini, pernyataan yang menyatakan bahwa 'argv akan dapat dimodifikasi ... dan mempertahankan isinya' jelas bermaksud bahwa isi dari array tersebut dapat dimodifikasi.

Saya mengakui bahwa masih ada beberapa ambiguitas dalam kata-kata, khususnya mengenai apa yang mungkin terjadi jika argc dimodifikasi.


Hanya untuk memperjelas, yang saya katakan adalah bahwa saya membaca bahasa ini sebagai makna:

[isi dari] argv [array] dan string yang ditunjuk oleh array argv harus dapat dimodifikasi ...

Jadi baik pointer dalam array dan string yang mereka tunjuk berada dalam memori baca-tulis, tidak ada salahnya dilakukan dengan mengubahnya, dan keduanya mempertahankan nilai-nilai mereka untuk kehidupan program. Saya berharap bahwa perilaku ini dapat ditemukan di semua implementasi protokol runtime C / C ++ utama, tanpa kecuali. Ini bukan UB.

Ambiguitas adalah penyebutan argc. Sulit membayangkan tujuan apa pun atau implementasi apa pun di mana nilai argc (yang tampaknya hanya parameter fungsi lokal) tidak dapat diubah, jadi mengapa menyebutkannya? Standar dengan jelas menyatakan bahwa suatu fungsi dapat mengubah nilai parameternya, jadi mengapa memperlakukan argc secara khusus dalam hal ini? Ini adalah penyebutan argc yang tak terduga yang telah memicu kekhawatiran tentang argv, yang jika tidak akan berlalu tanpa komentar. Hapus argc dari kalimat dan ambiguitas menghilang.


-1
2017-09-11 13:59