স্বাক্ষরিত / স্বাক্ষরযুক্ত তুলনা


87

আমি নীচের কোডটি কেন নির্দেশিত স্থানে সতর্কতা জারি করে না তা বোঝার চেষ্টা করছি।

//from limits.h
#define UINT_MAX 0xffffffff /* maximum unsigned int value */
#define INT_MAX  2147483647 /* maximum (signed) int value */
            /* = 0x7fffffff */

int a = INT_MAX;
//_int64 a = INT_MAX; // makes all warnings go away
unsigned int b = UINT_MAX;
bool c = false;

if(a < b) // warning C4018: '<' : signed/unsigned mismatch
    c = true;
if(a > b) // warning C4018: '<' : signed/unsigned mismatch
    c = true;
if(a <= b) // warning C4018: '<' : signed/unsigned mismatch
    c = true;
if(a >= b) // warning C4018: '<' : signed/unsigned mismatch
    c = true;
if(a == b) // no warning <--- warning expected here
    c = true;
if(((unsigned int)a) == b) // no warning (as expected)
    c = true;
if(a == ((int)b)) // no warning (as expected)
    c = true;

আমি ভেবেছিলাম এটি ব্যাকগ্রাউন্ড প্রচারের সাথে করা হয়েছে, তবে শেষ দুটি মনে হয় অন্যথায় বলেছে।

আমার মনে হয়, প্রথম ==তুলনাটি কি অন্যদের মতো ঠিক একটি স্বাক্ষরিত / স্বাক্ষরবিহীন অমিল?


4
জিসিসি ৪.৪.২ সতর্কতা প্রিন্ট করে যখন '-ওয়াল'
বোবাহ

এটি অনুমান তবে এটি সংকলনের সময়ে উত্তরটি জানে বলে এটি সমস্ত তুলনাটি অপ্টিমাইজ করে।
নুল সেট

4
আহ! পুনরায়। বোবার মন্তব্য: আমি সমস্ত সতর্কতা চালু করেছি এবং অনুপস্থিত সতর্কতা এখন উপস্থিত রয়েছে। আমি মতামত করছি যে এটি অন্য তুলনাগুলির মতো একই সতর্কতা স্তরের সেটিংসে উপস্থিত হওয়া উচিত ছিল।
পিটার

4
@ বোবাঃ আমি সেই জিসিিকে সত্যই ঘৃণা করি 4..৪.২.২ সতর্কতাটি প্রিন্ট করে (কেবলমাত্র এটি বৈষম্যের জন্য মুদ্রণ করতে বলার উপায় নেই), যেহেতু এই সতর্কতাটি স্থির করার সমস্ত উপায় বিষয়টিকে আরও খারাপ করে তোলে । ডিফল্ট পদোন্নতি নির্ভরযোগ্যভাবে -1 বা ~ 0 উভয়কে কোনও স্বাক্ষরবিহীন প্রকারের সর্বোচ্চ সম্ভাব্য মান হিসাবে রূপান্তর করে তবে আপনি যদি সতর্কতাটি নিজে কাস্ট করে শান্ত করেন তবে আপনাকে সঠিক প্রকারটি জানতে হবে। তাই আপনি যদি টাইপ পরিবর্তন (প্রসারিত এটা দীর্ঘ দীর্ঘ স্বাক্ষরবিহীন বলছি), বেয়ার সঙ্গে আপনার তুলনা -1সঙ্গে আপনার তুলনা হবে এখনও কাজ (কিন্তু যারা দিতে সাবধানবাণী) যখন -1uবা (unsigned)-1উভয় বিফল মনোরথ হয়েছে।
জানু হুডেক

আপনার কেন একটি সতর্কতা দরকার তা আমি জানি না এবং সংকলকরা কেন এটি কাজ করতে পারে না। -1 নেতিবাচক তাই কোনও স্বাক্ষরযুক্ত সংখ্যার চেয়ে কম। সরল।
ক্যাশকো

উত্তর:


96

স্বাক্ষরযুক্ত স্বাক্ষরের সাথে তুলনা করার সময়, সংকলক স্বাক্ষরিত মানটিকে স্বাক্ষরবিহীন রূপান্তরিত করে। সমতার জন্য, এটি কোনও ব্যাপার নয় -1 == (unsigned) -1,। অন্যান্য তুলনা এটা গুরুত্বপূর্ণ জন্য, নিম্নলিখিত যেমন সত্য: -1 > 2U

সম্পাদনা: তথ্যসূত্র:

5/9: (এক্সপ্রেশন)

