সিতে কাঠামো ফিরিয়ে দেয় এমন অনেকগুলি কার্যকারিতা কেন আসলে কাঠামোগুলিতে পয়েন্টার ফেরত দেয়?


49

returnফাংশনের বিবৃতিতে পুরো কাঠামোটি ফিরিয়ে দেওয়ার বিপরীতে কোনও কাঠামোতে পয়েন্টার ফিরিয়ে দেওয়ার সুবিধা কী ?

আমি মত fopenএবং অন্যান্য নিম্ন স্তরের ফাংশন সম্পর্কে কথা বলছি তবে সম্ভবত উচ্চ স্তরের ফাংশন রয়েছে যা কাঠামোগুলিতেও পয়েন্টারগুলি ফেরত দেয়।

আমি বিশ্বাস করি যে এটি কেবলমাত্র একটি প্রোগ্রামিং প্রশ্নের চেয়ে একটি নকশা পছন্দ এবং আমি দুটি পদ্ধতির সুবিধা এবং অসুবিধাগুলি সম্পর্কে আরও জানতে আগ্রহী।

যে কারণগুলির মধ্যে আমি ভেবেছিলাম এটির মধ্যে একটি বিন্যাসে কোনও পয়েন্টার ফিরিয়ে দেওয়া একটি সুবিধা হবে তা হল পয়েন্টারটি ফিরে দিয়ে ফাংশনটি ব্যর্থ হলে আরও সহজেই বলতে সক্ষম NULLহোন।

এমন একটি পূর্ণ কাঠামো ফিরে পাওয়া NULLযা আমি মনে করি আরও শক্ত বা কম দক্ষ would এটি কি বৈধ কারণ?


9
@ জনআর.স্ট্রোহম আমি চেষ্টা করেছিলাম এবং এটি আসলে কাজ করে। একটি ফাংশন একটি কাঠামো ফিরে আসতে পারে .... সুতরাং কারণ কি না হয়?
yoyo_fun

27
প্রাক-মানীকরণ সি স্ট্রাইকগুলি অনুলিপি করতে বা মান দ্বারা পাস করার অনুমতি দেয় না। সি স্ট্যান্ডার্ড লাইব্রেরিতে সেই যুগের অনেকগুলি হোল্ডআউট রয়েছে যা আজ সেভাবে লেখা হবে না, যেমন সি 11 পর্যন্ত পুরোপুরি ভুল নকশাকৃত gets()ফাংশনটি সরিয়ে ফেলতে সময় লাগল । কিছু প্রোগ্রামার এখনও স্ট্রিপি অনুলিপি করতে একটি বিরক্তি আছে, পুরানো অভ্যাস কঠোরভাবে মারা যায়।
আমন

26
FILE*কার্যকরভাবে একটি অস্বচ্ছ হ্যান্ডেল। ব্যবহারকারী কোডটির অভ্যন্তরীণ কাঠামো কী তা যত্নশীল হওয়া উচিত নয়।
কোডসইনচওস

3
আপনার আবর্জনা সংগ্রহ করার সময় কেবলমাত্র রেফারেন্সের মাধ্যমে ফেরত দেওয়া যুক্তিসঙ্গত ডিফল্ট।
ইদান আরে

6
@ জনআর.স্ট্রোহম আপনার প্রোফাইলে "খুব সিনিয়র" মনে হচ্ছে 1989 ;-) এর আগে ফিরে যেতে পারে - যখন এএনএসআই সি যখন কে ও আর সি এর অনুমতি দেয় না তখন: অ্যাসাইনমেন্ট, প্যারামিটার পাসিং এবং রিটার্ন মানগুলির কাঠামো অনুলিপি করে। কে অ্যান্ড আর এর মূল বইটি প্রকৃতপক্ষে স্পষ্টভাবে জানিয়েছে (আমি প্যারাফ্রেসিং করছি): "আপনি কোনও কাঠামো দিয়ে ঠিক দুটি জিনিস করতে পারেন, এর ঠিকানাটি সহ & এবং কোনও সদস্যের সাথে অ্যাক্সেস করতে পারেন .।"
পিটার - মনিকা

উত্তর:


61

