Saya mendefinisikan dua variabel:
uint8_t a[2];
uint16_t b;
Selanjutnya saya ingin menggunakan a
sebagai variabel tipe uint16_t
, mis
b = (uint16_t)a;
Tapi ini salah! Program saya tidak berfungsi dengan benar dengan kode tersebut. Semua adalah OK ketika saya mengganti b
ke uint8_t b[2]
dan operasi penggunaan elementwise.
Mengapa?
Jawaban:
a
adalah pointer ke array byte. Jika Anda melemparkannya ke uint16_t dan menetapkannyab
, makab
akan berisi alamat basis array (tempat disimpannya) di SRAM. Jika Anda ingin memperlakukan dua byte arraya
sebagai integer, maka gunakan union seperti yang disarankan oleh user14284, tetapi perlu diketahui bahwa union akan mewakili array byte dalam pemesanan byte memori arsitektur (dalam AVR yang akan sedikit -endian, yang berarti byte 0 adalah byte paling signifikan). Cara menulis itu dalam kode adalah:Cara lain untuk melakukan ini tanpa menggunakan gabungan adalah dengan melemparkan
a
ke pointer uint16_t dan kemudian dereferensi seperti itu:Jika Anda menggunakan buffer untuk menyimpan data big endian (mis. Urutan byte jaringan), maka Anda perlu byte-swap untuk menggunakan salah satu dari teknik ini. Cara untuk melakukannya tanpa cabang atau variabel sementara adalah:
Kebetulan ini bukan AVR atau bahkan masalah yang hanya tertanam. Kode jaringan level aplikasi yang ditulis untuk PC biasanya memanggil fungsi-fungsi yang disebut
htonl
,htons
(host to network, varian 32-dan 16-bit) danntohl
,ntohs
(network to host, varian 32-dan 16-bit) yang implementasinya bergantung pada arsitektur target, apakah mereka menukar byte atau tidak (dengan asumsi bahwa byte yang dikirimkan 'on the wire' selalu big-endian ketika mereka adalah bagian dari kata-kata multi-byte).sumber
a
' sendiri adalah sebuah pointer.-fno-strict-aliasing
.Jika maksud Anda adalah menggabungkan dua variabel 8-bit menjadi variabel 16-bit, gunakan a
union
. Jika Anda ingin memasukkan satu anggotaa
ke dalamb
, maka tentukan elemen larik mana yang ingin Anda gunakan.sumber
Pada kode Anda, Anda hanya melemparkan pointer ke array.
Anda harus memberikan nilai yang ditunjukkan
a
.Saya tidak pernah menggunakan AVR tetapi jika Anda bekerja dengan arsitektur 16 bit Anda harus memastikan bahwa kata tersebut selaras. Gagal melakukan ini dapat menghasilkan pengecualian.
sumber
Setiap anggota yang merupakan nomor 8-bit. Itu tidak bisa menampung sesuatu yang lebih besar. Casting ke 16-bit tidak melakukan apa pun untuk a . Itu hanya mengekstraksi nilai apa pun yang mungkin bisa dimiliki, dan mengubahnya menjadi 16 bit sehingga cocok dengan format b ketika nilai disimpan di sana.
Anda bahkan tidak merujuk ke anggota a . Anda harus menggunakan [0] atau [1] (dan bukan [2]!). Jika Anda menggunakan sebuah dengan sendirinya, Anda hanya mendapatkan alamat itu. (Tangkapan bagus, Bruno).
Mendeklarasikan sebuah menjadi array dua angka 8-bit tidak membuat sejumlah 16-bit, baik. Anda dapat melakukan beberapa hal secara terprogram untuk menyimpan dan mengambil nilai 16-bit menggunakan urutan 8-bit, tetapi tidak seperti yang Anda pikirkan.
sumber
Jika Anda ingin mengubah byte
a
menjadi nilai 16 bit, dan representasi tersebut adalah little-endian (8 bit nilai yang lebih rendah berasal dari byte pertama), lakukanUntuk representasi big-endian lakukan
Hindari menggunakan cast pointer atau serikat pekerja untuk melakukan ini, karena itu mengarah pada masalah portabilitas.
sumber