Nima uchun test belgisi har doim "salbiy" xabar beradi?

Quyidagi dastur array elementlarining summasi ijobiy yoki salbiy ekanligini tekshirishi kerak:

#include 

#define ARR_SIZE 5

int main()
{
   int array[ARR_SIZE] = {1,-2,3,4,-5};
   unsigned sum;
   int i;

   for(i=0, sum=0; i < ARR_SIZE; i++)
   {
         sum += array[i];
         printf("sum %d\n ", sum);
   }


         printf("%d\n",sum);
   if(sum>-1) printf("non negative\n");
   else printf("negative\n");
   return 0;
 }

Dastur nimani nazarda tutganini qilmaydi; Qaysi qator qiymatlarni olishidan qat'i nazar, u "salbiy" yozishga imkon beradi.

Masalan, yuqoridagi dasturda yozilgan qator summasi 1 bo'lib, shuning uchun quyidagi natijani kutmoqdaman:

sum 1
sum -1
sum 2
sum 6
sum 1
1
non negative

Chiqish esa:

sum 1
sum -1
sum 2
sum 6
sum 1
1
negative

Ushbu mahsulotni nima uchun olaman?

0
@ squeamish ossifrage Tashakkur. Men bu haqda allaqachon o'ylab qoldim, lekin agar narsa summasi imzolansa, demak u har doim ijobiy bo'ladi ... shuning uchun chiqish qanday "salbiy" deyish mumkin? Men har doim "salbiy bo'lmagan" ni chop eta olaman deb o'yladim.
qo'shib qo'ydi muallif Tree, manba
sum unsigned bo'lmasligi kerak.
qo'shib qo'ydi muallif Paul Ogilvie, manba
Topshiriq: sum unsigned bo'lsa, nima sodir bo'lishini tushuntiring.
qo'shib qo'ydi muallif Paul Ogilvie, manba
if (sum> -1) derivativ ogohlantirishini berishi kerak. Derleyici ogohlantirishlarini yoqing!
qo'shib qo'ydi muallif Paul Ogilvie, manba
Siz sum kodini unsigned deb e'lon qildingiz. Buni biroz o'ylang ...
qo'shib qo'ydi muallif squeamish ossifrage, manba

6 javoblar

In the expression sum > -1, the usual arithmetic conversions ("balancing") applies. Since one operand is unsigned int and the other is int, the operand -1 which is int gets implicitly converted to unsigned int. The comparison operation is carried out on type unsigned int.

Bundan tashqari, imzolangan bo'lmagan o'zgaruvchilar hech qachon salbiy ma'noga ega bo'lolmaydi, shuning uchun ifoda yopiq konvertatsiya qilinmasdan ham ma'no bermaydi.