বিভিন্ন কারণের কারণগুলির কারণগুলির fopenপরিবর্তে পুনরায় পয়েন্টারগুলির মতো ফাংশনগুলি রয়েছে struct:

  1. আপনি structব্যবহারকারীর কাছ থেকে প্রকারের উপস্থাপনাটি গোপন করতে চান ;
  2. আপনি একটি বস্তুকে গতিশীলভাবে বরাদ্দ দিচ্ছেন;
  3. আপনি একাধিক রেফারেন্সের মাধ্যমে কোনও জিনিসের একক উদাহরণকে উল্লেখ করছেন;

এর মতো ধরণের ক্ষেত্রে, FILE *কারণ আপনি ব্যবহারকারীর কাছে টাইপের প্রতিনিধিত্বের বিশদটি প্রকাশ করতে চান না - কোনও FILE *বস্তু অস্বচ্ছ হ্যান্ডেল হিসাবে কাজ করে, এবং আপনি কেবল সেই হ্যান্ডেলটি বিভিন্ন I / O রুটিনগুলিতে প্রেরণ করেন (এবং FILEপ্রায়শই যখন থাকে একটি হিসাবে প্রয়োগ করা structধরন, এটা না আছে হতে)।

সুতরাং, আপনি কোথাও শিরোনামে অসম্পূর্ণ struct প্রকারটি প্রকাশ করতে পারেন :

typedef struct __some_internal_stream_implementation FILE;

আপনি অসম্পূর্ণ প্রকারের উদাহরণটি প্রকাশ করতে না পারলেও আপনি এটিতে একটি পয়েন্টার ঘোষণা করতে পারেন। তাই আমি একটি তৈরি করতে পারেন FILE *এবং এটি মাধ্যমে বরাদ্দ fopen, freopenইত্যাদি, কিন্তু আমি সরাসরি বস্তুর এটি পয়েন্ট নিপূণভাবে করতে পারবে না।

এটিও সম্ভবত যে fopenফাংশনটি কোনও FILEবস্তুকে গতিশীলভাবে বরাদ্দ করছে , ব্যবহার করে mallocবা অনুরূপ। সেক্ষেত্রে পয়েন্টারটি ফিরতে বোঝা যায়।

অবশেষে, এটি সম্ভব যে আপনি কোনও জিনিসে কোনও ধরণের রাজ্য সংরক্ষণ করছেন structএবং আপনাকে সেই রাজ্যটি বিভিন্ন স্থানে উপলভ্য করতে হবে। আপনি যদি structপ্রকারের উদাহরণগুলি ফেরৎ করেন তবে সেই দৃষ্টান্তগুলি একে অপরের থেকে মেমরির পৃথক বস্তু হবে এবং শেষ পর্যন্ত সিঙ্ক থেকে বেরিয়ে আসবে। একটি একক বস্তুতে একটি পয়েন্টার ফিরিয়ে দিয়ে, প্রত্যেকের একই অবজেক্টের উল্লেখ করা হয়।


31
অস্বচ্ছ ধরণের হিসাবে পয়েন্টারটি ব্যবহার করার একটি বিশেষ সুবিধা হ'ল কাঠামোগুলি নিজেই গ্রন্থাগারের সংস্করণগুলির মধ্যে পরিবর্তন করতে পারে এবং আপনার কলারগুলিকে পুনরায় সংকলনের প্রয়োজন হবে না।
বার্মার 21

6
বার্মার: সত্যই, এবিআই স্থিতিশীলতা সি এর বিশাল বিক্রয় কেন্দ্র এবং এটি অস্বচ্ছ পয়েন্টার ছাড়া স্থিতিশীল হবে না।
ম্যাথিউ এম।

37

"কাঠামো ফিরে আসার" দুটি উপায় রয়েছে। আপনি ডেটার একটি অনুলিপি ফিরে দিতে পারেন, বা আপনি এটিতে একটি রেফারেন্স (পয়েন্টার) ফিরিয়ে দিতে পারেন। এটি বেশ কয়েকটি কারণে পয়েন্টারটি ফিরে আসার (এবং সাধারণভাবে পাস করার জন্য) পছন্দ করে।

প্রথমত, কাঠামোর অনুলিপি করতে পয়েন্টারটি অনুলিপি করার চেয়ে অনেক বেশি সিপিইউ সময় লাগে। যদি আপনার কোডটি ঘন ঘন এমন কিছু করে তবে তা পারফরম্যান্সের পার্থক্য দেখা দিতে পারে।

