বি পয়েন্ট এবং অপারেটরের সাথে অ্যারে ডিক্লেয়ারেশনে সি পয়েন্টার


9

আমি নিম্নলিখিত কোডটি বুঝতে চাই:

//...
#define _C 0x20
extern const char *_ctype_;
//...
__only_inline int iscntrl(int _c)
{
    return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c] & _C));
}

এটি obtybsd অপারেটিং সিস্টেম উত্স কোড থেকে ctype.h ফাইল থেকে উদ্ভূত । এই ফাংশনটি পরীক্ষা করে যদি কোনও চর কোনও নিয়ন্ত্রণ অক্ষর হয় বা এএসসিআই রেঞ্জের ভিতরে একটি মুদ্রণযোগ্য অক্ষর হয়। এটি আমার বর্তমান চিন্তার শৃঙ্খল:

  1. iscntrl ('a') বলা হয় এবং 'a' এর পূর্ণসংখ্যার মানতে রূপান্তরিত হয়
  2. প্রথমে _c -1 হয় কিনা তা পরীক্ষা করে দেখুন 0 টি আবার ...
  3. অ্যাড্রেসটি পূর্বনির্ধারিত পয়েন্টারটিকে 1 দ্বারা বাড়িয়ে দিন
  4. এই ঠিকানাটিকে দৈর্ঘ্যের অ্যারে (স্বাক্ষরবিহীন চর) ((অন্তর্নিহিত) 'এ') এর পয়েন্টার হিসাবে ঘোষণা করুন
  5. বিটওয়াইজ এবং অপারেটরটিকে _ সি (0x20) এবং অ্যারে (???) এ প্রয়োগ করুন

একরকম, আশ্চর্যের সাথে, এটি কাজ করে এবং প্রতিবার 0 প্রদান করা গৃহস্থালি _c প্রিন্টযোগ্য অক্ষর নয়। অন্যথায় এটি মুদ্রণযোগ্য যখন ফাংশন কেবল একটি পূর্ণসংখ্যা মান প্রদান করে যা কোনও বিশেষ আগ্রহের নয়। আমার বোঝার সমস্যাটি পদক্ষেপ 3, 4 (কিছুটা) এবং 5 তে রয়েছে।

কোন সাহায্যের জন্য আপনাকে ধন্যবাদ।


1
_ctype_মূলত বিটমাস্কের একটি অ্যারে। এটি আগ্রহের চরিত্র দ্বারা সূচিত করা হচ্ছে। সুতরাং _ctype_['A']"আলফা" এবং "বড় হাতের অক্ষরে" _ctype_['a']অনুরূপ বিট থাকতে পারে , "আলফা" এবং "ছোট হাতের" _ctype_['1']সাথে সামঞ্জস্যপূর্ণ বিট থাকতে পারে , "অঙ্ক" এর সাথে সামঞ্জস্যপূর্ণ কিছু ছিল, ইত্যাদি দেখে মনে 0x20হয় কিছুটা "নিয়ন্ত্রণ" এর সাথে সম্পর্কিত । তবে কোনও কারণে _ctype_অ্যারেটি অফসেট হয় 1, তাই বিটগুলি 'a'সত্যই ভিতরে রয়েছে _ctype_['a'+1]। (এটি সম্ভবত EOFঅতিরিক্ত পরীক্ষা ছাড়াই এটির জন্য কাজ করা হতে পারে))
স্টিভ সামিট

অভিনেতাদের (unsigned char)হ'ল চরিত্রগুলি স্বাক্ষরিত এবং নেতিবাচক হওয়ার সম্ভাবনাটির যত্ন নেওয়া।
স্টিভ সামিট

উত্তর:


3

_ctype_প্রতীক টেবিলের একটি সীমিত অভ্যন্তরীণ সংস্করণ বলে মনে হচ্ছে এবং আমি অনুমান করছি + 1যে 0এটি মুদ্রণযোগ্য নয় বলে তারা এটির সংরক্ষণ সূচকে বিরক্ত করেনি । অথবা সম্ভবত তারা সি-তে কাস্টম অনুসারে 0-সূচকের পরিবর্তে 1-ইনডেক্সযুক্ত টেবিল ব্যবহার করছে

