Apa yang dilakukan ,
operator di C?
Apa yang dilakukan ,
operator di C?
Jawaban:
Ekspresi:
(expression1, expression2)
Ekspresi1 pertama dievaluasi, kemudian ekspresi2 dievaluasi, dan nilai ekspresi2 dikembalikan untuk seluruh ekspresi.
i
memiliki nilai 5, 4, 3, 2 atau 1. Ini hanya 0. Praktis tidak berguna kecuali ekspresi memiliki efek samping.
i = b, c;
setara dengan (i = b), c
karena karena penugasan =
memiliki prioritas lebih tinggi daripada operator koma ,
. Operator koma memiliki prioritas terendah dari semua.
expression1, expression2;
pertama expression1
dievaluasi, mungkin karena efek sampingnya (seperti memanggil fungsi), kemudian ada titik urutan, kemudian expression2
dievaluasi dan nilai dikembalikan ...
Saya telah melihat yang paling sering digunakan dalam while
loop:
string s;
while(read_string(s), s.len() > 5)
{
//do something
}
Ini akan melakukan operasi, kemudian melakukan tes berdasarkan efek samping. Cara lain adalah dengan melakukannya seperti ini:
string s;
read_string(s);
while(s.len() > 5)
{
//do something
read_string(s);
}
while (read_string(s) && s.len() > 5)
. Jelas itu tidak akan berhasil jika read_string
tidak memiliki nilai kembali (atau tidak memiliki nilai yang berarti). (Sunting: Maaf, tidak menyadari berapa usia kiriman ini.)
while (1)
dengan break;
pernyataan di dalam tubuh. Mencoba memaksa bagian break-out dari kode menjadi test sementara atau turun ke tes do-while, seringkali merupakan pemborosan energi dan membuat kode lebih sulit untuk dipahami.
while(1)
dan break
;
The operator koma akan mengevaluasi operan kiri, membuang hasilnya dan kemudian mengevaluasi operan kanan dan yang akan menjadi hasilnya. Penggunaan idiomatis seperti tercantum dalam tautan adalah saat menginisialisasi variabel yang digunakan dalam satu for
lingkaran, dan memberikan contoh berikut:
void rev(char *s, size_t len)
{
char *first;
for ( first = s, s += len - 1; s >= first; --s)
/*^^^^^^^^^^^^^^^^^^^^^^^*/
putchar(*s);
}
Kalau tidak, tidak ada banyak kegunaan besar dari operator koma , meskipun mudah untuk menyalahgunakan untuk menghasilkan kode yang sulit dibaca dan dipelihara.
Dari standar draft C99 tata bahasanya adalah sebagai berikut:
expression:
assignment-expression
expression , assignment-expression
dan ayat 2 mengatakan:
The operan kiri dari operator koma dievaluasi sebagai ekspresi kosong; ada titik urutan setelah evaluasi. Kemudian operan yang tepat dievaluasi; hasilnya memiliki jenis dan nilai. 97) Jika suatu upaya dilakukan untuk memodifikasi hasil dari operator koma atau untuk mengaksesnya setelah titik urutan berikutnya, perilaku tidak terdefinisi.
Catatan kaki 97 mengatakan:
Operator koma tidak menghasilkan nilai .
yang berarti Anda tidak dapat menetapkan hasil dari operator koma .
Penting untuk dicatat bahwa operator koma memiliki prioritas paling rendah dan oleh karena itu ada kasus di mana penggunaan ()
dapat membuat perbedaan besar, misalnya:
#include <stdio.h>
int main()
{
int x, y ;
x = 1, 2 ;
y = (3,4) ;
printf( "%d %d\n", x, y ) ;
}
akan memiliki output berikut:
1 4
Operator koma menggabungkan dua ekspresi kedua sisi menjadi satu, mengevaluasi keduanya dalam urutan kiri-ke-kanan. Nilai sisi kanan dikembalikan sebagai nilai keseluruhan ekspresi.
(expr1, expr2)
seperti { expr1; expr2; }
tetapi Anda dapat menggunakan hasil expr2
dalam panggilan fungsi atau tugas.
Sering terlihat dalam for
loop untuk menginisialisasi atau mempertahankan beberapa variabel seperti ini:
for (low = 0, high = MAXSIZE; low < high; low = newlow, high = newhigh)
{
/* do something with low and high and put new values
in newlow and newhigh */
}
Terlepas dari ini, saya hanya menggunakannya "dalam kemarahan" dalam satu kasus lain, ketika menyelesaikan dua operasi yang harus selalu berjalan bersama dalam makro. Kami memiliki kode yang menyalin berbagai nilai biner ke buffer byte untuk dikirim di jaringan, dan sebuah pointer mempertahankan di mana kami telah sampai:
unsigned char outbuff[BUFFSIZE];
unsigned char *ptr = outbuff;
*ptr++ = first_byte_value;
*ptr++ = second_byte_value;
send_buff(outbuff, (int)(ptr - outbuff));
Di mana nilainya short
atau int
kami melakukan ini:
*((short *)ptr)++ = short_value;
*((int *)ptr)++ = int_value;
Kemudian kita membaca bahwa ini bukan C yang benar-benar valid, karena (short *)ptr
tidak lagi bernilai l dan tidak dapat ditingkatkan, meskipun kompiler kami pada saat itu tidak keberatan. Untuk memperbaiki ini, kami membagi ekspresi menjadi dua:
*(short *)ptr = short_value;
ptr += sizeof(short);
Namun, pendekatan ini bergantung pada semua pengembang yang mengingat untuk menempatkan kedua pernyataan di sepanjang waktu. Kami menginginkan fungsi di mana Anda bisa meneruskan di pointer output, nilai dan dan tipe nilai. Ini adalah C, bukan C ++ dengan templat, kami tidak dapat memiliki fungsi mengambil tipe arbitrer, jadi kami memutuskan makro:
#define ASSIGN_INCR(p, val, type) ((*((type) *)(p) = (val)), (p) += sizeof(type))
Dengan menggunakan operator koma, kami dapat menggunakan ini dalam ekspresi atau sebagai pernyataan seperti yang kami inginkan:
if (need_to_output_short)
ASSIGN_INCR(ptr, short_value, short);
latest_pos = ASSIGN_INCR(ptr, int_value, int);
send_buff(outbuff, (int)(ASSIGN_INCR(ptr, last_value, int) - outbuff));
Saya tidak menyarankan contoh-contoh ini adalah gaya yang baik! Memang, saya sepertinya ingat Steve McConnell's Code Complete menasihati bahkan menggunakan operator koma dalam satu for
loop: untuk keterbacaan dan pemeliharaan, loop harus dikontrol oleh hanya satu variabel, dan ekspresi dalam for
baris itu sendiri hanya boleh berisi kode loop-control, bukan bit tambahan lain dari inisialisasi atau pemeliharaan loop.
Ini menyebabkan evaluasi beberapa pernyataan, tetapi hanya menggunakan yang terakhir sebagai nilai yang dihasilkan (nilai, saya pikir).
Begitu...
int f() { return 7; }
int g() { return 8; }
int x = (printf("assigning x"), f(), g() );
harus menghasilkan x yang diatur ke 8.
Satu-satunya tempat yang saya lihat bermanfaat adalah ketika Anda menulis loop funky di mana Anda ingin melakukan banyak hal dalam salah satu ekspresi (mungkin ekspresi init atau ekspresi loop. Sesuatu seperti:
bool arraysAreMirrored(int a1[], int a2[], size_t size)
{
size_t i1, i2;
for(i1 = 0, i2 = size - 1; i1 < size; i1++, i2--)
{
if(a1[i1] != a2[i2])
{
return false;
}
}
return true;
}
Maafkan saya jika ada kesalahan sintaks atau jika saya mencampurkan sesuatu yang tidak ketat C. Saya tidak berargumen bahwa, operator adalah bentuk yang baik, tetapi untuk itulah Anda dapat menggunakannya. Dalam kasus di atas saya mungkin akan menggunakan while
loop sebagai gantinya sehingga beberapa ekspresi pada init dan loop akan lebih jelas. (Dan saya akan menginisialisasi i1 dan i2 inline alih-alih mendeklarasikan dan kemudian menginisialisasi .... bla bla bla.)
Saya menghidupkan kembali ini hanya untuk menjawab pertanyaan dari @Rajesh dan @JeffMercado yang saya pikir sangat penting karena ini adalah salah satu hit mesin pencari teratas.
Ambil cuplikan kode berikut sebagai contoh
int i = (5,4,3,2,1);
int j;
j = 5,4,3,2,1;
printf("%d %d\n", i , j);
Itu akan mencetak
1 5
The i
kasus ditangani seperti yang dijelaskan oleh sebagian besar jawaban. Semua ekspresi dievaluasi dalam urutan kiri-ke-kanan tetapi hanya yang terakhir ditugaskan i
. Hasil dari (
ekspresi ) is
1`.
Kasing j
ini mengikuti aturan prioritas yang berbeda karena ,
memiliki prioritas operator terendah. Karena aturan-aturan, kompilator melihat tugas-ekspresi, konstanta, konstan ... . Ekspresi yang lagi dievaluasi dalam kiri-ke-kanan ketertiban dan efek samping mereka tetap terlihat, oleh karena itu, j
adalah 5
sebagai akibat darij = 5
.
Interstingly, int j = 5,4,3,2,1;
tidak diizinkan oleh spec bahasa. Sebuah initializer mengharapkan tugas-ekspresi sehingga langsung ,
operator tidak diperbolehkan.
Semoga ini membantu.