বহু বাইনারি অপারেটরগণ যারা গণিত বা গণনা প্রকারের অপারেশনগুলি প্রত্যাশা করে একই ধরণের রূপান্তর ঘটায় এবং ফলস্বরূপ ফলাফলের ধরণ। উদ্দেশ্যটি একটি সাধারণ প্রকারের ফলন, যা ফলাফলের ধরণও। এই প্যাটার্নটিকে সাধারণ গাণিতিক রূপান্তর বলা হয়, যা নিম্নলিখিত হিসাবে সংজ্ঞায়িত হয়:

  • যদি অপরেন্দ্র টাইপ দীর্ঘ ডাবল হয় তবে অন্যটি লম্বা ডাবলে রূপান্তরিত হবে।

  • অন্যথায় যদি অপরেন্দ্র দ্বিগুণ হয় তবে অন্যটি দ্বিগুণ রূপান্তরিত হবে।

  • অন্যথায়, অপরেন্দ্রটি যদি ভাসমান হয় তবে অন্যটি ফ্লোটে রূপান্তরিত হবে।

  • অন্যথায়, অবিচ্ছেদ্য প্রচার (4.5) উভয় অপারেন্ডে করা হবে .5৪)

  • তারপরে, উভয় অপ্রেন্ড স্বাক্ষরযুক্ত দীর্ঘ না হলে অন্যটি স্বাক্ষরযুক্ত লম্বায় রূপান্তরিত হবে।

  • অন্যথায়, যদি একটি অপারেণ্ড দীর্ঘ লম্বা হয় এবং অন্যটি স্বাক্ষরবিহীন অন্তর্ভুক্ত হয়, তবে যদি একটি দীর্ঘ অন্তর্নিহিত স্বাক্ষরবিহীন কোনও মানের সমস্ত মান উপস্থাপন করতে পারে তবে স্বাক্ষরযুক্ত স্বাক্ষরকে একটি দীর্ঘ ইনটে রূপান্তর করা হবে; অন্যথায় উভয় অপারেন্ড স্বাক্ষরবিহীন দীর্ঘ অন্তর্নিহিত করা হবে।

  • অন্যথায়, যদি অপরেন্ড দীর্ঘ হয়, অন্যটি দীর্ঘ রূপান্তরিত হবে।

  • অন্যথায় অপরেন্দ্র স্বাক্ষরিত না হলে অন্যটি স্বাক্ষরবিহীন রূপান্তরিত হবে।

4.7 / 2: (সংহত রূপান্তরগুলি)

গন্তব্যের প্রকারটি স্বাক্ষরিত না হলে ফলাফলটি হ'ল উত্স পূর্ণসংখ্যার স্বল্প স্বাক্ষরযুক্ত পূর্ণসংখ্যার সমষ্টি (মডুলো 2 এন যেখানে এন স্বাক্ষরযুক্ত প্রকারের প্রতিনিধিত্ব করতে ব্যবহৃত বিটের সংখ্যা)। [দ্রষ্টব্য: দু'জনের পরিপূরক উপস্থাপনায়, এই রূপান্তরটি ধারণাগত এবং বিট প্যাটার্নে কোনও পরিবর্তন নেই (যদি কোনও ছাঁটাই না হয়)। ]

EDIT2: এমএসভিসি সতর্কতা স্তর

এমএসভিসির বিভিন্ন সতর্কতা স্তরের বিষয়ে যে বিষয়ে সতর্ক করা হয়েছে তা হ'ল বিকাশকারীগণের পছন্দগুলি। আমি এটি দেখতে পাচ্ছি, স্বাক্ষরিত / স্বাক্ষরিত সমতা বনাম বৃহত্তর / কম তুলনা সম্পর্কিত তাদের পছন্দগুলি বোধগম্য হয়, এটি অবশ্যই সম্পূর্ণ বিষয়গত:

-1 == -1এর অর্থ একই -1 == (unsigned) -1- আমি এটি একটি স্বজ্ঞাত ফলাফল।

-1 < 2 এর অর্থ একই নয়-1 < (unsigned) 2 - এটি প্রথম নজরে কম স্বজ্ঞাত, এবং আইএমও একটি "পূর্ববর্তী" সতর্কতার দাবি রাখে।


