এম্বেড কোডের জন্য, কেন আমি "স্বাক্ষরবিহীন ইন্টি" এর পরিবর্তে "uint_t" প্রকারগুলি ব্যবহার করব?


22

আমি একটি এসটিএম 32 এফ 10 এর জন্য সি-তে একটি আবেদন লিখছি, জিসিসি ব্যবহার করে writing

গত (সহজ প্রকল্পের সঙ্গে), আমি সবসময় ভেরিয়েবল সংজ্ঞায়িত করেছেন char, int, unsigned int, ইত্যাদি।

আমি দেখতে এটি যেমন stdint.h সংজ্ঞায়িত ধরনের, ব্যবহার করা খুবই সাধারণ int8_t, uint8_t, uint32_t, ইত্যাদি এটা একাধিক এপিআই এর যে আমি ব্যবহার করছি, এবং এছাড়াও এসটি থেকে এআরএম CMSIS লাইব্রেরিতে সত্য।

আমি বিশ্বাস করি যে আমি বুঝতে পারি কেন আমাদের এমন করা উচিত; সংকলকটিকে মেমরির স্থানটিকে আরও অনুকূলিতকরণের অনুমতি দিতে। আমি আশা করি এর অতিরিক্ত কারণও থাকতে পারে।

যাইহোক, কারণ গ এর পূর্ণসংখ্যা প্রচার নিয়ম, আমি রূপান্তর সতর্কবার্তা বিরুদ্ধে যে কোনো সময় চলমান রাখতে আমি দুটি মানের যোগ করার চেষ্টা করুন, একটি bitwise অপারেশন না, ইত্যাদি সতর্কবার্তা ভালো কিছু লেখা আছে conversion to 'uint16_t' from 'int' may alter its value [-Wconversion]। বিষয়টি এখানে এবং এখানে আলোচনা করা হয়েছে

যখন ভেরিয়েবল হিসেবে ঘোষণা ব্যবহার করে এটি ঘটবে না intবা unsigned int

এই দেওয়া কয়েকটি উদাহরণ দিতে:

uint16_t value16;
uint8_t value8;

আমাকে এটি পরিবর্তন করতে হবে:

value16 <<= 8;
value8 += 2;

এটি:

value16 = (uint16_t)(value16 << 8);
value8 = (uint8_t)(value8 + 2);

এটি কুৎসিত, তবে প্রয়োজনে আমি এটি করতে পারি। আমার প্রশ্নগুলি এখানে:

  1. সেখানে একটি মামলা কোথা থেকে রূপান্তর হয় স্বাক্ষরবিহীন করার স্বাক্ষরিত এবং ফিরে স্বাক্ষরবিহীন ফলাফলের ভুল করবে?

  2. Stdint.h পূর্ণসংখ্যার প্রকার ব্যবহার করার / বিপরীতে অন্য কোনও বড় কারণ আছে কি?

আমি যে উত্তরগুলি পেয়েছি তার উপর ভিত্তি করে, দেখে মনে হচ্ছে stdint.h প্রকারগুলি সাধারণত অগ্রাধিকারপ্রাপ্ত হয়, যদিও সি এবং পিছনে রূপান্তরিত uintহয় int। এটি একটি বড় প্রশ্ন বাড়ে:

  1. আমি টাইপকাস্টিং (উদাহরণস্বরূপ value16 = (uint16_t)(value16 << 8);) ব্যবহার করে সংকলক সতর্কতাগুলি প্রতিরোধ করতে পারি । আমি কি শুধু সমস্যাটি লুকিয়ে রাখছি? এটি সম্পর্কে আরও ভাল উপায় আছে?

স্বাক্ষরবিহীন আক্ষরিক: যেমন 8uএবং 2u
হারমিং মনিকা বন্ধ করুন

ধন্যবাদ, @ ওরেঞ্জডগ, আমি মনে করি আমি ভুল বুঝছি। আমি উভয় চেষ্টা value8 += 2u;এবং value8 = value8 + 2u;, কিন্তু আমি একই সতর্কবার্তা পেতে।
বিটসম্যাক

আপনার ইতিমধ্যে প্রস্থের সতর্কতা না থাকলে স্বাক্ষরিত সতর্কতাগুলি এড়াতে এগুলি যেভাবেই হোক না কেন :)
মনমিকাকে

উত্তর:


11

একটি স্ট্যান্ডার্ড-কনফর্মিং সংকলক যেখানে int17 থেকে 32 বিট পর্যন্ত কোথাও ছিল নিচের কোডটি সহ বৈধভাবে যা কিছু ইচ্ছা তা করতে পারে :

uint16_t x = 46341;
uint32_t y = x*x; // temp result is signed int, which can't hold 2147488281