1
qo'shib qo'ydi
Rahmat! Nima uchun har doim salbiy natija berishi mumkinligini tushunaman, lekin nima uchun -1 qiymat UMAX + 1 bilan o'zgartirilmaydi?
qo'shib qo'ydi muallif Tree, manba
Tushunaman. Juda sabr-toqatli bo'lishingiz va uni tushuntirib berishingiz uchun sizga katta rahmat. Buni qadrlayman :) @Lundin
qo'shib qo'ydi muallif Tree, manba
Rahmat. Men hali ham buni qabul qilmayapman. Agar men (imzolangan bo'lmagan) -1 qilsam, unda nega u -1 + UINT_MAX + 1 = oldin UINT_MAX emas?
qo'shib qo'ydi muallif Tree, manba
Sabr uchun katta rahmat! Sen, albatta, buni tushunishimga yordam berding. Ha, men UINT_MAXni nazarda tutdim. Faqat bitta narsa, "yangi turdagi" nima degani? @ Lundin
qo'shib qo'ydi muallif Tree, manba
@ Lundin * Men anglatmaydigan intga aylantirildi -1 degan ma'noni anglatadi.
qo'shib qo'ydi muallif Tree, manba
@Lunding Tashakkur. Demak, agar (sum> -1) chindan ham (sum> 0) bo'lsa Men hali ham buni bilmayman: agar 1 - imzosiz int ga aylantirilsa va undagi qiymat belgisi int unsigned int bo'lsa, qanday qilib chiqdi doim "salbiy" bo'ladi? "Salbiy bo'lmagan" bo'lmasligi kerakmi? To'liqsiz imzolangan intga aylantirilsa-da, men hali uning qiymatini bilmayman, shuning uchun men ushbu dasturni amalga oshirganimda aslida qanday taqqoslash mumkin?
qo'shib qo'ydi muallif Tree, manba
Rahmat. Buni biroz batafsilroq tushuntirib bera olasizmi? Aslida, bu operand -1 imzosiz intga aylanadi degan ma'noni anglatadi? Salbiy qiymat summaga tayinlanganda nima bo'ladi? Men biroz chalkashdim, chunki men buni yozganimda: int main() {unsigned int x; x = -1; printf ("% d \ n", sum); qaytish 0} Chiqish -1 bo'ldi. Men bu haqda o'qidim va tushunganim sababli, bu printf uchundir.
qo'shib qo'ydi muallif Tree, manba
@ Odatda sodda qilib aytganda, C -1 ikkilik vakillikni tutadi va uni imzolangan bo'lmagan ekvivalentga aylantiradi. 32 bitlik tamsayılar 2-qo'shimcha bo'lsa, siz 0xFFFFFFFF bilan yakunlanadi. Va sum hech qachon 0xFFFFFFFF dan katta bo'lmasligi mumkin.
qo'shib qo'ydi muallif Lundin, manba
@Tree No, if (sum> -1) bo'lsa, bu if (sum> 0xFFFFFFFF) ga teng.
qo'shib qo'ydi muallif Lundin, manba
@Tree "UMAX + 1" nima? UINT_MAX ni nazarda tutasizmi? Imzolanmagan konvertatsiya qilish uchun imzolangan ushbu qoida bo'yicha amalga oshiriladi: "Agar yangi turdagi belgisi imzolangan bo'lmasa, qiymat yangi turdagi maksimal qiymatdan birortasini qo'shish yoki olib tashlash yo'li bilan qiymati o'zgaruvchan qiymatgacha o'zgaradi. yangi turdagi ". Shuning uchun derleyici ichki kodni unsigned int oralig'ida joylashgan -1 + UINT_MAX + 1 = UINT_MAX amalga oshiradi. Bundan tashqari UINT_MAX 32 bitlik ikkita komplekt tizimida 0xFFFFFFFF bo'lishi mumkin.
qo'shib qo'ydi muallif Lundin, manba
@Tree Bu C standartidan va "yangi turdagi" so'zidan olingan, ular konvertatsiya qilingandan so'ng sizning imzolagan turini bildiradi. Bu qoida faqatgina yopiq bo'lmaganlar uchun emas, imzosiz konvertatsiyaga imzolanganlar uchun bir xildir. Masalan, agar siz (unsigned char) -1 kodini kiritayotgan bo'lsangiz, siz 0xFF (255) qiymatiga ega bo'lasiz.
qo'shib qo'ydi muallif Lundin, manba
@Tree Bu erda "odatiy arifmetik konvertatsiya" qoidalariga bog'langan o'xshash savol bor. stackoverflow.com/questions/17312545/& hellip;
qo'shib qo'ydi muallif Lundin, manba
@Tree Chunki unsigned char uchun "yangi turdagi vakolatlarning maksimal qiymati" UCHAR_MAX, 255 dir. Ya'ni maksimum biz o'zgartiradigan yangi turdagi aniqlanadi.
qo'shib qo'ydi muallif Lundin, manba

Yopiq matn kiritish usuli: Agar o'zgaruvchini Unsigned deb belgilaganingizda va uni salbiy raqam bilan taqqoslasangiz, u holda salbiy raqam yoppasiga typecast hisoblanadi. Bilamizki, salbiy raqamlar ikkita iltifotda saqlanadi, shuning uchun -1 aslida juda katta musbat songa aylanadi. Keling, sizga taqdim etadigan ko'p sonli raqam har doim ham katta raqamdan kam bo'ladi, shuning uchun har doim javob sifatida salbiy bo'lasiz.

Favkulodda yechim: + va - raqamlarni ishlatish uchun uchinchi operatordan foydalaning. Rahmat

1
qo'shib qo'ydi
Katta rahmat!
qo'shib qo'ydi muallif Tree, manba
To'g'ri atama - bu konvertatsiya qilish. Typecasting faqat dasturchi kodni (x) yozib turini aniq o'zgartirganda vaziyatga ishora qiladi.
qo'shib qo'ydi muallif Lundin, manba
Xuddi shu narsa. bog'lanish havolasiga amal qiling
qo'shib qo'ydi muallif Vishwajeet Vishu, manba
@Tree Your welcome :)
qo'shib qo'ydi muallif Vishwajeet Vishu, manba
@Tree mening javobimni endi qabul qila olasizmi? Bu juda katta yordam.
qo'shib qo'ydi muallif Vishwajeet Vishu, manba