আপনি কীভাবে সাইন ইন স্বাক্ষরিত রূপান্তর করতে পারেন? স্বাক্ষরিত মান -1 এর স্বাক্ষরিত সংস্করণটি কী? (স্বাক্ষরিত -1 = 1111, স্বাক্ষরবিহীন 15 = 1111, কিছুটা হলেও তারা সমান হতে পারে তবে তারা যৌক্তিকভাবে সমান নয়)) আমি বুঝতে পারি যে আপনি এই রূপান্তরকে জোর করলে এটি কার্যকর হবে, তবে সংকলক কেন এটি করবে? এটা অযৌক্তিক। তদ্ব্যতীত, আমি উপরে মন্তব্য হিসাবে, আমি যখন সতর্কতাগুলি হারিয়েছি তখন == সতর্কতা উপস্থিত হয়েছিল, যা আমার বলার ব্যাক আপ করবে বলে মনে হচ্ছে?
পিটার

4
৪.7 / ২ বলছেন, স্বাক্ষরযুক্ত স্বাক্ষরিত মানে দু'জনের পরিপূরকের জন্য বিট প্যাটার্নে কোনও পরিবর্তন করা হয়নি। সংকলকটি কেন এটি করে, এটি সি ++ মানক দ্বারা প্রয়োজনীয়। আমি বিশ্বাস করি যে বিভিন্ন স্তরে ভিএসের সতর্কতার পিছনে যুক্তিটি প্রকাশের অপ্রয়োজনীয় হওয়ার সুযোগ - এবং আমি তাদের সাথে একমত হই যে স্বাক্ষরিত / স্বাক্ষরযুক্ত না হওয়া সমতার তুলনা অসমতার তুলনার তুলনায় সমস্যা হওয়ার সম্ভাবনা "কম সম্ভাবনা"। এটি অবশ্যই বিষয়গত - এটি ভিসি সংকলক বিকাশকারীদের দ্বারা করা পছন্দগুলি।
এরিক

ঠিক আছে, আমি মনে করি আমি এটি প্রায় পেয়েছি। আমি যেভাবে পড়লাম, তা সংকলকটি করছে (ধারণাগতভাবে): 'যদি (((স্বাক্ষরযুক্ত _int64) 0x7fffffff)) == ((স্বাক্ষরযুক্ত _int64) 0xffffffff))', কারণ _int64 হল সবচেয়ে ছোট ধরন যা 0x7fffffff এবং 0xffffffff উভয়েরই প্রতিনিধিত্ব করতে পারে স্বাক্ষরবিহীন পদে?
পিটার

4
আসলে তুলনা করা (unsigned)-1বা তুলনার তুলনায় -1uপ্রায়শই খারাপ-1 । কারণ (unsigned __int64)-1 == -1, কিন্তু (unsigned __int64)-1 != (unsigned)-1। সুতরাং যদি সংকলকটি কোনও সতর্কতা দেয়, আপনি স্বাক্ষরবিহীন বা ব্যবহার করে কাস্ট করে এটি নীরব করার চেষ্টা করেন -1uএবং যদি মানটি আসলে -৪-বিট হিসাবে ঘটে বা আপনি এটি পরে পরিবর্তন করে ফেলেন, আপনি আপনার কোডটি ভেঙে দেবেন! এবং মনে রাখবেন যে size_tস্বাক্ষরবিহীন, কেবল 64৪-বিট প্ল্যাটফর্মগুলিতে -৪-বিট এবং অবৈধ মানের জন্য -১ ব্যবহার করা এর সাথে খুব সাধারণ।
জানু হুডেক

4
সম্ভবত সিপিম্পিলারগুলি তখন তা করা উচিত নয়। যদি এটি স্বাক্ষরিত এবং স্বাক্ষরবিহীন এর তুলনা করে তবে স্বাক্ষরিত মানটি নেতিবাচক কিনা তা পরীক্ষা করে দেখুন। যদি তাই হয় তবে নির্বিশেষে স্বাক্ষরযুক্ত এর চেয়ে কম হওয়ার গ্যারান্টিযুক্ত।
ক্যাশকো

33

স্বাক্ষরিত / স্বাক্ষরবিহীন সতর্কতাগুলি কেন গুরুত্বপূর্ণ এবং প্রোগ্রামারদের অবশ্যই তাদের মনোযোগ দেওয়া উচিত, তা নিম্নলিখিত উদাহরণ দ্বারা প্রদর্শিত হয়।

এই কোড আউটপুট অনুমান?

#include <iostream>

int main() {
        int i = -1;
        unsigned int j = 1;
        if ( i < j ) 
            std::cout << " i is less than j";
        else
            std::cout << " i is greater than j";

        return 0;
}

আউটপুট:

i is greater than j

অবাক? অনলাইন ডেমো: http://www.ideone.com/5iCxY