এমন বাস্তবায়ন যা করতে চেয়েছিল তা বৈধভাবে একটি প্রোগ্রাম তৈরি করতে পারে যা প্রতিটি কল্পনাযোগ্য প্রোটোকল ব্যবহার করে প্রতিটি পোর্ট পিনে বারবার "ফ্রেড" স্ট্রিং ব্যতীত আর কিছুই করে না। কোনও প্রোগ্রাম এমন একটি বাস্তবায়নে পোর্ট হয়ে যাওয়ার সম্ভাবনা খুব কম, তবে তাত্ত্বিকভাবে এটি সম্ভব। উপরের কোডটি লিখতে চাইলে যাতে অপরিজ্ঞাত আচরণে জড়িত না থাকার গ্যারান্টি দেওয়া হয়, তবে এটি পরবর্তী বর্ণটি (uint32_t)x*xবা হিসাবে লিখতে হবে 1u*x*x। একটি সংকলক যেখানে int17 থেকে 31 বিটের মধ্যে রয়েছে, পরবর্তী প্রকাশটি উপরের বিটগুলি বন্ধ করে দেবে, তবে অনির্ধারিত আচরণে নিযুক্ত হবে না।

আমি মনে করি জিসিসি সতর্কতা সম্ভবত পরামর্শ দেওয়ার চেষ্টা করছে যে লিখিত কোডটি সম্পূর্ণ 100% পোর্টেবল নয়। এমন কিছু সময় রয়েছে যখন আচরণগুলি এড়ানোর জন্য কোডটি সত্যই রচনা করা উচিত যা কিছু বাস্তবায়নের ক্ষেত্রে অপরিজ্ঞাপিত হবে, তবে অন্য অনেক ক্ষেত্রে সহজভাবে বোঝা উচিত যে কোডটি বাস্তবায়নের ক্ষেত্রে ব্যবহার করার সম্ভাবনা নেই যা অতিরিক্ত বিরক্তিকর কাজ করে do

মনে রাখবেন যে এর মতো ধরণের ব্যবহার intএবং shortকিছু সতর্কতা দূর করতে এবং কিছু সমস্যা সমাধান করতে পারে তবে সম্ভবত অন্যদের তৈরি করতে পারে। uint16_tসি এর পূর্ণসংখ্যা-প্রচারের বিধিগুলির মতো প্রকারের মধ্যে পারস্পরিক মিথস্ক্রিয়াটি আইকিউইন, তবে এই জাতীয় প্রকারগুলি এখনও অন্য কোনও বিকল্পের চেয়ে সম্ভবত ভাল।


6

1) আপনি যদি সাইন ইন থেকে ঠিক একই দৈর্ঘ্যের স্বাক্ষরিত পূর্ণসংখ্যার পিছনে পিছনে পিছনে কোনও ক্রিয়াকলাপ না করে থাকেন তবে আপনি প্রতিবার একই ফলাফল পাবেন, সুতরাং এখানে কোনও সমস্যা নেই। কিন্তু বিভিন্ন যৌক্তিক এবং গাণিতিক ক্রিয়াকলাপ স্বাক্ষরিত এবং স্বাক্ষরবিহীন অপারেশনগুলিতে আলাদাভাবে অভিনয় করছে।
২) stdint.hপ্রকারগুলি ব্যবহারের প্রধান কারণ হ'ল এই জাতীয় প্রকারের বিট আকারটি সমস্ত প্ল্যাটফর্মের মধ্যেই সংজ্ঞায়িত এবং সমান, যা সত্য নয় int, longইত্যাদির পাশাপাশি charকোনও মান চিহ্ন নেই, এটি স্বাক্ষরিত বা স্বাক্ষরহীন হতে পারে ডিফল্ট. অতিরিক্ত চেকিং এবং অনুমানগুলি ব্যবহার না করে সঠিক আকারটি জেনে ডেটা ম্যানিপুলেট করা সহজ করে তোলে।


2
আকারগুলি int32_tএবং uint32_tসমস্ত প্ল্যাটফর্ম জুড়ে সেগুলি সমান যেখানে সেগুলি সংজ্ঞায়িত করা হয় । প্রসেসরের যদি সঠিকভাবে মিলে যাওয়া হার্ডওয়্যার টাইপ না থাকে তবে এই ধরণের সংজ্ঞা দেওয়া হয় না are এর অত: পর সুবিধা intইত্যাদি এবং, সম্ভবত, int_least32_tইত্যাদি
পিট বেকার

1
@ পেটবেকার - এটি তাত্ক্ষণিকভাবে একটি সুবিধা, যদিও এর ফলে সংকলিত ত্রুটিগুলি আপনাকে তাত্ক্ষণিকভাবে সমস্যা সম্পর্কে সচেতন করে তোলে। আমার চেয়ে আমার প্রকারের পরিবর্তনের চেয়ে আমি তার চেয়ে অনেক বেশি চাই।
সাপি