সি স্ট্যান্ডার্ড সমস্ত সিটিপি এইচ কর্মের জন্য এটি নির্দেশ করে:

সমস্ত ক্ষেত্রে যুক্তি হ'ল একটি int, যার মান একটি হিসাবে উপস্থাপিত হবে unsigned charবা ম্যাক্রোর মান সমান হবেEOF

ধাপে ধাপে কোডটি অতিক্রম করছেন:

  • int iscntrl(int _c)intধরনের সত্যিই অক্ষর আছে, কিন্তু সব ctype.h ফাংশন হ্যান্ডেল করার প্রয়োজন হয় EOF, তাই তারা হওয়া আবশ্যক int
  • চেক বিপরীতে -1একটি চেক হয় EOF, যেহেতু এর মান রয়েছে -1
  • _ctype+1 অ্যারে আইটেমের ঠিকানা পেতে পয়েন্টার গাণিতিক।
  • [(unsigned char)_c]কেবল সেই অ্যারেটির একটি অ্যারে অ্যাক্সেস, যেখানে প্যারামিটারের স্ট্যান্ডার্ড প্রয়োজনীয়তা হিসাবে প্রতিনিধিত্বযোগ্য হওয়া কার্যকর করতে সেখানে castালাই থাকে unsigned char। নোট করুন যে charআসলে একটি নেতিবাচক মান ধরে রাখতে পারে, সুতরাং এটি রক্ষণাত্মক প্রোগ্রামিং। []অ্যারে অ্যাক্সেসের ফলাফলটি তাদের অভ্যন্তরীণ প্রতীক টেবিলের একক অক্ষর।
  • &মাস্কিং প্রতীক টেবিল থেকে অক্ষরের একটি নির্দিষ্ট গ্রুপ পেতে নেই। দৃশ্যত বিট 5 সেট (মুখোশ 0x20) সহ সমস্ত অক্ষর নিয়ন্ত্রণের অক্ষর। টেবিলটি না দেখেই এর কোনও উপলব্ধি নেই।
  • বিট 5 সেট সহ যে কোনও কিছুই 0x20 সহ মুখোশযুক্ত মানটি ফিরিয়ে দেবে, এটি একটি শূন্য-মান। এটি বুলিয়ান সত্যের ক্ষেত্রে অ-শূন্য ফিরে ফাংশনটির প্রয়োজনীয়তার প্রয়োজনীয়তা নির্ধারণ করে।

এটা যে ঢালাই sates মান প্রয়োজন যে মান যেমন representable হতে সঠিক নয় unsigned char। স্ট্যান্ডার্ডটির প্রয়োজন হয় যে রুটিনটি যখন বলা হয় তখনই মানটি *unsigned char বা হিসাবে সমান হিসাবে প্রতিনিধিত্বযোগ্য হয় EOF। Castালাই কেবল "প্রতিরক্ষামূলক" প্রোগ্রামিং হিসাবে কাজ করে: ম্যাক্রো ব্যবহার করার সময় অনূষ্কের কোনও মান পাস করার সময় কোনও স্বাক্ষরকারী char(বা ক signed char) পাস করা প্রোগ্রামারটির ত্রুটি সংশোধন করে । এটি লক্ষ করা উচিত যে এই ক্ষেত্রে ত্রুটিটি সংশোধন করতে পারে না যখন implementation1 এর মান an1 ব্যবহার করে এমন বাস্তবায়নে পাস হয় । unsigned charctype.hcharEOF
এরিক পোস্টপিসিল

