Apa yang terjadi jika perilaku C ++ yang tidak ditentukan memenuhi perilaku yang didefinisikan C?


10

Saya memiliki *.cppfile yang saya kompilasi dengan C ++ (bukan kompiler C). Fungsi yang berisi bergantung pada pemain (lihat baris terakhir) yang tampaknya didefinisikan dalam C (tolong perbaiki jika saya salah!), Tetapi tidak dalam C ++ untuk jenis khusus ini.

[...] C++ code [...]

struct sockaddr_in sa = {0};
int sockfd = ...;
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
bind(sockfd, (struct sockaddr *)&sa, sizeof sa);

[...] C++ code [...]

Karena saya mengkompilasi ini dalam file C ++, apakah ini perilaku yang sekarang didefinisikan atau tidak terdefinisi? Atau apakah saya perlu memindahkan ini ke *.cfile, untuk membuatnya menjadi perilaku yang didefinisikan?


1
Ekstensi file tidak memiliki arti; hanya jika Anda mengompilasinya sebagai C atau C ++.
Fredrik

1
Jenis yang sesuai tidak diwarisi satu sama lain dan tidak memiliki hubungan dan itu tidak terdefinisi dalam C ++
Daniel Stephens

1
Biasanya, jika file memiliki .cekstensi, kompiler C dipanggil secara otomatis.
Igor R.

1
Saya melakukan trik itu sepanjang waktu dalam kode C ++. Tidak tahu mengapa itu tidak berhasil untuk Anda. Tidak ada tajuk di suatu tempat?
user4581301

3
@DanielStephens Program ini tidak pernah mencoba untuk menunjuk pointer. Pemain itu sendiri diperbolehkan , dereferencing - hanya kadang-kadang. Jika sisi C benar melemparkan pointer kembali ke tipe nyata maka semuanya akan baik-baik saja. Masalah dengan casting akan terjadi jika tipe-tipe tersebut memiliki persyaratan pelurusan yang berbeda.
user7860670

Jawaban:


6

Ini didefinisikan dalam C ++ dan C. Ini tidak melanggar peraturan aliasing yang ketat karena tidak mengubah pointer yang dihasilkan.

Inilah kutipan dari C ++ (terima kasih kepada @interjay dan @VTT) yang memungkinkan ini:

Pointer objek dapat secara eksplisit dikonversi ke objek pointer dari tipe yang berbeda.

Inilah kutipan dari C (terima kasih @StoryTeller) yang memungkinkan ini:

Pointer ke tipe objek dapat dikonversi ke pointer ke tipe objek yang berbeda.

Ini menentukan bahwa satu tipe pointer dapat dikonversi ke tipe pointer lain (dan kemudian secara opsional dikonversi kembali) tanpa konsekuensi.

Dan inilah kutipan dari POSIX yang memungkinkan kasus khusus ini:

The sockaddr_in struktur digunakan untuk menyimpan alamat untuk keluarga alamat Internet. Pointer ke jenis ini harus dilemparkan oleh aplikasi ke struct sockaddr * untuk digunakan dengan fungsi soket.

Karena fungsi ini ( bind) adalah bagian dari pustaka standar C, apa pun yang terjadi di dalam (khususnya, menandakan pointer tipe-dicor) tidak memiliki perilaku yang tidak ditentukan.


Untuk menjawab pertanyaan yang lebih umum:

C dan C ++ adalah dua bahasa yang berbeda. Jika sesuatu didefinisikan dalam C tetapi tidak dalam C ++, itu didefinisikan dalam C tetapi tidak dalam C ++. Tidak ada kompatibilitas yang tersirat antara kedua bahasa yang akan mengubah itu. Jika Anda ingin menggunakan kode yang didefinisikan dengan baik dalam C tetapi tidak terdefinisi dalam C ++, Anda harus menggunakan kompiler C untuk mengkompilasi kode itu.


1
@interjay Bisakah Anda mencadangkannya dengan kutipan dari standar (baik C atau C ++ baik-baik saja)?
SS Anne


1
@StoryTeller Terima kasih. Sebaliknya, menambahkan versi HTTP.
SS Anne

2
Bisa dibilang ini adalah cacat dalam standar POSIX - argumen kedua bindharus a const void *, tetapi bindmendahului keberadaan voiddalam bahasa C (dan keberadaan C ++ sama sekali). Mereka memperbaruinya di beberapa titik untuk menambahkan const, tetapi tidak pernah memperbaiki tipe dasar.
Chris Dodd

1
Saya dapat merekomendasikan pembicaraan ini youtube.com/watch?v=_qzMpk-22cc Saya masih tidak yakin apakah ini memvalidasi jawabannya, atau jika itu benar-benar mengatakan sebaliknya: -o C ++ adalah mimpi buruk .. lol
Daniel Stephens

-3

Panggilan antara kode C dan C ++ semua memanggil Perilaku Tidak Terdefinisi, dari sudut pandang standar masing-masing, tetapi sebagian besar platform menentukan hal-hal seperti itu.

Dalam situasi di mana bagian dari Standar C atau C ++ dan dokumentasi implementasi bersama-sama mendefinisikan atau menggambarkan suatu tindakan, tetapi bagian lain mencirikannya sebagai Tidak Terdefinisi, implementasi diizinkan untuk memproses kode dengan cara apa pun yang paling sesuai dengan kebutuhan pelanggan mereka atau - jika mereka tidak peduli dengan kebutuhan pelanggan - busana apa pun yang mereka sukai. Fakta bahwa Standar menganggap hal-hal seperti di luar yurisdiksi mereka tidak menyiratkan penilaian kapan dan / atau bagaimana implementasi yang mengklaim kesesuaian untuk berbagai tujuan harus diharapkan untuk memprosesnya secara bermakna, tetapi beberapa pembuat kompiler menganut mitos yang berlaku.


Paragraf pertama: "Panggilan antara kode C dan C ++ semua memanggil Perilaku Tidak Terdefinisi" Bahkan jika ada yang namanya "memohon perilaku tidak terdefinisi" (yang tidak ada), ini masih tidak masuk akal.
Lightness Races di Orbit

Paragraf kedua: tidak tahu apa yang ingin Anda katakan.
Lightness Races di Orbit

@LightnessRacesinOrbit Saya pikir jawaban ini adalah hasil dari penambahan tag [pengacara bahasa] saya pada pertanyaan. Saya sekarang berpikir lebih baik tentang itu (jawabannya cenderung terlalu harfiah) dan menghapusnya.
SS Anne

1
@ JL2210 Saya tidak berpikir itu salahmu.
Lightness Races dalam Orbit
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.