Ketika pointer ke jenis tertentu (misalnya int
, char
, float
, ..) bertambah, nilainya meningkat dengan ukuran jenis data. Jika sebuah void
penunjuk yang menunjuk ke data ukuran x
bertambah, bagaimana bisa sampai ke titik x
byte di depan? Bagaimana kompiler tahu untuk menambah x
nilai pointer?
c
pointers
void-pointers
pointer-arithmetic
Siva Sankaran
sumber
sumber
void
pointer yang menunjuk ke data ukuranx
bertambah, bagaimana ia bisa sampai titikx
byte di depan?" Tidak. Mengapa orang-orang yang memiliki pertanyaan semacam itu tidak dapat mengujinya sebelum bertanya - Anda tahu, setidaknya sampai titik minimum di mana mereka memeriksa apakah itu benar-benar dikompilasi, yang tidak. -1, tidak percaya ini dapat +100 dan -0.Jawaban:
Kesimpulan akhir: aritmatika pada a
void*
adalah ilegal di C dan C ++.GCC memungkinkannya sebagai ekstensi, lihat Aritmatika pada
void
- dan Function-Pointer (perhatikan bahwa bagian ini adalah bagian dari bab "C Extensions" pada manual). Dentang dan ICC kemungkinan memungkinkanvoid*
aritmatika untuk tujuan kompatibilitas dengan GCC. Kompiler lain (seperti MSVC) melarang aritmatika aktifvoid*
, dan GCC melarangnya jika-pedantic-errors
flag ditentukan, atau jika-Werror-pointer-arith
flag ditentukan (flag ini berguna jika basis kode Anda juga harus dikompilasi dengan MSVC).The C Standard Speaks
Kutipan diambil dari draft n1256.
Deskripsi standar tentang status operasi penjumlahan:
Jadi, pertanyaannya di sini adalah apakah
void*
pointer ke "tipe objek", atau setara, apakahvoid
"tipe objek". Definisi untuk "tipe objek" adalah:Dan standar didefinisikan
void
sebagai:Karena
void
ini adalah tipe yang tidak lengkap, itu bukan tipe objek. Karenanya itu bukan operan yang valid untuk operasi penambahan.Karena itu Anda tidak dapat melakukan aritmatika pointer pada
void
pointer.Catatan
Awalnya, ia berpikir bahwa
void*
aritmatika diizinkan, karena bagian-bagian dari standar C ini:Namun,
Jadi ini berarti yang
printf("%s", x)
memiliki arti yang sama apakahx
memiliki tipechar*
atauvoid*
, tetapi itu tidak berarti bahwa Anda dapat melakukan aritmatika pada avoid*
.Catatan editor: Jawaban ini telah diedit untuk mencerminkan kesimpulan akhir.
sumber
void*
pointer aritmatika tidak diperbolehkan. GCC memiliki ekstensi yang memungkinkan untuk melakukan ini.void*
aritmatika (setidaknya secara default).Aritmatika pointer tidak diizinkan pada
void*
pointer.sumber
void
adalah tipe tidak lengkap yang tidak pernah dapat diselesaikan dengan definisi.melemparkannya ke pointer char peningkatan incaran Anda maju x byte di depan.
sumber
char
, menambah denganx
, dan kemudian menafsirkan kembali nilai baru karena beberapa jenis lainnya adalah perilaku yang tidak berguna dan tidak terdefinisi.man 3 qsort
seharusnya memilikivoid qsort(void *base, size_t nmemb, size_t size, [snip])
, maka Anda tidak memiliki cara untuk mengetahui "tipe yang tepat"Standar C tidak memungkinkan aritmetika void pointer. Namun, GNU C diperbolehkan dengan mempertimbangkan ukuran void tersebut
1
.Standar C11 §6.2.5
Paragraf - 19
Program berikut berfungsi dengan baik di kompiler GCC.
Mungkin kompiler lain menghasilkan kesalahan.
sumber
Anda tidak dapat melakukan aritmatika penunjuk pada
void *
tipe, untuk alasan yang tepat ini!sumber
Anda harus melemparkannya ke jenis pointer lain sebelum melakukan aritmatika pointer.
sumber
Pointer kosong dapat mengarah ke potongan memori apa pun. Karenanya kompiler tidak tahu berapa byte yang bertambah / berkurang ketika kita mencoba pointer aritmatika pada void pointer. Oleh karena itu void pointer harus menjadi typecast pertama ke jenis yang diketahui sebelum mereka dapat terlibat dalam aritmatika pointer apa pun.
sumber
Kompiler tahu berdasarkan tipe pemain. Diberikan
void *x
:x+1
menambahkan satu byte kex
, pointer menuju ke bytex+1
(int*)x+1
menambahkansizeof(int)
byte, pointer menuju ke bytex + sizeof(int)
(float*)x+1
addressizeof(float)
byte, dll.Meskipun item pertama tidak portabel dan bertentangan dengan Galateo dari C / C ++, itu tetap benar dalam bahasa C, artinya ia akan dikompilasi ke sesuatu pada kebanyakan kompiler yang mungkin memerlukan bendera yang sesuai (seperti -Wpointer-arith)
sumber
Althought the first item is not portable and is against the Galateo of C/C++
Benar.it is nevertheless C-language-correct
Salah. Ini adalah pemikiran ganda! Aritmatika pointer aktifvoid *
secara sintaksis, tidak boleh dikompilasi, dan menghasilkan perilaku yang tidak terdefinisi jika itu. Jika seorang programmer yang ceroboh dapat membuatnya dikompilasi dengan menonaktifkan beberapa peringatan, itu bukan alasan.unsigned char*
ke misalnya menambahkansizeof
nilai ke pointer.