দ্বিতীয়ত, আপনি চারপাশে কোনও পয়েন্টারটি অনুলিপি করেছেন কতবারই না, এটি এখনও স্মৃতিতে একই কাঠামোর দিকে ইশারা করে। এটিতে সমস্ত পরিবর্তনগুলি একই কাঠামোতে প্রতিফলিত হবে। তবে আপনি যদি কাঠামোটি নিজেই অনুলিপি করেন এবং তারপরে একটি পরিবর্তন করেন তবে পরিবর্তনটি কেবল সেই অনুলিপিটিতে প্রদর্শিত হয় । যে কোনও কোড যা একটি আলাদা অনুলিপি ধারণ করে সেই পরিবর্তনটি দেখতে পাবে না। কখনও কখনও, খুব কমই, এটি আপনি চান তবে বেশিরভাগ সময় এটি হয় না এবং এটি ভুল হয়ে থাকলে এটি বাগের কারণ হতে পারে।


54
পয়েন্টার দ্বারা ফিরে আসার অসুবিধা: এখন আপনি object বস্তুর মালিকানা ট্র্যাক এবং এটি সম্ভব বিনামূল্যে পেয়েছি। এছাড়াও, দ্রুত কপির চেয়ে পয়েন্টার ইন্ডিয়ারেশন বেশি ব্যয়বহুল হতে পারে। এখানে প্রচুর ভেরিয়েবল রয়েছে, সুতরাং পয়েন্টার ব্যবহার করা সর্বজনীনভাবে ভাল নয়।
আমন

17
এছাড়াও, পয়েন্টারগুলি আজকাল বেশিরভাগ ডেস্কটপ এবং সার্ভার প্ল্যাটফর্মগুলিতে 64 বিট are আমি আমার ক্যারিয়ারে কয়েকটি স্ট্রাকের বেশি দেখেছি যা 64৪ বিটের মধ্যে ফিট হবে। সুতরাং, আপনি সবসময় বলতে পারবেন না যে পয়েন্টার অনুলিপি করা স্ট্রাক্ট অনুলিপি করার চেয়ে কম ব্যয় করে।
সলোমন আস্তে আস্তে

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

6
এটি লক্ষ করা উচিত যে এটি কেবলমাত্র বাহ্যিক APIগুলির জন্য প্রযোজ্য। অভ্যন্তরীণ ফাংশনগুলির জন্য গত দশকগুলির প্রতিটি এমনকি প্রান্তিকভাবে সক্ষম সংকলক একটি ফাংশন পুনর্লিখন করবে যা একটি অতিরিক্ত কাঠামোকে অতিরিক্ত যুক্তি হিসাবে পয়েন্টার হিসাবে নিতে এবং সেখানে অবজেক্টটি সরাসরি সেখানে নির্মাণ করতে পুনরায় লিখন করে। অপরিবর্তনীয় বনাম পরিবর্তনীয় যুক্তিগুলি প্রায়শই যথেষ্ট হয়ে গেছে, তবে আমি মনে করি যে আমরা সকলেই একমত হতে পারি যে অপরিবর্তনীয় ডেটা স্ট্রাকচারগুলি আপনি যা চান তা প্রায় কখনওই সত্য নয়।
ভু

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

12

অন্যান্য উত্তরের পাশাপাশি, কখনও কখনও মূল্য দিয়ে একটি ছোট ফিরিয়ে দেওয়া structসার্থক। উদাহরণস্বরূপ, কেউ একটি ডেটার একজোড়া এবং এর সাথে সম্পর্কিত কিছু ত্রুটি (বা সাফল্য) কোড ফিরিয়ে দিতে পারে।

উদাহরণস্বরূপ, fopenকেবলমাত্র একটি ডেটা (খোলা FILE*) প্রদান করে এবং ত্রুটির ক্ষেত্রে, errnoসিউডো-গ্লোবাল ভেরিয়েবলের মাধ্যমে ত্রুটি কোড দেয় । তবে structদু'জন সদস্যের মধ্যে একজনকে ফেরত দেওয়া আরও ভাল হবে : FILE*হ্যান্ডেলটি এবং ত্রুটি কোডটি (ফাইল হ্যান্ডেলটি যদি সেট করা থাকে NULL)। Reasonsতিহাসিক কারণে এটি হয় না (এবং errnoবিশ্বব্যাপী ত্রুটিগুলি রিপোর্ট করা হয় , যা আজ একটি ম্যাক্রো)।