এটি এর একটি ব্যাখ্যাও দেয় + 1। যদি ম্যাক্রো আগে এই প্রতিরক্ষামূলক সামঞ্জস্য না রাখে, তবে এটি কেবল নিখরচায় প্রয়োগ করা যেতে পারে ((_ctype_+1)[_c] & _C), সুতরাং এইভাবে প্রাক-সমন্বয় মানগুলি −1 থেকে 255 এর সাথে সূচিযুক্ত একটি সারণী ছিল So সুতরাং প্রথম এন্ট্রিটি এড়ানো হয়নি এবং কোনও উদ্দেশ্য কার্যকর করা হয়নি। পরে যখন কেউ প্রতিরক্ষামূলক castালাই যুক্ত করেছে, তখন EOFcast1 এর মান সেই কাস্টের সাথে কাজ করবে না, তাই তারা শর্তসাপেক্ষ অপারেটরটিকে এটি বিশেষভাবে চিকিত্সার জন্য যুক্ত করেছিল।
এরিক পোস্টপিশিল

3

_ctype_257 বাইটের বিশ্বব্যাপী অ্যারেটির পয়েন্টার। আমি জানিনা কি _ctype_[0]জন্য ব্যবহার করা হয়। _ctype_[1]এর মাধ্যমে _ctype_[256]_যথাক্রমে 0,…, 255 বর্ণের চরিত্রের প্রতিনিধিত্ব করুন: চরিত্রের _ctype_[c + 1]বিভাগটি প্রতিনিধিত্ব করে c। এটি বলার মতো একই জিনিসটি _ctype_ + 1256 টি অক্ষরের একটি অ্যারে নির্দেশ করে যেখানে চরিত্রটির (_ctype_ + 1)[c]শ্রেণিবিন্যাসকে উপস্থাপন করে c

(_ctype_ + 1)[(unsigned char)_c]এটি কোনও ঘোষণা নয়। এটি অ্যারে সাবস্ক্রিপ্ট অপারেটরটি ব্যবহার করে একটি অভিব্যক্তি। এটি (unsigned char)_cশুরু হয় এমন অ্যারের অবস্থান অ্যাক্সেস করে (_ctype_ + 1)

কোড কাস্ট _cথেকে intথেকে unsigned charকঠোরভাবে প্রয়োজন নেই: ctype ফাংশন নিক্ষেপ গৃহস্থালির কাজ মান নিতে unsigned char( charOpenBSD স্বাক্ষরিত হয়): একটি সঠিক কল char c; … iscntrl((unsigned char)c)। তাদের গ্যারান্টি দেওয়ার সুবিধা রয়েছে যে সেখানে কোনও বাফার ওভারফ্লো নেই: যদি অ্যাপ্লিকেশনটি iscntrlএমন কোনও মানের সাথে কল করে যা সীমার বাইরে unsigned charনয় এবং -1 নয়, এই ফাংশনটি এমন কোনও মূল্য দেয় যা অর্থবহ না হলেও কমপক্ষে ঘটায় না ক্র্যাশ বা ব্যক্তিগত তথ্য ফাঁস যা অ্যারের সীমানার বাইরের ঠিকানায় ছিল। যদি ফাংশনটি -1 না হয় char c; … iscntrl(c)যতক্ষণ cনা ডাকা হয় মানটিও সঠিক হয়।

-1 এর সাথে বিশেষ মামলার কারণ এটি EOF। অনেক প্রমিত C ফাংশন যে একটি কাজ char, উদাহরণস্বরূপ getchar, একটি চরিত্রেও প্রতিনিধিত্ব intমান যা একটি ইতিবাচক পরিসরের আবৃত গৃহস্থালির কাজ মান, এবং বিশেষ মান ব্যবহার EOF == -1ইঙ্গিত কোনো অক্ষর পড়তে যেতে পারে। মতো কাজগুলির জন্য getchar, EOFফাইলের শেষে, তাই নাম নির্দেশ করে nd- F- Ile। এরিক পোস্টপিসিল পরামর্শ দেয় যে কোডটি মূলত স্রেফ ছিল return _ctype_[_c + 1]এবং সম্ভবত এটি সঠিক: ইওএফের_ctype_[0] জন্য মান হবে। এই কার্যকর প্রয়োগটি যদি ফাংশনটির অপব্যবহার করা হয় তবে একটি বাফার ওভারফ্লোতে পাওয়া যায়, যদিও বর্তমান বাস্তবায়ন এটি উপরে বর্ণিত হিসাবে এড়িয়ে চলে।

