সি ++ এনামগুলি স্বাক্ষরিত বা স্বাক্ষরবিহীন?


107

সি ++ এনামগুলি স্বাক্ষরিত বা স্বাক্ষরবিহীন? এবং এক্সটেনশনের মাধ্যমে কোনও ইনপুটটি <= আপনার সর্বোচ্চ মান, এবং আপনার ন্যূনতম মানটি (আপনি 0 থেকে শুরু করেছেন এবং 1 দ্বারা বর্ধিত) ধরে রেখেছেন কিনা তা পরীক্ষা করে কোনও বৈধতা পরীক্ষা করা নিরাপদ?


আমরা যখন এনাম টাইপটি এমন একটি প্রসঙ্গে ব্যবহার করতে পারি যার জন্য এর সাইন প্রয়োজন, আমরা প্রকৃতপক্ষে এনামকে ইন্টিগ্রাল টাইপের রূপে রূপান্তর করার কথা বলছি। সি ++ 03 স্ট্যান্ডার্ড বলছে এটি ইন্টিগ্রাল প্রচার দ্বারা সম্পন্ন হয়েছে, এনামের অন্তর্নিহিত ধরণের সাথে সম্পর্কিত কিছুই নয়। সুতরাং, আমি বুঝতে পারি না কেন এখানে প্রতিটি উত্তর অন্তর্নিহিত ধরণের উল্লেখ করে মান দ্বারা সংজ্ঞায়িত হয় না? : আমি এখানে প্রত্যাশিত behaviou বর্ণনা stackoverflow.com/questions/24802322/...
JavaMan

উত্তর:


60

আপনার কোনও নির্দিষ্ট উপস্থাপনার উপর নির্ভর করা উচিত নয়। নীচের লিঙ্কটি পড়ুন । এছাড়াও, মানকটি বলে যে এটি বাস্তবায়ন-সংজ্ঞায়িত যা কোন এনামের জন্য অন্তর্নিহিত প্রকার হিসাবে ইন্টিগ্রাল টাইপ ব্যবহৃত হয়, ব্যতীত এটি ইন্টের চেয়ে বড় হবে না, যদি না কোনও মান অন্তর্নিহিত বা স্বাক্ষরবিহীন কোনও ইন্টিতে ফিট না করে।

সংক্ষেপে: আপনি স্বাক্ষরিত বা স্বাক্ষরিত কোনও এনামের উপর নির্ভর করতে পারবেন না।


28
মাইকেল বুরের উত্তর (যা মানটির উদ্ধৃতি দেয়) বোঝায় যে আপনি স্বাক্ষরিত হওয়ার উপর নির্ভর করতে পারবেন যদি আপনি এনুমুর মানটিকে "গুনে সংজ্ঞায়িত সমস্ত বর্ণকের মান উপস্থাপন করতে" টাইপ করার কারণে নেতিবাচক হিসাবে সংজ্ঞায়িত করেন।
স্যামুয়েল হারমার

101

উত্স যেতে যাক। এখানে সি ++ 03 স্ট্যান্ডার্ড (আইএসও / আইইসি 14882: 2003) নথিটি কি 7.2-5 (গণনার ঘোষণা) তে বলেছে:

একটি গণনার অন্তর্নিহিত ধরণ হল একটি অবিচ্ছেদ্য প্রকার যা গণনাতে সংজ্ঞায়িত সমস্ত গণকের মানকে উপস্থাপন করতে পারে। এটি রূপায়ণ-সংজ্ঞায়িত যা কোন সংখ্যার জন্য অন্তর্নিহিত প্রকারটি অন্তর্নিহিত প্রকার হিসাবে ব্যবহৃত হয় তা বাদে অন্তর্নিহিত প্রকারটি ইন্টের চেয়ে বড় হবে না যদি না কোনও এনুম্যরেটারের মান কোনও ইন্ট বা স্বাক্ষরযুক্ত ইনতে ফিট না করে।

সংক্ষেপে, আপনার সংকলকটি চয়ন করতে পারে (স্পষ্টতই, যদি আপনার কিছু গণনা মানের জন্য নেতিবাচক সংখ্যা থাকে তবে তা স্বাক্ষরিত হবে)।