লক্ষ্য করুন যে দুটি ভাষার (বা কয়েকটি) মান ফেরত দেওয়ার জন্য গো ভাষার একটি দুর্দান্ত স্বরলিপি রয়েছে।

আরও লক্ষ করুন, লিনাক্স / x86-64 এবিআই এবং কলিং কনভেনশনগুলিতে ( x86-psABI পৃষ্ঠা দেখুন) উল্লেখ করে যে structদুটি স্কেলার সদস্যের মধ্যে একটি (যেমন একটি পয়েন্টার এবং একটি পূর্ণসংখ্যা, বা দুটি পয়েন্টার, বা দুটি পূর্ণসংখ্যার) দুটি রেজিস্ট্রারের মাধ্যমে ফিরে আসে (এবং এটি খুব দক্ষ এবং স্মৃতি থেকে যায় না)।

সুতরাং নতুন সি কোডে, একটি ছোট সি ফিরিয়ে দেওয়া structআরও পাঠযোগ্য, আরও থ্রেড-বান্ধব এবং আরও দক্ষ হতে পারে।


আসলে ছোট স্ট্রাক্টগুলি প্যাক করা হয় rdx:rax। তাই struct foo { int a,b; };প্যাক করে ফেরত দেওয়া হয় rax(উদাঃ শিফট / বা সহ), এবং শিফট / মুভ দিয়ে আনপ্যাক করা উচিত। এখানে গডবোল্টের একটি উদাহরণ । তবে x86 উচ্চ বিট সম্পর্কে যত্ন না নিয়ে 32-বিট ক্রিয়াকলাপের জন্য 64-বিট নিবন্ধের কম 32 বিট ব্যবহার করতে পারে, তাই এটি সর্বদা খুব খারাপ তবে 2-সদস্যের স্ট্রাক্টের জন্য বেশিরভাগ সময় 2 টি রেজিস্টার ব্যবহার করার চেয়ে খারাপ।
পিটার কর্ডস

সম্পর্কিত: bugs.llvm.org/show_bug.cgi?id=34840 std::optional<int> বুলিয়ানটির উপরের অর্ধে ফিরে আসে rax, সুতরাং এটি পরীক্ষা করার জন্য আপনার একটি 64-বিট মুখোশ ধ্রুব দরকার test। অথবা আপনি ব্যবহার করতে পারে bt। তবে এটি কলকারী এবং কলি ব্যবহারের সাথে তুলনা করে dl, যা "ব্যক্তিগত" ফাংশনগুলির জন্য কম্পাইলারদের করা উচিত suc এছাড়াও সম্পর্কিত: টি লাইভেস্টডিসি ++ এর std::optional<T>তুচ্ছ-অনুলিপিযোগ্য নয়, সুতরাং এটি সর্বদা লুকানো পয়েন্টারটির মাধ্যমে ফিরে আসে: stackoverflow.com/questions/46544019/… । (লিবিসি ++ এর তুচ্ছ-অনুলিপিযোগ্য)
পিটার

@ পিটারকর্ডস: আপনার সম্পর্কিত জিনিসগুলি সি নয় + সি, সি নয়
বেসাইল স্টারিঙ্কেভিচ

উফ, ঠিক আছে। ওয়েল একই জিনিস প্রযোজ্য হবে ঠিক করতে struct { int a; _Bool b; };সি, যদি কলার, বুলিয়ান পরীক্ষা করার কারণ জাভাস্ক্রিপ্টে গার্বেজ-copyable সি ++ structs মধ্যে সি হিসাবে একই ABI- র ব্যবহার চেয়েছিলেন
পিটার Cordes

1
ক্লাসিক উদাহরণdiv_t div()
chux - মনিকা

6

আপনি সঠিক পথে আছেন

আপনার উল্লিখিত দুটি কারণই বৈধ:

যে কারণগুলির মধ্যে আমি ভেবেছিলাম এটির মধ্যে একটি বিন্যাসে কোনও পয়েন্টার ফিরিয়ে দেওয়া একটি সুবিধা হবে তা হল NUL পয়েন্টারটি ফিরিয়ে ফাংশনটি ব্যর্থ হলে আরও সহজেই বলতে সক্ষম হোন।

একটি পূর্ণ কাঠামো যা নুল হয় তা ফেরত পাওয়া আমার পক্ষে শক্ত বা কম দক্ষ বলে মনে হয়। এটি কি বৈধ কারণ?

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

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