যদি vমান অ্যারের মধ্যে পাওয়া যায়, v & _Cপরীক্ষা বিট এ যদি 0x20সেট করা হয় v। অ্যারের মানগুলি হল বিভাগগুলির মুখোশ যা অক্ষরটি থাকে: _Cনিয়ন্ত্রণ অক্ষরের _Uজন্য সেট করা হয়, বড় হাতের অক্ষর ইত্যাদির জন্য সেট করা হয় ইত্যাদি are


(_ctype_ + 1)[_c] হবে যেমন সি মান দ্বারা নির্দিষ্ট সঠিক অ্যারে সূচক, ব্যবহার কারণ এটা হয় পাস ব্যবহারকারীর দায়িত্ব, EOFঅথবা একটি unsigned charমান। অন্যান্য মানের জন্য আচরণ সি মান দ্বারা সংজ্ঞায়িত করা হয় না। Castালাই সি স্ট্যান্ডার্ডের দ্বারা প্রয়োজনীয় আচরণটি প্রয়োগ করে না। প্রোগ্রামারদের দ্বারা ভুলভাবে নেতিবাচক চরিত্রের মানগুলি পাস করার কারণে হওয়া বাগগুলি থেকে রক্ষা পাওয়ার জন্য এটি একটি কার্যনির্বাহী কাজ। তবে এটি অসম্পূর্ণ বা ভুল (এবং সংশোধন করা যায় না) কারণ একটি character1 চরিত্রের মানটি অবশ্যই অগত্যা হিসাবে বিবেচিত হবে EOF
এরিক পোস্টপিশিল

এটি এর একটি ব্যাখ্যাও দেয় + 1। যদি ম্যাক্রো আগে এই প্রতিরক্ষামূলক সামঞ্জস্য না রাখে, তবে এটি কেবল নিখরচায় প্রয়োগ করা যেতে পারে ((_ctype_+1)[_c] & _C), সুতরাং এইভাবে প্রাক-সমন্বয় মানগুলি −1 থেকে 255 এর সাথে সূচিযুক্ত একটি সারণী ছিল So সুতরাং প্রথম এন্ট্রিটি এড়ানো হয়নি এবং কোনও উদ্দেশ্য কার্যকর করা হয়নি। পরে যখন কেউ প্রতিরক্ষামূলক castালাই যুক্ত করেছে, তখন EOFcast1 এর মান সেই কাস্টের সাথে কাজ করবে না, তাই তারা শর্তসাপেক্ষ অপারেটরটিকে এটি বিশেষভাবে চিকিত্সার জন্য যুক্ত করেছিল।
এরিক পোস্টপিশিল

2

আমি পদক্ষেপ 3 দিয়ে শুরু করব:

অ্যাড্রেসটি পূর্বনির্ধারিত পয়েন্টারটিকে 1 দ্বারা বাড়িয়ে দিন

পয়েন্টারটি অপরিজ্ঞাত নয় । এটি কেবলমাত্র কয়েকটি অন্যান্য সংকলনের ইউনিটে সংজ্ঞায়িত করা হয়েছে। এই externঅংশটি সংকলকটি বলে। সুতরাং যখন সমস্ত ফাইল একসাথে লিঙ্ক হয়, লিঙ্কারটি এর উল্লেখগুলি সমাধান করবে।

সুতরাং এটি কি নির্দেশ করে?

এটি প্রতিটি চরিত্র সম্পর্কে তথ্য সহ একটি অ্যারে নির্দেশ করে। প্রতিটি চরিত্রের নিজস্ব প্রবেশ রয়েছে। একটি এন্ট্রি চরিত্রের জন্য বৈশিষ্ট্যগুলির একটি বিটম্যাপ উপস্থাপনা। উদাহরণস্বরূপ: বিট 5 সেট করা থাকলে এর অর্থ হ'ল অক্ষরটি একটি নিয়ন্ত্রণ চরিত্র। আর একটি উদাহরণ: বিট 0 সেট করা থাকলে এর অর্থ হ'ল অক্ষরটি একটি উচ্চতর অক্ষর।