বটমলাইন: তুলনায়, যদি একটি অপারেন্ড হয় unsigned, তবে অন্য অপারেন্ডকে স্পষ্টভাবে রূপান্তরিত করা হয় unsigned যদি এর ধরণের স্বাক্ষরিত হয়!


4
সে সঠিক! এটা বোবা, কিন্তু তিনি ঠিক বলেছেন। এটি এমন একটি প্রধান গোচা যা আমি এর আগে কখনও পাইনি। কেন এটি স্বাক্ষরিত স্বাক্ষরিত (বৃহত্তর) স্বাক্ষরিত মানটিতে রূপান্তর করে না ?! আপনি যদি "যদি (i <((int) j))) করেন তবে এটি আপনার প্রত্যাশার মতোই কাজ করে। যদিও "if (i <((_intint)) j))" আরও অর্থবোধ করতে পারে (ধরে নিচ্ছি যে যা আপনি পারবেন না, _ যে int৪ ইন্টির আকারের দ্বিগুণ)।
পিটার

6
@ পিটার "কেন এটি আনজিগেন্ডকে একটি (বৃহত্তর) স্বাক্ষরিত মানের রূপান্তর করে না?" উত্তরটি সহজ: বৃহত্তর স্বাক্ষরিত মান নাও থাকতে পারে। একটি 32 বিট মেশিনে, দীর্ঘ দিনগুলির আগের দিনগুলিতে, আন্ত এবং দীর্ঘ উভয়ই 32 বিট ছিল এবং এর চেয়ে বড় কিছুই ছিল না। স্বাক্ষরিত এবং স্বাক্ষরবিহীন তুলনা করার সময়, প্রাথমিক সি ++ সংকলকগণ উভয়কে স্বাক্ষরে রূপান্তরিত করেছিলেন। আমি কারণগুলি ভুলে যাচ্ছি, সি স্ট্যান্ডার্ড কমিটি এটি পরিবর্তন করেছে। আপনার সর্বোত্তম সমাধান হ'ল যতটা সম্ভব স্বাক্ষর করা এড়ানো avoid
জেমস কানজে

4
@ জামেসকানজে: আমার সন্দেহ হয় যে এটিকে সত্য হিসাবেও কিছু করতে হবে, স্বাক্ষরিত ওভারফ্লোয়ের ফলাফলটি অনির্ধারিত আচরণের সময় স্বাক্ষরিত ওভারফ্লো ফলাফল নয় এবং তাই স্বাক্ষরিত নেতিবাচক স্বাক্ষরিত মানকে নেতিবাচক স্বাক্ষরে রূপান্তরিত করার সময় সংজ্ঞায়িত করা হয় মান হয় না
জানু হুডেক

4
@ জেমস সংকলকটি সর্বদা এমন সমাবেশ তৈরি করতে পারে যা আরও বড় আকারে না ফেলে এই তুলনার আরও স্বজ্ঞাত শব্দার্থ প্রয়োগ করে। এই বিশেষ উদাহরণে, এটি প্রথমে পরীক্ষা করা যথেষ্ট i<0। তারপরে নিশ্চিত iহওয়ার চেয়ে ছোট smaller jযদি iশূন্যের চেয়ে কম না হয় তবে এর ìসাথে তুলনা করার জন্য স্বাক্ষরযুক্তভাবে নিরাপদে রূপান্তর করা যেতে পারে j। অবশ্যই, স্বাক্ষরযুক্ত এবং স্বাক্ষরযুক্ত না থাকাগুলির মধ্যে তুলনাগুলি ধীর হবে, তবে তাদের ফলাফলটি কিছু দিক থেকে আরও সঠিক হবে।
সেভেন

@ তবে আমি সম্মত হই। স্ট্যান্ডার্ডটির জন্য দুটি ধরণের একটিতে রূপান্তরিত না করে প্রকৃত মানগুলির জন্য সমস্ত তুলনা করার প্রয়োজন হতে পারে। এটি কেবল তুলনার ক্ষেত্রে কাজ করবে; আমার সন্দেহ হয় যে কমিটি তুলনা এবং অন্যান্য ক্রিয়াকলাপের জন্য বিভিন্ন বিধি চায় না (যখন আসলে তুলনা করা টাইপটি উপস্থিত ছিল না তখন তা তুলনা নির্দিষ্টকরণের সমস্যাটিতে আক্রমণ করতে চায় না)।
জেমস কানজে

4

অপারেটর কেবল কিছুটা তুলনা করে (সাধারণ বিভাগ দ্বারা এটি 0 হয় কিনা তা দেখতে)।

তুলনায় তুলনায় ছোট / বৃহত্তর সংখ্যার চিহ্নটিতে অনেক বেশি নির্ভর করে।