এর একটি ভাল উদাহরণ ব্যবহারকারী দ্বারা নির্দিষ্ট করা একটি ফাইল থেকে পড়া। এই ক্ষেত্রে, আপনি প্রোগ্রামটি সংকলন করার সময় ফাইলটি কত বড় হতে পারে সে সম্পর্কে আপনার কোনও ধারণা নেই। আপনি যখন প্রোগ্রামটি চালু তখন আপনার কতটা মেমরি দরকার তা কেবল আপনিই বুঝতে পারবেন।

ম্যালোক এবং ফ্রি রিটার্ন পয়েন্টার উভয়ই মেমোরিতে অবস্থিত। সুতরাং গতিশীল মেমরি বরাদ্দ ব্যবহার করে এমন ফাংশনগুলি পয়েন্টারগুলিকে ফিরে আসবে যেখানে তারা মেমরিতে তাদের কাঠামো তৈরি করেছে।

এছাড়াও, মন্তব্যে আমি দেখতে পাচ্ছি যে আপনি কোনও ফাংশন থেকে কোনও কাঠামো ফিরিয়ে দিতে পারবেন কিনা তা নিয়ে একটি প্রশ্ন রয়েছে। আপনি সত্যিই এটি করতে পারেন। নিম্নলিখিতগুলি কাজ করা উচিত:

struct s1 {
   int integer;
};

struct s1 f(struct s1 input){
   struct s1 returnValue = xinput
   return returnValue;
}

int main(void){
   struct s1 a = { 42 };
   struct s1 b= f(a);

   return 0;
}

আপনার যদি ইতিমধ্যে স্ট্রাক্টের সংজ্ঞা দেওয়া থাকে তবে নির্দিষ্ট ভেরিয়েবলের কতটুকু স্মৃতি প্রয়োজন তা কীভাবে জানা সম্ভব নয়?
yoyo_fun

9
@ জেনিফার অ্যান্ডারসন সি-এর অসম্পূর্ণ প্রকারের ধারণা রয়েছে: একটি প্রকারের নাম ঘোষণা করা যেতে পারে তবে এখনও সংজ্ঞায়িত করা যায় না, সুতরাং এটির আকারটি উপলভ্য নয়। আমি যে ধরনের ভেরিয়েবল ডিক্লেয়ার করতে পারেন না, কিন্তু ডিক্লেয়ার করতে পারেন পয়েন্টার যে ধরনের, যেমন struct incomplete* foo(void)। এইভাবে আমি একটি শিরোনামে ফাংশনগুলি ডিক্লেয়ার করতে পারি, তবে কেবলমাত্র একটি সি ফাইলের মধ্যে স্ট্রাক্টগুলি সংজ্ঞায়িত করতে পারি, এইভাবে এনক্যাপসুলেশনের অনুমতি দেয়।
আমন

@ এ্যামন সুতরাং ফাংশন শিরোনামগুলি (প্রোটোটাইপস / স্বাক্ষর) ডিক্লেয়ার করার আগে তারা কীভাবে কাজ করে তা বাস্তবে সি তে সম্পন্ন হয়? এবং সি
yoyo_fun

@ জেনিফার অ্যান্ডারসন আপনি শিরোনাম ফাইলগুলিতে ফাংশন প্রোটোটাইপগুলি ( দেহবিহীন ফাংশন ) ঘোষণা করেন এবং তারপরে ফাংশনগুলির দেহ না জেনে অন্য কোডগুলিতে functions ফাংশনগুলি কল করতে পারেন, কারণ সংকলকটিকে কেবল আর্গুমেন্টগুলি কীভাবে সাজানো যায় এবং কীভাবে গ্রহণ করতে হয় তা জানতে হবে because ফেরত মূল্য. আপনি প্রোগ্রামটি সংযুক্ত করার সময়, আপনাকে আসলে ফাংশন সংজ্ঞাটি জানতে হবে (অর্থাত্ একটি দেহ সহ), তবে আপনাকে কেবল একবার এটি প্রক্রিয়া করতে হবে। আপনি যদি অ-সরল প্রকার ব্যবহার করেন তবে এ ধরণের কাঠামোটিও জানতে হবে তবে পয়েন্টারগুলি প্রায়শই একই আকারের হয় এবং প্রোটোটাইপের ব্যবহারের জন্য এটি কোনও বিষয় নয়।
সরলবহর

6