ikkita ikkita iltifot (int hajmi 2 baytda)

0000 0000 0000 0001 (1 ikkilik qiymat)

1111 1111 1111 1110 (iltifotli)

1111 1111 1111 1111 (two's compliment)(this value is 65535)

bu qiymat sizning kodingizda -1 bilan almashtiriladi.

1
qo'shib qo'ydi
Rahmat! Men biroz chalkashib ketdim, men mavzu haqida o'qigan edim va men UMAX + 1 qiymatini olishini o'yladim, nima uchun bunday emas?
qo'shib qo'ydi muallif Tree, manba
Bir marta, ikkita iltifot haqida o'qing. So'ngra sizning savolingizga javob topasiz.
qo'shib qo'ydi muallif Rama rju, manba

Og'ir ogohlantirishlar yoqilgan bo'lsa, yaxshi derleyici muammoni ta'kidlaydi:

gcc -std=c11 -fPIC -g -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds      42362568.c    -o 42362568
42362568.c: In function ‘main’:
42362568.c:19:10: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
    if(sum>-1) printf("non negative\n");
          ^

Sizga imkon qadar ko'p ogohlantirishlar berish uchun har doim yaxshi maslahat; tarixiy sabablarga ko'ra ko'pchiligini talab qilishni unutmasangiz, juda oz sonli ogohlantirishlar beradi.

Note that if you change the comparison to if (sum >= 0), then you'll get a different (and perhaps more useful) message, because the literal 0 can be treated as 0u:

42362568.c:19:10: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits]
    if(sum>=0) printf("non negative\n");
          ^~
0
qo'shib qo'ydi
Katta rahmat!
qo'shib qo'ydi muallif Tree, manba

the output because of your declaration of sum variable, you declared it as a unsigned sum just change the unsigned sum to signed sum or int sum

0
qo'shib qo'ydi
@Sabir Hossain Rahmat qilamiz
qo'shib qo'ydi muallif Tree, manba
Bu nima uchun ni bo'lsa ham izohlamaydi. sum kodi unsigned short deb e'lon qilingan bo'lsa, kod kutilganidek ishlaydi. Shuning uchun sum imzolanishi bilan hech qanday aloqasi yo'q.
qo'shib qo'ydi muallif Lundin, manba
Siz haqsiz, lekin uning muammoini hal qilishga harakat qildim, nima uchun u signin chiqishi bilan ishlayotganida unga unsigned o'zgaruvchiga kerak.
qo'shib qo'ydi muallif Sabir Hossain, manba

Biz ikkita o'zgaruvchining (bir xil ma'lumot turi) ishorasini solishtirishga harakat qilsak, Kompilyator (ichki) ikkala parametrni yuqori imzolangan turdagi (imzosiz turdagi) baholaydi.

Hear if(sum > -1) is your code.You are trying to compare unsigned sum , signed constant so compiler internally convert -1 as unsigned . If we consider integer size as 2 bytes then sum = 1(as your code) but the -1 will be converted to unsigned value 65535 (do 2's compliment for -1) now your code will be simplified to if(sum > 65535), so the condition isFALSE that's why only always you are getting un- expected result.If you want to avoid this problem, always compare same signed type variables(if both variables are same data type , other wise there is no problem with different signed types also).

0
qo'shib qo'ydi