4 বিটের উদাহরণ:

1111 = 15? বা -1?

সুতরাং আপনার যদি 1111 <0001 থাকে ... এটি অস্পষ্ট ...

তবে আপনার যদি 1111 == 1111 থাকে ... এটি একই জিনিস যদিও আপনি এটি বোঝাতে চাইছেন নি।


আমি এটি বুঝতে পারি, তবে এটি আমার প্রশ্নের উত্তর দেয় না। আপনি চিহ্নিত হিসাবে, 1111! = 1111 চিহ্নগুলি মেলে না, তাহলে। সংকলকটি জানে যে প্রকারগুলি থেকে কোনও অমিল আছে, সুতরাং এটি কেন এটি সম্পর্কে সতর্ক করে না? (আমার বক্তব্যটি হ'ল যে আমার কোডটিতে এমন অনেকগুলি অমিল রয়েছে যা সম্পর্কে আমাকে সতর্ক করা হচ্ছে না))
পিটার

এটি ডিজাইন করার উপায়। সমতা পরীক্ষা সমানতা পরীক্ষা করে। এবং এটি একই রকম। আমি আপনার সাথে একমত যে এটি এমন হওয়া উচিত নয়। আপনি কোনও ম্যাক্রো বা এমন কিছু করতে পারেন যা x == y হতে হবে! ((X <y) || (x> y))
যোচাই টিমমার

1

এমন একটি সিস্টেমে যা 2-পরিপূরক (সর্বাধিক আধুনিক প্রসেসর) ব্যবহার করে মানগুলি উপস্থাপন করে তারা এমনকি তাদের বাইনারি আকারেও সমান। এই কারণেই সংকলক a == খ সম্পর্কে অভিযোগ না করে ।

এবং আমার কাছে এটি বিস্ময়কর সংকলক আপনাকে একটি == ((পূর্ববর্তী) খ) সম্পর্কে সতর্ক করে না । আমি মনে করি এটির আপনাকে একটি পূর্ণসংখ্যার কাটা সতর্কতা বা কিছু দেওয়া উচিত।


4
সি / সি ++ এর দর্শনটি হ'ল: সংকলকটি বিশ্বাস করে যে প্রকারগুলির মধ্যে স্পষ্টত রূপান্তর করার সময় বিকাশকারী কী করে (গুলি) জানেন। সুতরাং, কোনও সতর্কতা নেই (কমপক্ষে ডিফল্টরূপে - আমি বিশ্বাস করি যে সংকলক রয়েছে যা যদি সতর্কতার স্তরটি ডিফল্টের চেয়ে উচ্চতর সেট করা থাকে তবে এর জন্য সতর্কতা উত্পন্ন করে)।
পিটার টারিক

0

প্রশ্নে থাকা কোডের রেখাটি C4018 সতর্কতা তৈরি করে না কারণ মাইক্রোসফ্ট সেই কেসটি পরিচালনা করতে একটি পৃথক সতর্কতা নম্বর ব্যবহার করেছে (যেমন C4389 ), এবং সি 439 ডিফল্টরূপে সক্ষম করা হয়নি (অর্থাত্ 3 স্তরে))

C4389 এর জন্য মাইক্রোসফ্ট ডক্স থেকে :

// C4389.cpp
// compile with: /W4
#pragma warning(default: 4389)

int main()
{
   int a = 9;
   unsigned int b = 10;
   if (a == b)   // C4389
      return 0;
   else
      return 0;
};

অন্যান্য উত্তরগুলি বেশ ভালভাবে ব্যাখ্যা করেছে যে মাইক্রোসফ্ট কেন সাম্যতা অপারেটরের বাইরে একটি বিশেষ মামলা করার সিদ্ধান্ত নিয়েছে, তবে আমি দেখতে পেয়েছি যে উত্তরগুলি C4389 উল্লেখ না করে বা কীভাবে এটি ভিজুয়াল স্টুডিওতে সক্ষম করতে হবে তা কার্যকর নয়

আমার আরও উল্লেখ করা উচিত যে আপনি যদি C4389 সক্ষম করতে চলেছেন তবে আপনি C 4388 সক্ষম করার বিষয়টিও বিবেচনা করতে পারেন। দুর্ভাগ্যক্রমে C4388 এর জন্য কোনও অফিসিয়াল ডকুমেন্টেশন নেই তবে এটি নীচের মত প্রকাশে পপ আপ বলে মনে হচ্ছে:

int a = 9;
unsigned int b = 10;
bool equal = (a == b); // C4388
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.