FILE*ক্লায়েন্ট কোড সম্পর্কিত যতটা কাঠামোর মতো কোনও বিষয় সত্যই এটির নির্দেশক নয়, তবে পরিবর্তে এটি কোনও ফাইলের মতো কিছু অন্যান্য সত্তার সাথে সম্পর্কিত অস্বচ্ছ শনাক্তকারীগুলির একটি ফর্ম । যখন কোনও প্রোগ্রাম কল করে fopen, এটি সাধারণত ফিরে আসা কাঠামোর যে কোনও বিষয়বস্তু সম্পর্কে চিন্তা করে না - এটির জন্য যত্ন নেওয়া হবে যে অন্যান্য ফাংশনগুলি freadএটির সাথে যা করার প্রয়োজন তা করবে।

যদি কোনও স্ট্যান্ডার্ড লাইব্রেরি FILE*সেই ফাইলের মধ্যে যেমন বর্তমানের পড়ার অবস্থান সম্পর্কিত কোনও তথ্য রাখে , একটি কল করতে freadসেই তথ্যটি আপডেট করতে সক্ষম হওয়া প্রয়োজন। রয়ে freadএকটি পয়েন্টার গ্রহণ FILEকরে তোলে সহজ। freadপরিবর্তে FILEএটি যদি একটি পেয়ে থাকে FILEতবে কলারের কাছে থাকা এই অবজেক্টটি আপডেট করার কোনও উপায় নেই ।


3

তথ্য গোপন

ফাংশনের রিটার্ন স্টেটমেন্টে পুরো কাঠামোটি ফিরিয়ে দেওয়ার বিপরীতে কোনও কাঠামোর পয়েন্টার ফিরিয়ে দেওয়ার সুবিধা কী?

সর্বাধিক সাধারণ তথ্য হাইডিং । সি এর কোনও structপ্রাইভেটের ক্ষেত্র তৈরি করার ক্ষমতা নেই , এগুলি অ্যাক্সেসের জন্য পদ্ধতি সরবরাহ করুন।

সুতরাং যদি আপনি বিকাশকারীদের পয়েন্টটির বিষয়বস্তুগুলি দেখতে পছন্দ করতে এবং ছদ্মবেশে জোর করে আটকাতে চান FILEতবে একমাত্র এবং একমাত্র উপায় হ'ল পয়েন্টারটিকে অস্বচ্ছ হিসাবে বিবেচনা করে তার সংজ্ঞাটির সংস্পর্শে আনা থেকে বাধা দেওয়া যার পয়েন্টটির আকার এবং সংজ্ঞা বাইরের বিশ্বের অজানা। FILEতারপরে সংজ্ঞাটি কেবল তখনই অপারেশনগুলিকে প্রয়োগ করে যার জন্য তার সংজ্ঞা প্রয়োজন তাদের fopenপক্ষে দৃশ্যমান হবে , যেমন কেবল কাঠামোর ঘোষণাপত্র পাবলিক শিরোনামের জন্য দৃশ্যমান হবে।

বাইনারি সামঞ্জস্য

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

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

দক্ষতা

একটি পূর্ণ কাঠামো যা নুল হয় তা ফেরা আমার পক্ষে শক্ত বা কম দক্ষ বলে মনে হয়। এটি কি বৈধ কারণ?

mallocইতিমধ্যে বরাদ্দকৃত ভেরিয়েবল-সাইজের বরাদ্দকারী পুলিং মেমরির চেয়ে দৃশ্যের আকারের চেয়ে অনেক কম সাধারণীকরণের মেমরির বরাদ্দকারী লোক ব্যবহার না করা না পারলে এটি সাধারণত স্ট্যাকের উপর নির্ভরযোগ্যভাবে প্রকারের জন্য উপযুক্ত হতে পারে এবং ধরে নেওয়া উচিত এটি কম দক্ষ is এই ক্ষেত্রে এটি একটি সুরক্ষা বাণিজ্য-অফ, সম্ভবত গ্রন্থাগার বিকাশকারীদের সম্পর্কিত সম্পর্কিত (ধারণা সংক্রান্ত গ্যারান্টি) বজায় রাখার অনুমতি দেয় FILE

