Menggunakan avr-gcc sebagai contoh, tipe int ditentukan selebar 16-bit. Melakukan operasi pada operan 8-bit dalam C menghasilkan operan tersebut dikonversi ke tipe int 16-bit karena promosi integer dalam C. Apakah ini berarti bahwa semua operasi aritmatika 8-bit pada AVR akan memakan waktu lebih lama jika ditulis dalam C daripada jika ditulis dalam rakitan karena promosi bilangan bulat C?
microcontroller
avr
c
pr871
sumber
sumber
Jawaban:
Singkat cerita:
Promosi integer ke 16 bit selalu terjadi - standar C memberlakukan ini. Tetapi kompiler diperbolehkan untuk mengoptimalkan perhitungan kembali ke 8 bit (kompiler sistem embedded biasanya cukup bagus dalam optimasi seperti itu), jika dapat disimpulkan bahwa tanda akan sama dengan yang seharusnya jika jenis telah dipromosikan.
Ini tidak selalu terjadi! Perubahan penandatanganan implisit yang disebabkan oleh promosi integer adalah sumber bug yang umum dalam sistem embedded.
Penjelasan terperinci dapat ditemukan di sini: Aturan promosi tipe implisit .
sumber
seperti yang diharapkan fun1 adalah semua ints begitu juga matematika 16 bit
Meskipun secara teknis salah karena merupakan tambahan 16 bit yang dipanggil oleh kode, bahkan tidak dioptimalkan kompiler ini menghapus adc karena ukuran hasil.
tidak benar-benar terkejut di sini promosi terjadi, kompiler tidak terbiasa melakukan ini tidak yakin versi apa yang membuat ini mulai terjadi, berlari ke awal ini dalam karir saya dan meskipun kompiler mempromosikan rusak (seperti di atas), melakukan promosi meskipun saya menyuruhnya melakukan matematika uchar, tidak terkejut.
dan yang ideal, saya tahu itu 8 bit, ingin hasil 8 bit jadi saya hanya menyuruhnya melakukan 8 bit sepanjang jalan.
Jadi secara umum lebih baik untuk bertujuan untuk ukuran register, yang idealnya ukuran int (u), untuk 8 bit mcu seperti ini penulis kompiler harus membuat kompromi ... Intinya jangan membuat kebiasaan menggunakan uchar untuk matematika yang Anda tahu tidak perlu lebih dari 8 bit seperti ketika Anda memindahkan kode itu atau menulis kode baru seperti itu pada prosesor dengan register yang lebih besar sekarang kompiler harus mulai menutupi dan menandatangani perluasan, yang beberapa lakukan secara asli dalam beberapa instruksi, dan yang lainnya tidak.
memaksa 8 bit lebih mahal. Saya curang sedikit / banyak, akan membutuhkan contoh yang sedikit lebih rumit untuk melihat lebih banyak tentang ini secara adil.
EDIT berdasarkan diskusi komentar
tidak ada kejutan. Meskipun mengapa pengoptimal meninggalkan instruksi tambahan itu, bisakah Anda tidak menggunakan ldi pada r19? (Saya tahu jawabannya ketika saya menanyakannya).
EDIT2
untuk avr
untuk menghindari kebiasaan buruk atau tidak perbandingan 8 bit
jelas optimisasi hanya membutuhkan waktu satu detik untuk mencoba dengan kompiler Anda sendiri untuk melihat bagaimana perbandingannya dengan output saya, tetapi bagaimanapun:
Dan ya menggunakan byte untuk variabel ukuran byte, tentu saja pada avr, pic, dll, akan menghemat memori Anda dan Anda ingin benar-benar mencoba untuk melestarikannya ... jika Anda benar-benar menggunakannya, tetapi seperti yang ditunjukkan di sini sesedikit mungkin adalah akan berada dalam memori, sebanyak mungkin dalam register, sehingga penghematan flash datang dengan tidak memiliki variabel tambahan, penghematan ram mungkin atau mungkin tidak nyata ..
sumber
unsigned char
sehingga memiliki untuk melakukan promosi untuk 16 bit, seperti yang diperlukan menurut standar.(a<<8)|b
selalu salah untuk sistem mana pun yangint
memiliki 16 bit.a
akan dipromosikan secara implisitint
yang ditandatangani. Dalam kasusa
memegang nilai dalam MSB, Anda akhirnya menggeser data itu ke bit tanda nomor 16 bit, yang memanggil perilaku tidak terdefinisi.Tidak harus, karena kompiler modern melakukan pekerjaan yang baik dalam mengoptimalkan kode yang dihasilkan. Misalnya, jika Anda menulis di
z = x + y;
mana semua variabel beradaunsigned char
, kompiler harus mempromosikannyaunsigned int
sebelum melakukan perhitungan. Namun, karena hasil akhirnya akan sama persis tanpa promosi, kompiler akan menghasilkan kode yang hanya menambahkan variabel 8-bit.Tentu saja, ini tidak selalu terjadi, misalnya hasil
z = (x + y)/2;
tergantung pada byte atas, sehingga promosi akan berlangsung. Itu masih bisa dihindari tanpa menggunakan perakitan dengan mengembalikan hasil antaraunsigned char
.Beberapa inefisiensi semacam itu dapat dihindari dengan menggunakan opsi kompiler. Sebagai contoh, banyak kompiler 8-bit memiliki pragma atau saklar baris perintah agar sesuai dengan tipe enumerasi dalam 1 byte, alih-alih
int
seperti yang disyaratkan oleh C.sumber
int
, karenachar
kemungkinan besar tidak memiliki peringkat konversi yang sama sepertiint
pada platform apa pun.int
(ya tidak konsisten). C11 6.7.2.2Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined...