Pertanyaan Kasus yang dapat digunakan untuk menunjuk ke array dengan batas yang tidak ditentukan dalam C ++ (tidak dalam C)


Pertimbangkan kode berikut:

int main() {
    int (*p)[]; // pointer to array with unspecified bounds

    int a[] = {1};
    int b[] = {1,2};

    p = &a; // works in C but not in C++
    p = &b; // works in C but not in C++

    return 0;
}

Dalam C murni Anda dapat menetapkan pointer ke jenis alamat array dari berbagai dimensi. Tetapi dalam C ++ Anda tidak bisa. Saya menemukan satu kasus ketika kompiler memungkinkan menetapkan nilai ke penunjuk seperti itu:

struct C
{
    static int v[];
};

int main() 
{
    int (*p)[] = &C::v; // works in C++ if 'v' isn't defined (only declared)
    return 0;
}

Tetapi tidak dapat menemukan kasus yang berguna dari kode ini.

Adakah yang bisa memberikan contoh yang berguna (dalam C ++) dari pointer ke array dengan batas yang tidak ditentukan? Atau apakah hanya sisa sisa dari C?


32
2018-06-29 18:12


asal


Jawaban:


Penunjuk seperti itu tidak dapat berpartisipasi dalam aritmatika penunjuk, hal-hal yang berpotensi berguna yang masih bisa dilakukan adalah mendapatkan jenisnya decltype atau reinterpret_cast ke tipe pointer lain atau intptr_t. Ini karena bagian 3.9p6 mengatakan:

Tipe kelas (seperti "class X") mungkin tidak lengkap pada satu titik di unit terjemahan dan selesai nanti; jenisnya"class X"Adalah tipe yang sama di kedua titik. Jenis objek array yang dinyatakan mungkin merupakan array dari tipe kelas yang tidak lengkap dan karena itu tidak lengkap; jika tipe kelas selesai nanti di unit terjemahan, jenis array menjadi lengkap; jenis array pada kedua titik tersebut adalah tipe yang sama. Tipe objek array yang dinyatakan mungkin merupakan array dari ukuran yang tidak diketahui dan oleh karena itu tidak lengkap pada satu titik dalam unit terjemahan dan selesai nanti; jenis larik pada dua titik tersebut ("larik batas tidak diketahui T"dan" array N  T") adalah tipe yang berbeda. Jenis pointer ke array yang tidak diketahui ukurannya, atau tipe yang didefinisikan oleh deklarasi typedef menjadi array yang tidak diketahui ukurannya, tidak dapat diselesaikan.

5.3.1 mengatakan:

Catatan: tipuan melalui pointer ke tipe yang tidak lengkap (selain cv  void) adalah benar. Nilai yang diperoleh dapat digunakan dengan cara terbatas (untuk menginisialisasi referensi, misalnya); nilai ini tidak harus dikonversi ke nilai prvalue, lihat 4.1.

Karena peluruhan array-to-pointer dapat dilakukan pada laves array tanpa konversi sebelumnya ke rvalue, kode dyp yang tersisa dalam komentar adalah benar:

(*p)[i]

Aturan yang relevan, dari 4.2:

Sebuah lvalue atau rvalue dari array tipe N  T" atau msgstr "larik batas tidak dikenal dari T" dapat dikonversi ke prvalue tipe "pointer ke T". Hasilnya adalah pointer ke elemen pertama dari array.


12
2018-06-29 21:15



Saya pikir kompilator harus menerimanya (terlepas dari pengaturan -O) karena definisi statis dapat disediakan oleh unit kompilasi lain. (Ini mungkin penyimpangan pragmatis dari standar - saya bukan ahli C ++.) Cuplikan yang diposting dapat dikompilasi, tetapi tidak lengkap dan tidak dapat dibawa ke eksekusi tanpa definisi anggota statis.

File c.h:

struct C {
    static int v[];
};

File x.cpp

#include "c.h"
#include <iostream>
int main(){
    int (*p)[] = &C::v; // works in C++ if 'v' isn't defined (only declared)
    std::cout << *((int*)p) << std::endl; 
    return 0;
}

File y.cpp

#include "c.h"
int C::v[3] = {1,2,3};

Dikompilasi dan ditautkan menggunakan (dont-tell-me-it-old) g ++ 4.3.3. Cetakan 1.

Dan: ya saya tahu itu adalah C cast.


2
2018-06-29 20:05