সমস্ত গণনা মান ছোট, ধনাত্মক পূর্ণসংখ্যক হলে আমরা কীভাবে সংকলক অনুমানগুলি এড়াতে এবং অন্তর্নিহিত স্বাক্ষরযুক্ত প্রকারটি ব্যবহার করতে এটি বলতে পারি? (আমরা একটি ইউবসান সন্ধান করছি কারণ সংকলকটি কোন ইনট বাছাই করছে, এবং ইনট এর উপচে পড়েছে The মানটি স্বাক্ষরিত এবং ইতিবাচক এবং আমাদের ব্যবহার হ্রাস বা "নেতিবাচক পদক্ষেপ" সরবরাহ করতে স্বাক্ষরযুক্ত মোড়কের উপর নির্ভর করে)।
jwww

@jww - আপনি কি কম্পাইলারটি সঠিকভাবে ব্যবহার করছেন তার উপর নির্ভর করবে, আমার ধারণা। যেহেতু স্ট্যান্ডার্ডটি অন্তর্নিহিত ধরণের নির্দেশ দেয় না এবং এটি বাস্তবায়নের দিকে ছেড়ে দেয়, তারপরে আপনার সরঞ্জামটির ডকুমেন্টেশনটি দেখার প্রয়োজন এবং এই বিকল্পটি আদৌ সম্ভব কিনা তা দেখতে হবে। আপনি যদি আপনার কোডটিতে একটি নির্দিষ্ট আচরণের গ্যারান্টি দিতে চান তবে আপনি যে এনাম সদস্যটি প্রকাশ করেন তা castালাই না কেন?
ysap

22

আপনি স্বাক্ষরিত বা স্বাক্ষরিত হওয়ার উপর নির্ভর করবেন না। আপনি যদি তাদের সুস্পষ্টভাবে স্বাক্ষরিত বা স্বাক্ষরবিহীন করতে চান তবে আপনি নিম্নলিখিতটি ব্যবহার করতে পারেন:

enum X : signed int { ... };    // signed enum
enum Y : unsigned int { ... };  // unsigned enum

11
কেবলমাত্র ভবিষ্যতে সি ++ 0 এক্স স্ট্যান্ডার্ড।
ডাল 18

3
@dalle মাইক্রোসফট compilator মঞ্জুরি দেয় টাইপ করা enums msdn.microsoft.com/en-us/library/2dzy4k6e(v=vs.80).aspx
teodozjan

15

আপনি স্বাক্ষরিত বা স্বাক্ষরিত না হয়ে এটির উপর নির্ভর করবেন না। মান অনুযায়ী এটি বাস্তবায়ন-সংজ্ঞায়িত যা কোন এনামের জন্য অন্তর্নিহিত ধরণ হিসাবে ইন্টিগ্রাল টাইপ ব্যবহৃত হয়। যদিও বেশিরভাগ বাস্তবায়নে এটি একটি স্বাক্ষরিত পূর্ণসংখ্যা।

সি ++ 0 এক্সে দৃ strongly ়ভাবে টাইপযুক্ত গণনা যুক্ত করা হবে যা আপনাকে এনুমের ধরণ নির্দিষ্ট করার অনুমতি দেয়:

enum X : signed int { ... };    // signed enum
enum Y : unsigned int { ... };  // unsigned enum

এখনও, যদিও, এনামকে ভেরিয়েবল বা প্যারামিটারের ধরণের মতো ব্যবহার করে কিছু সাধারণ বৈধতা পাওয়া যায়:

enum Fruit { Apple, Banana };

enum Fruit fruitVariable = Banana;  // Okay, Banana is a member of the Fruit enum
fruitVariable = 1;  // Error, 1 is not a member of enum Fruit
                    // even though it has the same value as banana.

আমি মনে করি আপনার দ্বিতীয় উদাহরণটি কিছুটা বিভ্রান্ত :)
মিরাল

5

সংকলক এনামস স্বাক্ষরিত বা স্বাক্ষরবিহীন কিনা তা সিদ্ধান্ত নিতে পারে।