সুতরাং এর মতো এমন কিছু (_ctype_ + 1)['x']বৈশিষ্ট্যগুলি প্রয়োগ করবে যা প্রযোজ্য 'x'। তারপরে একটি বিটওয়াইজ এবং বিট 5 সেট করা আছে কিনা তা পরীক্ষা করার জন্য সঞ্চালিত হয়, অর্থাত এটি নিয়ন্ত্রণের অক্ষর কিনা তা পরীক্ষা করে দেখুন।

1 যুক্ত করার কারণ সম্ভবত এটিই হ'ল আসল সূচক 0 কোনও বিশেষ উদ্দেশ্যে সংরক্ষিত।


1

এখানে সমস্ত তথ্য উত্স কোড (এবং প্রোগ্রামিং অভিজ্ঞতা) বিশ্লেষণের উপর ভিত্তি করে।

ঘোষণা

extern const char *_ctype_;

সংকলককে বলে যে const charকোথাও নামের একটি পয়েন্টার রয়েছে _ctype_

(4) এই পয়েন্টারটি অ্যারে হিসাবে অ্যাক্সেস করা হয়।

(_ctype_ + 1)[(unsigned char)_c]

কাস্টটি (unsigned char)_cসূচকের মানটি unsigned char(0..255) এর মধ্যে রয়েছে তা নিশ্চিত করে ।

পয়েন্টার গাণিতিক _ctype_ + 1কার্যকরভাবে 1 উপাদান দ্বারা অ্যারের অবস্থানটি স্থানান্তর করে। আমি জানি না কেন তারা এভাবে অ্যারে প্রয়োগ করেছিল implemented পরিসরটি ব্যবহার করে _ctype_[1].. _ctype[256]চরিত্রের মানগুলির জন্য 0.. এই ফাংশনের জন্য 255মানটিকে _ctype_[0]অব্যবহৃত রাখে । (1 এর অফসেটটি বেশ কয়েকটি বিকল্প উপায়ে প্রয়োগ করা যেতে পারে))

অ্যারে অ্যাক্সেস charঅ্যারে সূচক হিসাবে অক্ষরের মানটি ব্যবহার করে একটি মান (প্রকারের সংরক্ষণের জন্য) পুনরুদ্ধার করে।

(5) বিটওয়াস এবং অপারেশন মান থেকে একক বিট বের করে।

স্পষ্টতই অ্যারের থেকে প্রাপ্ত মানটি একটি বিট ক্ষেত্র হিসাবে ব্যবহৃত হয় যেখানে বিট 5 (কমপক্ষে উল্লেখযোগ্য বিট থেকে 0 থেকে গণনা করা 0x20হচ্ছে = = ) "একটি নিয়ন্ত্রণ অক্ষর" এর পতাকা। সুতরাং অ্যারেটিতে অক্ষরের বৈশিষ্ট্যগুলি বর্ণনা করে বিট ফিল্ডের মান রয়েছে।


আমি অনুমান করি + 1যে তারা এটির 1..256পরিবর্তে উপাদানগুলিতে অ্যাক্সেস করছে তা পরিষ্কার করার জন্য তারা পয়েন্টারে স্থানান্তরিত করেছে 1..255,0_ctype_[1 + (unsigned char)_c]অন্তর্ভুক্ত রূপান্তর কারণে সমতুল্য হত int। এবং _ctype_[(_c & 0xff) + 1]আরও স্পষ্ট এবং সংক্ষিপ্ত হতে হবে।
মাস্টার -

0

