সি তে কোন ফাংশন স্থির করার বিন্দু কী?
সি তে কোন ফাংশন স্থির করার বিন্দু কী?
উত্তর:
একটি ফাংশন তৈরি করা static
এটি অন্য অনুবাদ ইউনিট থেকে আড়াল করে, যা এনক্যাপসুলেশন সরবরাহ করতে সহায়তা করে ।
helper_file.c
int f1(int); /* prototype */
static int f2(int); /* prototype */
int f1(int foo) {
return f2(foo); /* ok, f2 is in the same translation unit */
/* (basically same .c file) as f1 */
}
int f2(int foo) {
return 42 + foo;
}
main.c :
int f1(int); /* prototype */
int f2(int); /* prototype */
int main(void) {
f1(10); /* ok, f1 is visible to the linker */
f2(12); /* nope, f2 is not visible to the linker */
return 0;
}
#include <helper_file.c>
? আমি মনে করি এটি তখন এটি একটি একক অনুবাদ ইউনিট করে
gcc -std=c99 -pedantic -Wall -Wextra main.c helper_file.c
। ফাংশনগুলির প্রোটোটাইপগুলি উভয় উত্স ফাইলগুলিতে উপস্থিত থাকে (শিরোনাম ফাইলগুলির প্রয়োজন নেই)। লিঙ্কার ফাংশনগুলি সমাধান করবে।
এমপিজি এনপ্যাপুলেশন সম্পর্কে স্পট হয়; অন্যান্য অনুবাদ ইউনিট (বা বরং এর কারণে ) থেকে ফাংশনটি আড়াল করার বাইরে, ফাংশনগুলি static
তৈরি করে সংকলক অপ্টিমাইজেশনের উপস্থিতিতে পারফরম্যান্স সুবিধাও প্রদান করতে পারে।
যেহেতু static
বর্তমান অনুবাদ ইউনিটের বাইরে কোথাও থেকে কোনও ফাংশন কল করা যায় না (যদি না কোডটি তার ঠিকানায় কোনও পয়েন্টার না নেয়), সংকলক এতে সমস্ত কল পয়েন্ট নিয়ন্ত্রণ করে।
এর অর্থ এই যে এটি একটি অ-মানক এবিআই ব্যবহার করা সম্পূর্ণরূপে ইনলাইন, বা বহিরাগত সংযোগের সাথে কোনও ফাংশনের পক্ষে সম্ভব না হতে পারে এমন অনেকগুলি অপ্টিমাইজেশান সম্পাদন বিনামূল্যে।
static
ফাংশনটির পয়েন্টার বর্তমান অনুবাদ ইউনিট থেকে অব্যাহতি পায়, তবে সেই ফাংশনটি অন্য অনুবাদ ইউনিট থেকে সরাসরি কল করা যেতে পারে।
static
সি এর কীওয়ার্ডটি একটি সংকলিত ফাইলে (.c এর বিপরীতে ব্যবহার করা হয়) যাতে ফাংশনটি কেবলমাত্র সেই ফাইলটিতেই বিদ্যমান থাকে।
সাধারণত, আপনি যখন কোনও ফাংশন তৈরি করেন, সংকলকটি ক্রুফ্টটি জেনারেট করে লিঙ্কারটি সেই ফাংশনে একটি ফাংশন কলকে লিঙ্ক করতে, ভালভাবে, যুক্ত করতে পারে। আপনি যদি স্ট্যাটিক কীওয়ার্ডটি ব্যবহার করেন তবে একই ফাইলের মধ্যে থাকা অন্যান্য ফাংশনগুলি এই ফাংশনটিকে কল করতে পারে (কারণ এটি লিঙ্কারের সাথে অবলম্বন না করেই করা যেতে পারে), তবে লিঙ্কারের কাছে অন্য ফাইলগুলিকে ফাংশনে অ্যাক্সেস দেওয়ার সুযোগ নেই।
উপরের পোস্টগুলির দিকে তাকিয়ে আমি একটি বিশদটি উল্লেখ করতে চাই।
ধরুন আমাদের মূল ফাইলটি ("main.c") এর মতো দেখাচ্ছে:
#include "header.h"
int main(void) {
FunctionInHeader();
}
এখন তিনটি ক্ষেত্রে বিবেচনা করুন:
কেস 1: আমাদের হেডার ফাইলটি ("শিরোনাম এইচ") এর মতো দেখাচ্ছে:
#include <stdio.h>
static void FunctionInHeader();
void FunctionInHeader() {
printf("Calling function inside header\n");
}
তারপরে লিনাক্সের জন্য নিম্নলিখিত কমান্ডটি:
gcc main.c header.h -o main
সফল হবে ! এটি অনুসরণ করে যদি একটি রান করে
./main
আউটপুট হবে
হেডারের ভিতরে কলিং ফাংশন
যা স্থির ফাংশন মুদ্রণ করা উচিত।
কেস 2: আমাদের হেডার ফাইলটি ("শিরোনাম এইচ") এর মতো দেখাচ্ছে:
static void FunctionInHeader();
এবং আমাদের আরও একটি ফাইল "header.c" রয়েছে, যা দেখতে এটির মতো দেখাচ্ছে:
#include <stdio.h>
#include "header.h"
void FunctionInHeader() {
printf("Calling function inside header\n");
}
তারপরে নিম্নলিখিত কমান্ড
gcc main.c header.h header.c -o main
একটি ত্রুটি দেবে।
কেস 3:
কেস 2 এর অনুরূপ, এখন আমাদের শিরোনাম ফাইলটি ("শিরোলেখ।") বাদে:
void FunctionInHeader(); // keyword static removed
তারপরে 2 এর মতো একই কমান্ডটি সফল হবে এবং আরও
সুতরাং এই পরীক্ষাগুলি থেকে (এসার x86 মেশিনে চালিত, উবুন্টু ওএস) আমি একটি অনুমান করেছি
স্ট্যাটিক কীওয়ার্ড যেখানে এটি সংজ্ঞায়িত করা হয়েছে তার চেয়ে অন্য * .c ফাইলে কল করতে বাধা দেয় preven
আমি ভুল হলে আমাকে সংশোধন করুন।
সি প্রোগ্রামাররা স্থির বৈশিষ্ট্যটি মডিউলগুলির মধ্যে ভেরিয়েবল এবং ফাংশন ডিক্লেয়ারেশনগুলি আড়াল করতে ব্যবহার করে, যতটা আপনি জাভা এবং সি ++ তে সরকারী এবং ব্যক্তিগত ঘোষণা ব্যবহার করবেন decla সি উত্স ফাইলগুলি মডিউলগুলির ভূমিকা পালন করে। স্থির বৈশিষ্ট্যের সাথে ঘোষিত যে কোনও বৈশ্বিক পরিবর্তনশীল বা ফাংশন সেই মডিউলটির জন্য ব্যক্তিগত। একইভাবে, স্থির বৈশিষ্ট্য ব্যতিরেকে ঘোষণা করা যে কোনও বৈশ্বিক পরিবর্তনশীল বা ফাংশন সর্বজনীন এবং অন্য কোনও মডিউল দ্বারা এটি অ্যাক্সেস করতে পারে। আপনার ভেরিয়েবল এবং ফাংশনগুলি যেখানেই সম্ভব স্থিত বৈশিষ্ট্যের সাথে রক্ষা করার জন্য এটি ভাল প্রোগ্রামিং অনুশীলন।
পিএমজির উত্তরটি খুব দৃinc়প্রত্যয়ী। যদি আপনি জানতে চান যে স্থির ঘোষণা কীভাবে অবজেক্ট পর্যায়ে কাজ করে তবে নীচের এই তথ্যটি আপনার কাছে আকর্ষণীয় হতে পারে। আমি পিএমজি দ্বারা লিখিত একই প্রোগ্রামটি পুনরায় ব্যবহার করেছি এবং এটি একটি এসও (ভাগ করা বস্তু) ফাইলে সংকলন করেছি
নিম্নলিখিত বিষয়বস্তুগুলি .so ফাইলটিকে মানব পাঠযোগ্য কিছুতে ফেলে দেওয়ার পরে
0000000000000675 f1 : এফ 1 ফাংশনের ঠিকানা
000000000000068c f2 : f2 (স্ট্যাটিক) ফাংশনের ঠিকানা
ফাংশন ঠিকানার পার্থক্যটি নোট করুন, এর অর্থ কিছু। বিভিন্ন ঠিকানায় ঘোষিত কোনও ক্রিয়াকলাপের জন্য, এটি খুব ভালভাবে বোঝাতে পারে যে f2 খুব দূরে বা অবজেক্ট ফাইলের আলাদা বিভাগে বাস করে।
লিঙ্কাররা তাদের লিঙ্কে অ্যাক্সেস রয়েছে এমন চিহ্নগুলি বুঝতে পিএলটি (প্রক্রিয়া লিংকেজ টেবিল) এবং জিওটি (গ্লোবাল অফসেট টেবিল) নামক কিছু ব্যবহার করেন।
আপাতত ভাবেন যে জিওটি এবং পিএলটি যাদুকরিভাবে সমস্ত ঠিকানাগুলিকে বেঁধে রাখে এবং একটি গতিশীল বিভাগ লিঙ্কার দ্বারা দৃশ্যমান এই সমস্ত ফাংশনের তথ্য ধারণ করে।
.So ফাইলের গতিশীল অংশটি ডাম্প করার পরে আমরা একগুচ্ছ এন্ট্রি পাই তবে কেবল f1 এবং f2 ফাংশনে আগ্রহী।
ডায়নামিক বিভাগটি কেবল 0000000000000675 ঠিকানার মধ্যে f1 ফাংশনের জন্য এন্ট্রি ধারণ করে এবং f2 এর জন্য নয় !
সংখ্যা: মান আকারের ধরণ বাইন্ড ভিজ এনডিএক্স নাম
9: 0000000000000675 23 FUNC GLOBAL DEFAULT 11 f1
এবং এটাই !. এ থেকে এটি পরিষ্কার হয়ে গেছে যে লিঙ্কারটি Fo ফাংশনটি সন্ধান করতে ব্যর্থ হবে যেহেতু .so ফাইলটির গতিশীল অংশে নয়।
যখন কিছু ফাংশনে অ্যাক্সেস সীমাবদ্ধ করার প্রয়োজন হয়, তখন আমরা কোনও ফাংশন সংজ্ঞায়িত ও ঘোষণার সময় স্থিতিক কীওয়ার্ডটি ব্যবহার করব।
/* file ab.c */
static void function1(void)
{
puts("function1 called");
}
And store the following code in another file ab1.c
/* file ab1.c */
int main(void)
{
function1();
getchar();
return 0;
}
/* in this code, we'll get a "Undefined reference to function1".Because function 1 is declared static in file ab.c and can't be used in ab1.c */