এনামগুলিকে বৈধতা দেওয়ার আরেকটি পদ্ধতি হ'ল এনামকে ভেরিয়েবল টাইপ হিসাবে ব্যবহার করা। উদাহরণ স্বরূপ:

enum Fruit
{
    Apple = 0,
    Banana,
    Pineapple,
    Orange,
    Kumquat
};

enum Fruit fruitVariable = Banana;  // Okay, Banana is a member of the Fruit enum
fruitVariable = 1;  // Error, 1 is not a member of enum Fruit even though it has the same value as banana.

5

এমনকি কিছু পুরানো উত্তর 44 টি আপত্তি পেয়েছে, আমি সেগুলির সাথে একমত নই। সংক্ষেপে, আমি মনে করি না underlying typeআমাদের এনামগুলির যত্ন নেওয়া উচিত ।

প্রথমে, সি ++ 03 এনাম টাইপ স্বতন্ত্র ধরণের যা স্বাক্ষরের কোনও ধারণা নেই। যেহেতু সি ++ 03 স্ট্যান্ডার্ড থেকেdcl.enum

7.2 Enumeration declarations 
5 Each enumeration defines a type that is different from all other types....

সুতরাং যখন আমরা একটি এনাম টাইপের চিহ্নের কথা বলছি, <অপারেটরটি ব্যবহার করে 2 এনাম অপারেন্ডের তুলনা করার সময় বলুন , আমরা প্রকৃতপক্ষে এনাম টাইপকে কিছু অবিচ্ছেদ্য ধরণের রূপান্তরিত করার বিষয়ে কথা বলছি। এটি গুরুত্বপূর্ণ এই ইন্টিগ্রাল টাইপের চিহ্ন । এবং এনামকে অবিচ্ছেদ্য প্রকারে রূপান্তর করার সময়, এই বিবৃতিটি প্রযোজ্য:

9 The value of an enumerator or an object of an enumeration type is converted to an integer by integral promotion (4.5).

এবং দৃশ্যত, এনামের অন্তর্নিহিত ধরণের ইন্টিগ্রাল প্রচারের সাথে কিছুই করার নেই to যেহেতু স্ট্যান্ডার্ডটি ইন্টিগ্রাল প্রচারকে এভাবে সংজ্ঞায়িত করে:

4.5 Integral promotions conv.prom
.. An rvalue of an enumeration type (7.2) can be converted to an rvalue of the first of the following types that can represent all the values of the enumeration
(i.e. the values in the range bmin to bmax as described in 7.2: int, unsigned int, long, or unsigned long.

সুতরাং, একটি enum টাইপ হয়ে কিনা signed intবা unsigned intকিনা উপর নির্ভর করে signed intসংজ্ঞায়িত তথ্যসংগ্রহকারী না enum অন্তর্নিহিত ধরনের সমস্ত মান থাকতে পারে।

আমার সম্পর্কিত প্রশ্নটি সি ++ এনাম প্রকারের ইন্টিগ্রাল প্রকারে রূপান্তরিত করার পরে ভুলের সাইন ইন দেখুন


আপনি যখন সংকলন করছেন তখন এটি গুরুত্বপূর্ণ -Wsign-conversion। আমরা আমাদের কোডে অনিচ্ছাকৃত ভুল ধরতে সহায়তা করতে এটি ব্যবহার করি। তবে +1 স্ট্যান্ডার্ড উদ্ধৃত করার জন্য, এবং একটি এনাম এর সাথে কোনও প্রকার ( signedবনাম unsigned) জড়িত তা নির্দেশ করে।
jww

4

ভবিষ্যতে, C ++ 0x এর সাথে দৃ strongly ়ভাবে টাইপ করা গণনাগুলি উপলব্ধ হবে এবং এর বেশ কয়েকটি সুবিধা রয়েছে (যেমন টাইপ-সুরক্ষা, স্পষ্টত অন্তর্নিহিত ধরণের বা স্পষ্টত স্কোপিং)। এটির সাথে আপনি ধরণের সাইন সম্পর্কে আরও ভালভাবে নিশ্চিত হতে পারেন।


4

স্বাক্ষরিত / স্বাক্ষরবিহীন সম্পর্কে অন্যরা ইতিমধ্যে যা বলেছে তা ছাড়াও, একটি গণিতের প্রকারের পরিধি সম্পর্কে স্ট্যান্ডার্ড যা বলেছে তা এখানে:

.2.২ ()): "একটি গণনার জন্য যেখানে ই (মিনিট) হ'ল ক্ষুদ্রতম গণক এবং ই (সর্বাধিক) বৃহত্তম, গণনার মানগুলি বি (ন্যূনতম) থেকে বি (সর্বাধিক) সীমাতে অন্তর্নিহিত ধরণের মান হয় ), যেখানে খ (মিনিট) এবং বি (সর্বোচ্চ) যথাক্রমে, ক্ষুদ্রতম বিটফিল্ডের সবচেয়ে ছোট এবং বৃহত্তম মান যা ই (মিনিট) এবং ই (সর্বাধিক) সঞ্চয় করতে পারে। এমন একটি সংখ্যার সংজ্ঞা দেওয়া সম্ভব যা মানগুলি সংজ্ঞায়িত না করে এর যে কোনও গণক দ্বারা "

