সি মধ্যে স্থির ফাংশন


172

সি তে কোন ফাংশন স্থির করার বিন্দু কী?


7
@ নাইটক্র্যাকার: সি ++ তে "পদ্ধতি" জাতীয় কোনও জিনিস নেই। আমি মনে করি আপনি উদ্দেশ্য-সি নিয়ে বিভ্রান্ত হয়েছেন।
বো পারসন

1
নাহ, আমি পাইথনের সাথে বিভ্রান্ত ক্লাসের ভিতরে একটি ফাংশনকে পাইথন-এ একটি পদ্ধতি বলা হয়।
orlp

উত্তর:


212

একটি ফাংশন তৈরি করা 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;
}

8
অনুবাদ ইউনিট কি এখানে ব্যবহারের সঠিক পরিভাষা? আপত্তি ফাইল আরো সঠিক হবে না? আমি যা বুঝি তার থেকে, ল্যাটিকার থেকে একটি স্ট্যাটিক ফাংশন লুকানো থাকে এবং লিঙ্কার অনুবাদ ইউনিটে কাজ করে না।
স্টিভেন এখফ

2
আমার এটাও বলা উচিত ছিল, আমি এটিকে লিঙ্কার থেকে লুকিয়ে থাকা হিসাবে ভাবতে পছন্দ করি; এটি যেভাবে পরিষ্কার মনে হয়।
স্টিভেন এখফ

1
সুতরাং, অভ্যন্তরীণ ফাংশন (আমরা নিশ্চিতরূপে এটি এর সি ফাইলের বাইরে কল করব না), আমাদের এটি স্ট্যাটিক ফাংশন হিসাবে রাখা উচিত, তাই না? সুতরাং, আমরা নিশ্চিত করতে পারি যে এটি অন্য কোথাও কল করতে পারে না। ধন্যবাদ :)
htt

1
আপনি কিভাবে এটি সংকলন করবেন? আপনি কি ব্যবহার করেন #include <helper_file.c>? আমি মনে করি এটি তখন এটি একটি একক অনুবাদ ইউনিট করে
তুলবে

2
@ অ্যাটকোল্ড: আমি কোডটি যেভাবে লিখেছি তাতে আপনি কেবল 2 কমান্ড লাইনে 2 উত্স ফাইলগুলি অন্তর্ভুক্ত করেন gcc -std=c99 -pedantic -Wall -Wextra main.c helper_file.c। ফাংশনগুলির প্রোটোটাইপগুলি উভয় উত্স ফাইলগুলিতে উপস্থিত থাকে (শিরোনাম ফাইলগুলির প্রয়োজন নেই)। লিঙ্কার ফাংশনগুলি সমাধান করবে।

80

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

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

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


9
... যদি না ফাংশনের ঠিকানা নেওয়া হয়।
ক্যাফে

1
@ ক্যাফ ফাংশনের ঠিকানা বলতে কী বোঝায়? আমার কাছে, ফাংশন / ভেরিয়েবলের ঠিকানাগুলি বা সংকলনের সময় ঠিকানা নির্ধারিত হওয়ার ধারণাটি কিছুটা বিভ্রান্তিকর। আপনি দয়া করে বিস্তারিত বলতে পারেন?
সাeedদহুসাইন

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

5
@ ক্রিপটিককোডার: আমি বলতে চাইছি যে অভিব্যক্তিটি ফাংশনটির জন্য একটি পয়েন্টারকে মূল্যায়ন করে এবং সাথে সাথে ফাংশনটি কল করার পরিবর্তে এটির সাথে অন্য কিছু করে। যদি কোনও staticফাংশনটির পয়েন্টার বর্তমান অনুবাদ ইউনিট থেকে অব্যাহতি পায়, তবে সেই ফাংশনটি অন্য অনুবাদ ইউনিট থেকে সরাসরি কল করা যেতে পারে।
ক্যাফে

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

28

staticসি এর কীওয়ার্ডটি একটি সংকলিত ফাইলে (.c এর বিপরীতে ব্যবহার করা হয়) যাতে ফাংশনটি কেবলমাত্র সেই ফাইলটিতেই বিদ্যমান থাকে।

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


1
3 ডিউউব: "ক্রাফ্ট" শব্দটি ব্যবহার করা আপনার পক্ষে যত বেশি creditণ দেওয়া হয় তার চেয়ে বেশি সুনির্দিষ্ট। প্রশ্নের প্রসঙ্গে, "ক্রুফ্ট" এখানে সঠিক শব্দটি ব্যবহার করা উচিত।
এরিক অ্যারোনস্টি

@ থ্রিউডব্লুনস আমি সম্মতি দিচ্ছি যে এটি সরলীকৃত, তবে আমি মনে করি এটি নতুনদের জন্য বুঝতে এত সহজ করে তোলে।
ইনগো বার্ক

11

উপরের পোস্টগুলির দিকে তাকিয়ে আমি একটি বিশদটি উল্লেখ করতে চাই।

ধরুন আমাদের মূল ফাইলটি ("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

আমি ভুল হলে আমাকে সংশোধন করুন।


5

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


4

পিএমজির উত্তরটি খুব দৃ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 ফাইলটির গতিশীল অংশে নয়।


0

যখন কিছু ফাংশনে অ্যাক্সেস সীমাবদ্ধ করার প্রয়োজন হয়, তখন আমরা কোনও ফাংশন সংজ্ঞায়িত ও ঘোষণার সময় স্থিতিক কীওয়ার্ডটি ব্যবহার করব।

            /* 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 */

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