@ সাপি - অনেক পরিস্থিতিতে অন্তর্নিহিত আকার অপ্রাসঙ্গিক; সি প্রোগ্রামাররা বেশ কয়েক বছর ধরে নির্দিষ্ট আকার ছাড়াই ঠিক জরিমানা অর্জন করে।
পিট বেকার 13

6

যেহেতু ইউজিনের # 2 সম্ভবত সবচেয়ে গুরুত্বপূর্ণ পয়েন্ট, আমি কেবল এটি যুক্ত করতে চাই যে এটি একটি পরামর্শদাতা

MISRA (directive 4.6): "typedefs that indicate size and signedness should be used in place of the basic types".

এছাড়াও জ্যাক গ্যানসেল সেই নিয়মের সমর্থক হিসাবে উপস্থিত হবে: http://www.ganssle.com/tem/tem265.html


2
এটি খুব খারাপ যে "এন-বিট স্বাক্ষরবিহীন পূর্ণসংখ্যার কোনও ধরণের নির্দিষ্ট নেই যা একই আকারের ফলাফল পেতে অন্য কোনও আকারের পূর্ণসংখ্যার সাথে নিরাপদে গুণিত হতে পারে"। পূর্ণসংখ্যা প্রচারের নিয়মগুলি বিদ্যমান ধরণের মতো মারাত্মকভাবে ইন্টারঅ্যাক্ট করে uint32_t
সুপারক্যাট

3

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

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

-std = c99 -প্যাডেন্টিক -ওয়াল-ওয়েক্সট্রা -শ্যাডো

আপনার যদি প্রয়োজন হয় তবে আরও যুক্ত করুন, তবে প্রতিক্রিয়া হ'ল আপনি তা করবেন না।

আপনি যদি -WWW র রূপান্তর রাখতে হবে, আপনি কেবল সংখ্যার অপারেন্ড টাইপ করে আপনার কোডটি কিছুটা ছোট করতে পারেন:

value16 <<= (uint16_t)8;
value8 += (uint8_t)2;

যদিও সিনট্যাক্স হাইলাইট করা ছাড়া এটি পড়া সহজ নয়।


2

যে কোনও সফ্টওয়্যার প্রকল্পে, পোর্টেবল ধরণের সংজ্ঞা ব্যবহার করা খুব গুরুত্বপূর্ণ। (একই সংকলকটির পরবর্তী সংস্করণটিরও এই বিবেচনার প্রয়োজন)) একটি উত্তম উদাহরণ, বেশ কয়েক বছর আগে আমি এমন একটি প্রকল্পে কাজ করেছি যেখানে বর্তমান সংকলকটি 'ইনট' 8 বিট হিসাবে সংজ্ঞায়িত করেছে। সংকলকটির পরবর্তী সংস্করণটি 'ইনট' 16 বিট হিসাবে সংজ্ঞায়িত করেছে। যেহেতু আমরা 'ইনট' এর জন্য কোনও পোর্টেবল সংজ্ঞা ব্যবহার করি নি, তাই আকারটি দ্বিগুণ (কার্যকরভাবে) দ্বিগুণ হয়ে গেছে এবং 8 বিট ইন্টের উপর নির্ভরশীল এমন অনেক কোড সিকোয়েন্স ব্যর্থ হয়েছে। একটি পোর্টেবল ধরণের সংজ্ঞা ব্যবহার এড়ানো যেত (সমস্যা সমাধানে কয়েকশো ঘন্টা)


int8 বিট প্রকারের উল্লেখ করার জন্য কোনও যুক্তিসঙ্গত কোড ব্যবহার করা উচিত নয় । সিসিএসের মতো কোনও নন-সি সংকলক যদি তা করেও, যুক্তিসঙ্গত কোডটি char8 বিটের জন্য একটি টাইপফিড টাইপ এবং 16 বিটের জন্য একটি টাইপফিড টাইপ ("দীর্ঘ" নয়) ব্যবহার করা উচিত। অন্যদিকে, সিসিএসের মতো কোনও বাস্তব সংকলক পর্যন্ত পোর্টিং কোডটি সঠিক টাইপডেফ ব্যবহার করা সত্ত্বেও সমস্যা হতে পারে, যেহেতু এই ধরনের সংকলকগুলি প্রায়শই অন্যান্য উপায়ে "অস্বাভাবিক" হয়।
সুপারক্যাট