উদাহরণস্বরূপ:

enum { A = 1, B = 4};

একটি গণিত প্রকার নির্ধারণ করে যেখানে e (সর্বনিম্ন) 1 এবং e (সর্বাধিক) 4 হয়। যদি অন্তর্নিহিত প্রকারটি স্বাক্ষরিত হয় তবে সর্বনিম্ন প্রয়োজনীয় বিটফিল্ডে 4 বিট থাকে এবং যদি আপনার প্রয়োগের ints দুটি সংখ্যক পরিপূরক হয় তবে এর বৈধ পরিসীমা এনামটি -8 থেকে 7. এর মধ্যে অন্তর্নিহিত প্রকারটি স্বাক্ষরিত না হলে এটিতে 3 টি বিট থাকে এবং পরিসীমা 0 থেকে 7 থাকে you যদি যত্নশীল হন তবে আপনার সংকলক ডকুমেন্টেশন পরীক্ষা করুন (উদাহরণস্বরূপ আপনি যদি গণকের পরিবর্তে ইন্টিগ্রাল মানগুলি কাস্ট করতে চান তবে অঙ্কিত প্রকার, তারপরে আপনাকে জানতে হবে যে মানটি গণনার পরিসরে রয়েছে কিনা - ফলাফলের এনাম মানটি অনির্ধারিত না থাকলে)।

সেই মানগুলি আপনার ফাংশনে বৈধ ইনপুট কিনা তা গণিত প্রকারের বৈধ মান কিনা তা থেকে আলাদা সমস্যা হতে পারে। আপনার চেকিং কোডটি সম্ভবত পরবর্তীকালের চেয়ে পূর্বের সম্পর্কে উদ্বিগ্ন এবং তাই এই উদাহরণে কমপক্ষে> = এ এবং <= বি পরীক্ষা করা উচিত।


0

এটিকে std::is_signed<std::underlying_type+ স্কোপড এনামগুলি ডিফল্ট হিসাবে পরীক্ষা করে দেখুনint

https://en.cppreferences.com/w/cpp/language/enum বোঝায়:

main.cpp

#include <cassert>
#include <iostream>
#include <type_traits>

enum Unscoped {};
enum class ScopedDefault {};
enum class ScopedExplicit : long {};

int main() {
    // Implementation defined, let's find out.
    std::cout << std::is_signed<std::underlying_type<Unscoped>>() << std::endl;

    // Guaranteed. Scoped defaults to int.
    assert((std::is_same<std::underlying_type<ScopedDefault>::type, int>()));

    // Guaranteed. We set it ourselves.
    assert((std::is_same<std::underlying_type<ScopedExplicit>::type, long>()));
}

গিটহাব উজানের দিকে

সংকলন এবং চালান:

g++ -std=c++17 -Wall -Wextra -pedantic-errors -o main main.cpp
./main

আউটপুট:

0

উবুন্টু 16.04, জিসিসি 6.4.0 এ পরীক্ষিত।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.