কমপক্ষে পারফরম্যান্সের দৃষ্টিকোণ থেকে fopenকোনও পয়েন্টার রিটার্ন তৈরির পক্ষে এটি বৈধ কারণ নয় কারণ কেবল NULLফাইলটি খোলার ব্যর্থতায় এটিই ফিরে আসবে। এটি সমস্ত সাধারণ ক্ষেত্রে কার্যকর করার পথগুলিকে ধীর করার পরিবর্তে একটি ব্যতিক্রমী দৃশ্যের অনুকূলকরণ করবে। কিছু ক্ষেত্রে NULLশর্ত সাপেক্ষে ফিরে আসার জন্য পয়েন্টারগুলি ফেরত দেওয়ার জন্য ডিজাইনগুলি আরও সহজবোধ্য করার জন্য বৈধ উত্পাদনশীলতার কারণ থাকতে পারে ।

ফাইল অপারেশনের জন্য ওভারহেড ফাইল অপারেশনগুলির তুলনায় নিজের তুলনায় তুলনামূলকভাবে তুচ্ছ এবং ম্যানুয়ালটিকে fcloseযেভাবেই এড়ানো যায় না। সুতরাং এটি এর মতো নয় যে আমরা ক্লায়েন্টকে সংস্থানটি মুক্ত করার (ক্লোজার) ঝামেলা বাঁচাতে পারি FILEএবং সংশ্লেষের দ্বারা মূল্য দিয়ে ফিরিয়ে দিয়ে fopenবা ফাইলের অপারেশনগুলির আপেক্ষিক ব্যয়কে একটি গাদা বরাদ্দ এড়াতে পারফরম্যান্স বৃদ্ধির অনেক আশা করতে পারি ।

হটস্পট এবং ফিক্স

যদিও অন্যান্য ক্ষেত্রে, আমি প্রচুর অপ্রয়োজনীয় সি কোড প্রেরণ করেছি লিগ্যাসি কোডবাসে হটস্পটগুলিতে mallocএবং অযথা বাধ্যতামূলক ক্যাশে মিস হয় এই অভ্যাসটি খুব ঘন ঘন অস্বচ্ছ পয়েন্টার ব্যবহার করে এবং অজস্রভাবে প্রচুর পরিমাণে স্তূপে বরাদ্দ দেওয়া হয় in বড় লুপ

পরিবর্তে আমি ব্যবহার করছি বিকল্প অনুশীলন হ'ল কাঠামোর সংজ্ঞাগুলি প্রকাশ করা, যদিও ক্লায়েন্টটি তাদের ছত্রভঙ্গ করে না, নামকরণের কনভেনশন স্ট্যান্ডার্ডটি ব্যবহার করে যোগাযোগ করার জন্য যে অন্য কারও ক্ষেত্রেও স্পর্শ করা উচিত নয়:

struct Foo
{
   /* priv_* indicates that you shouldn't tamper with these fields! */
   int priv_internal_field;
   int priv_other_one;
};

struct Foo foo_create(void);
void foo_destroy(struct Foo* foo);
void foo_something(struct Foo* foo);

ভবিষ্যতে যদি বাইনারি সামঞ্জস্যের উদ্বেগ থাকে তবে আমি কেবলমাত্র প্রয়োজনের জন্য ভবিষ্যতের উদ্দেশ্যে অতিরিক্ত অতিরিক্ত জায়গা সংরক্ষণ করার পক্ষে যথেষ্ট ভাল পেয়েছি:

struct Foo
{
   /* priv_* indicates that you shouldn't tamper with these fields! */
   int priv_internal_field;
   int priv_other_one;

   /* reserved for possible future uses (emergency backup plan).
     currently just set to null. */
   void* priv_reserved;
};

সংরক্ষিত স্থানটি কিছুটা অপব্যয়যুক্ত তবে জীবন রক্ষাকারী হতে পারে যদি আমরা ভবিষ্যতে খুঁজে পাই Fooযে আমাদের লাইব্রেরি ব্যবহার করে এমন বাইনারিগুলি না ভাঙ্গতে আমাদের আরও কিছু ডেটা যুক্ত করা দরকার ।

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

int foo_create(struct Foo* foo);
...
/* In the client code: */
struct Foo foo;
if (foo_create(&foo))
{
    foo_something(&foo);
    foo_destroy(&foo);
}

... Fooঅত্যধিক অনুলিপি হওয়ার সম্ভাবনা ছাড়াই স্ট্যাক থেকে শুরু করার জন্য। বা ক্লায়েন্ট এমনকি Fooকোনও কারণে তারা চাইলে স্তূপে বরাদ্দ দেওয়ার স্বাধীনতা অর্জন করে ।

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