1
  1. হ্যাঁ। একটি এন-বিট স্বাক্ষরিত পূর্ণসংখ্যা একটি এন-বিট স্বাক্ষরযুক্ত পূর্ণসংখ্যার হিসাবে অ-নেতিবাচক সংখ্যার প্রায় অর্ধেক সংখ্যার প্রতিনিধিত্ব করতে পারে এবং ওভারফ্লো বৈশিষ্ট্যের উপর নির্ভর করা অপরিজ্ঞাত আচরণ হয় যাতে কিছু ঘটতে পারে। বর্তমান এবং অতীতের প্রসেসরের বিস্তৃত অংশ দু'টি পরিপূরক ব্যবহার করে তাই স্বাক্ষরিত এবং স্বাক্ষরবিহীন ইন্টিগ্রাল ধরণের ক্ষেত্রে একই কাজটি করার জন্য প্রচুর ক্রিয়াকলাপ ঘটে তবে তারপরেও সমস্ত ক্রিয়াকলাপ বিট-বুদ্ধিযুক্ত অভিন্ন ফলাফল আনবে না। আপনার কোডটি কেন উদ্দেশ্য অনুযায়ী কাজ করছে না তা আপনি বুঝতে না পারলে আপনি পরে অতিরিক্ত সমস্যার জন্য জিজ্ঞাসা করছেন।

  2. যদিও int- এ এবং স্বাক্ষরবিহীন বাস্তবায়ন সংজ্ঞায়িত মাপ আছে, এই প্রায়ই "সুন্দর" বাস্তবায়ন দ্বারা পারেন আকার বা গতি কারণে নির্বাচিত হয়। আমার অন্যথায় করার উপযুক্ত কারণ না থাকলে আমি সাধারণত এগুলি বদ্ধ থাকি। তেমনি, অন্তর্নিহিত বা স্বাক্ষরবিহীন ব্যবহার করতে হবে কিনা তা বিবেচনা করার সময় আমি অন্যথায় অন্যভাবে না করার উপযুক্ত কারণ না থাকলে আমি সাধারণত পছন্দ করি।

যে ধরণের আকার বা স্বাক্ষরিত নেসের উপরে আমার সত্যিই আরও ভাল নিয়ন্ত্রণ প্রয়োজন সেখানে আমি সাধারণত সিস্টেম-সংজ্ঞায়িত টাইপইডেফ (আকার_টি, ইন্টম্যাক্স_টি ইত্যাদি) ব্যবহার করতে পছন্দ করব বা আমার নিজস্ব টাইপডেফ তৈরি করব যা প্রদত্ত কার্যকারিতা নির্দেশ করে টাইপ করুন (prng_int, adc_int, ইত্যাদি)।


0

প্রায়শই কোডটি এআরএম থাম্ব এবং এভিআর (এবং x86, পাওয়ারপিসি এবং অন্যান্য আর্কিটেকচার) এ ব্যবহৃত হয় এবং এসটিএম 32 এআরএম-তে 16 বা 32 বিট আরও দক্ষ (উভয় উপায়ে: ফ্ল্যাশ এবং চক্র) হতে পারে এমন একটি ভেরিয়েবলের জন্যও যা 8 বিটগুলিতে ফিট করে ( 8 বিট এভিআর উপর আরও দক্ষ হয়) । তবে যদি এসআরএএম প্রায় পূর্ণ থাকে তবে গ্লোবাল ওয়ার্সের জন্য 8 বিটে ফিরে যাওয়া যুক্তিসঙ্গত হতে পারে (তবে স্থানীয় যুদ্ধের জন্য নয়)। বহনযোগ্যতা এবং রক্ষণাবেক্ষণ (বিশেষত জন্য 8 বিট Vars) জন্য, এটি সুবিধার (যে কোন অসুবিধা ছাড়াই) রয়েছে MINIMUM থেকে উপযুক্ত আকার উল্লেখ সুর এক জ জায়গা (সাধারণত ifdef অধীনে) এ সঠিক আকার এবং হয় typedef (সম্ভবত uint_fast8_t / পরিবর্তে uint_least8_t) পোর্টিং / বিল্ড সময় চলাকালীন:

// apparently uint16_t is just as efficient as 32 bit on STM32, but 8 bit is punished (with more flash and cycles)
typedef uint16_t uintG8_t; // 8bit if SRAM is scarce (use fol global vars that fit in 8 bit)
typedef uint16_t uintL8_t; // 8bit on AVR (local var, 16 or 32 bit is more efficient on STM + less flash)
// might better reserve 32 bits on some arch, STM32 seems efficient with 16 bits:
typedef uint16_t uintG16_t; // 16bit if SRAM is scarce (use fol global vars that fit in 16 bit)
typedef uint16_t uintL16_t; // 16bit on AVR (local var, 16 or 32 bit whichever is more efficient on other arch)

জিএনইউ লাইব্রেরি কিছুটা সহায়তা করে, তবে সাধারণত টাইপিডফরা যাইহোক তা বোঝায়:

typedef uint_least8_t uintG8_t;
typedef uint_fast8_t uintL8_t;

// তবে দু'জনের জন্য uint_ ব্রেকফাস্ট8_t যখন এসআরএম কোনও উদ্বেগ নয়।

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