এখানে কীটি বোঝা যাচ্ছে যে এক্সপ্রেশনটি কী (_ctype_ + 1)[(unsigned char)_c]করে (যা পরে বিটওয়াইস এবং অপারেশনকে খাওয়ানো হয় , & 0x20ফলাফলটি পেতে!

সংক্ষিপ্ত উত্তর: এটি _c + 1অ্যারের উপাদানটিকে নির্দেশিত করে ফেরত দেয় _ctype_

কিভাবে?

প্রথমত, যদিও আপনি মনে করেন _ctype_এটি অপরিজ্ঞিত এটি আসলে তা নয়! শিরোনাম এটিকে বাহ্যিক পরিবর্তনশীল হিসাবে ঘোষনা করে - তবে এটি (প্রায় অবশ্যই) রান-টাইম লাইব্রেরির একটিতে সংজ্ঞায়িত করা হয় যা আপনি যখন এটি তৈরি করেন তখন আপনার প্রোগ্রামের সাথে এটি সংযুক্ত থাকে।

সিনট্যাক্স অ্যারে ইনডেক্সিংয়ের সাথে কীভাবে সামঞ্জস্য করে তা চিত্রিত করতে, নিম্নলিখিত সংক্ষিপ্ত প্রোগ্রামটির মাধ্যমে (এমনকি সংকলন) কাজ করার চেষ্টা করুন:

#include <stdio.h>
int main() {
    // Code like the following two lines will be defined somewhere in the run-time
    // libraries with which your program is linked, only using _ctype_ in place of _qlist_ ...
    const char list[] = "abcdefghijklmnopqrstuvwxyz";
    const char* _qlist_ = list;
    // These two lines show how expressions like (a)[b] and (a+1)[b] just boil down to
    // a[b] and a[b+1], respectively ...
    char p = (_qlist_)[6];
    char q = (_qlist_ + 1)[6];
    printf("p = %c  q = %c\n", p, q);
    return 0;
}

আরও স্পষ্টতা এবং / অথবা ব্যাখ্যা জিজ্ঞাসা করতে নির্দ্বিধায়।


0

ctype.hধরণের গৃহীত বস্তুগুলিতে ঘোষিত ফাংশনগুলি int। আর্গুমেন্ট হিসাবে ব্যবহৃত অক্ষরগুলির জন্য ধারণা করা হয় যে এগুলি প্রাথমিকভাবে টাইপ করা হয়েছে unsigned char। এই অক্ষরটি একটি সারণীতে সূচক হিসাবে ব্যবহৃত হয় যা চরিত্রের বৈশিষ্ট্য নির্ধারণ করে।

মনে হয় চেকটি _c == -1এমন ক্ষেত্রে ব্যবহৃত হয় যখন _cএর মান থাকে EOF। যদি এটি না হয় EOFতবে _c টাইপ স্বাক্ষরযুক্ত চরকে নিক্ষিপ্ত করা হয় যা প্রকাশের দ্বারা নির্দেশিত সারণীতে সূচক হিসাবে ব্যবহৃত হয় _ctype_ + 1। এবং যদি মুখোশ দ্বারা নির্দিষ্ট বিট 0x20সেট করা থাকে তবে অক্ষরটি একটি নিয়ন্ত্রণ প্রতীক।

এক্সপ্রেশন বুঝতে

(_ctype_ + 1)[(unsigned char)_c]

অ্যারে সাবস্ক্রিপশন একটি পোস্টফিক্স অপারেটর যা এর মতো সংজ্ঞায়িত করা হয় তা বিবেচনা করুন

postfix-expression [ expression ]

আপনি যেমন লিখতে পারে না

_ctype_ + 1[(unsigned char)_c]

কারণ এই অভিব্যক্তি সমান

_ctype_ + ( 1[(unsigned char)_c] )

সুতরাং _ctype_ + 1একটি প্রাথমিক এক্সপ্রেশন পেতে এক্সপ্রেশনটি বন্ধনীতে আবদ্ধ।

আসলে আপনি আছে

pointer[integral_expression]

যে সূচকটিতে একটি অ্যারের অবজেক্ট দেয় যা integral_expressionপয়েন্টার হিসাবে অভিব্যক্তি হিসাবে গণনা করা হয় (_ctype_ + 1)( পয়েন্টার অ্যারিমেটিক ব্যবহার করা হয়) এবং integral_expressionতা সূচকটি হ'ল প্রকাশ (unsigned char)_c

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