সি-তে কীভাবে সঠিকভাবে বহিরাগত কীওয়ার্ডটি ব্যবহার করতে হয়


235

আমার প্রশ্নটি কখন externসি এর কীওয়ার্ডের সাথে কোনও ফাংশনটি উল্লেখ করা উচিত should

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

আমি কীভাবে externভুলভাবে কাজ করে সে সম্পর্কে ভাবতে পারি এবং যদি তাই হয় তবে আমাকে সংশোধন করুন।

সম্পাদনা:extern কোনও শিরোনাম ফাইলে কীওয়ার্ড ছাড়াই যখন এটি ডিফল্ট ঘোষণা হয় তখন আপনার কিছু হওয়া উচিত ?


কাজকর্মের জন্য সম্পর্কিত: stackoverflow.com/questions/856636/... varables জন্য: stackoverflow.com/questions/1433204
সিরো Santilli郝海东冠状病六四事件法轮功

উত্তর:


290

externলিঙ্কেজ " " পরিবর্তন করে। মূলশব্দটির সাথে, ফাংশন / ভেরিয়েবলটি অন্য কোথাও উপলব্ধ বলে ধরে নেওয়া হয় এবং সমাধানটি লিংকের কাছে পিছিয়ে যায়।

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


1
তবে গিটে একই বহিরাগত জিনিসটি কেন রয়েছে: একটি খুব জনপ্রিয় এবং আধুনিক সফ্টওয়্যার এটি পরীক্ষা করে দেখুন: github.com/git/git/blob/master/strbuf.h
RSSJethani

কে অ্যান্ড আর নোট করবেন না যে ফাংশনটিকে "বাহ্যিক" হিসাবে ঘোষণা করা ডিফল্ট, তবে এই উত্তরটি আমার বিভ্রান্তির সমাধান করে!
অ্যাক্টিগার্যান্ট

@rsjethani আমি মনে করি এটি নথিটি আরও কঠোর এবং ফর্ম্যাট করা।
তীব্র

হতে পারে একটি বোবা প্রশ্ন, কিন্তু এটি কীভাবে ফরওয়ার্ড ডিক্লেয়ারের সাথে তুলনা করে?
weberc2

196

বাহ্যিক সংকলককে বলে যে এই ডেটা কোথাও সংজ্ঞায়িত হয়েছে এবং লিঙ্কারের সাথে সংযুক্ত থাকবে।

এখানে প্রতিক্রিয়াগুলির সাহায্যে এবং এখানে কয়েকজন বন্ধুর সাথে কথা বলা বাহ্যিক ব্যবহারের ব্যবহারিক উদাহরণ ।

উদাহরণ 1 - একটি দোষ দেখাতে:

File stdio.h:

int errno;
/* other stuff...*/

myCFile1.c:
#include <stdio.h>

Code...

myCFile2.c:
#include <stdio.h>

Code...

MyCFile1.o এবং myCFile2.o লিঙ্ক হয়, গ ফাইলগুলির প্রতিটির আলাদা অনুলিপি আছে errno । এই সমস্যা হিসাবে একই errno সব লিঙ্ক ফাইলে পাওয়া যাবে অনুমিত হয়।

উদাহরণ 2 - ফিক্স।

File stdio.h:

extern int errno;
/* other stuff...*/

File stdio.c

int errno;

myCFile1.c:
#include <stdio.h>

Code...

myCFile2.c:
#include <stdio.h>

Code...

এখন যদি উভয়ই MyCFile1.o এবং MyCFile2.o লিঙ্কারের মাধ্যমে সংযুক্ত থাকে তবে তারা উভয়ই একই ত্রুটির দিকে নির্দেশ করবে । সুতরাং, বহির্মুখী সঙ্গে বাস্তবায়ন সমাধান ।


70
সমস্যাটি নয় যে মাইসিফাইল 1 এবং মাইসিফিল 2 মডিউলগুলির মধ্যে ইরনের একটি পৃথক অনুলিপি রয়েছে, তারা উভয়ই "এর্নো" নামক একটি প্রতীক প্রকাশ করছে। লিঙ্কার এটি দেখলে, কোন "ভুল" বেছে নেবে তা এটি জানে না, সুতরাং এটি একটি ত্রুটির বার্তা দিয়ে জামিন দেয়।
cwick

2
"লিঙ্কারের সাথে যুক্ত" এর অর্থ কী? প্রত্যেকে এই শব্দটি ব্যবহার করেছেন, আমি কোনও সংজ্ঞা পাই না :(
মার্সেল ফ্যালিয়ের

7
@ মার্সেলফ্যালিয়ের উইকি ~ সংকলক প্রতিটি উত্স ফাইলটি নিজস্ব সংকলন করে এবং প্রতিটি উত্স ফাইলের জন্য একটি বস্তু ফাইল তৈরি করে। লিঙ্কার এই অবজেক্ট ফাইলগুলিকে 1 এক্সিকিউটেবলের সাথে লিঙ্ক করে।
বিটারব্লু

1
@cwick জিসিসি একটি ত্রুটি দান করা নেই বা ব্যবহার করার পরেও সতর্কীকরণ -Wallএবং -pedantic। কেন? এবং কিভাবে ?
বি-আক

6
একজন অন্তর্ভুক্তকারীরা কি এই সঠিক জিনিস থেকে রক্ষা করে না?
obskyr

32

ইতিমধ্যে এটি উল্লেখ করা হয়েছে যে externকীওয়ার্ডটি ফাংশনগুলির জন্য অপ্রয়োজনীয়।

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


@ আইবি "ফাংশনগুলির জন্য রিডানড্যান্ট", ব্লুব্রোথরের উত্তরে আমার মন্তব্য দেখুন।
rsjethani

আপনি যদি শিরোলেখ ফাইলটিতে কোনও ফাংশন প্রকাশ করতে না চান? এক সি ফাইলে ভেরিয়েবলটি ঘোষণা করা এবং অন্যটিতে বাহ্যিক মাধ্যমে এটি অ্যাক্সেস করা ভাল না; লিঙ্কারটিকে সমস্যার সমাধান করতে দিন এবং বাকী শিরোনামটি আড়াল করুন।
ste3e

16

বহু বছর পরে, আমি এই প্রশ্নটি আবিষ্কার করি। প্রতিটি উত্তর এবং মন্তব্য পড়ার পরে, আমি ভেবেছিলাম যে আমি কয়েকটি বিশদ স্পষ্ট করতে পারব ... গুগল অনুসন্ধানের মাধ্যমে যারা এখানে আসে তাদের পক্ষে এটি কার্যকর হতে পারে।

প্রশ্নটি বিশেষত "বহিরাগত" ফাংশনগুলি ব্যবহার সম্পর্কে, সুতরাং আমি গ্লোবাল ভেরিয়েবলগুলির সাথে "বহিরাগত" ব্যবহার উপেক্ষা করব।

আসুন 3 ফাংশন প্রোটোটাইপগুলি সংজ্ঞায়িত করি:

//--------------------------------------
//Filename: "my_project.H"
extern int function_1(void);
static int function_2(void);
       int function_3(void);

নীচের হিসাবে প্রধান উত্স কোড দ্বারা শিরোনাম ফাইলটি ব্যবহার করা যেতে পারে:

//--------------------------------------
//Filename: "my_project.C"
#include "my_project.H"

void main(void){
    int v1 = function_1();
    int v2 = function_2();
    int v3 = function_3();
}

int function_2(void) return 1234;

সংকলন এবং লিঙ্ক করার জন্য, আমাদের একই উত্স কোড ফাইলটিতে "ফাংশন 3" সংজ্ঞায়িত করতে হবে যেখানে আমরা সেই ফাংশনটি ডাকি। অন্য দুটি ফাংশন বিভিন্ন উত্স কোড " .C" এ সংজ্ঞায়িত করা যেতে পারে বা এগুলি যে কোনও বাইনারি ফাইল ( .OBJ, * .LIB, * .DLL) এ থাকতে পারে, যার জন্য আমাদের কাছে সোর্স কোড নাও থাকতে পারে।

আসুন "মাই_প্রজেক্ট.এইচ" আবার একটি পৃথক "*। সি" ফাইলে পার্থক্যটি আরও ভালভাবে বোঝার জন্য শিরোনামটি অন্তর্ভুক্ত করা যাক। একই প্রকল্পে, আমরা নিম্নলিখিত ফাইলটি যুক্ত করব:

//--------------------------------------
//Filename: "my_big_project_splitted.C"
#include "my_project.H"

void old_main_test(void){
    int v1 = function_1();
    int v2 = function_2();
    int v3 = function_3();
}

int function_2(void) return 5678;

int function_1(void) return 12;
int function_3(void) return 34;

গুরুত্বপূর্ণ বৈশিষ্ট্যগুলি লক্ষ করুন:

  • যখন একটি ফাংশন একটি শিরোনাম ফাইলটিতে "স্থিতিশীল" হিসাবে সংজ্ঞায়িত করা হয়, সংকলক / লিংককারীকে অবশ্যই প্রতিটি মডিউলে সেই নামটি সহ কোনও ফাংশনের একটি উদাহরণ সন্ধান করতে হবে যা ফাইল অন্তর্ভুক্ত করে uses

  • সি লাইব্রেরির অংশ এমন একটি ফাংশন কেবলমাত্র সেই মডিউলে "স্ট্যাটিক" দিয়ে একটি প্রোটোটাইপ পুনরায় সংজ্ঞায়িত করে কেবল একটি মডিউলে প্রতিস্থাপন করা যেতে পারে। উদাহরণস্বরূপ, মেমরি ফাঁস সনাক্তকরণ বৈশিষ্ট্য যুক্ত করতে কোনও কলকে "malloc" এবং "ফ্রি" প্রতিস্থাপন করুন।

  • নির্দিষ্টকরণকারী "বাহ্যিক" কার্যকারণের জন্য সত্যই প্রয়োজন হয় না। "স্থিতিশীল" খুঁজে পাওয়া যায় না, একটি ফাংশন সর্বদা "বাহ্যিক" হিসাবে ধরে নেওয়া হয়।

  • তবে ভেরিয়েবলের জন্য "বাহ্যিক" ডিফল্ট নয়। সাধারণত, যে কোনও শিরোনাম ফাইল যা ভেরিয়েবলকে অনেকগুলি মডিউল জুড়ে দৃশ্যমান হতে সংজ্ঞায়িত করে তার "বাহ্যিক" ব্যবহার করা দরকার। একমাত্র ব্যতিক্রম হবে যদি একটি এবং কেবলমাত্র একটি মডিউল থেকে কোনও শিরোনাম ফাইল অন্তর্ভুক্ত করার নিশ্চয়তা দেওয়া হয়।

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


সুতরাং কেন স্থির ফাংশনটির বহিরাগতগুলির তুলনায় একটি সংজ্ঞা প্রয়োজন? (আমি জানি এটি 2 বছর দেরি হয়ে গেছে, তবে এটি বোঝার জন্য আসলেই সহায়ক)
সাবলক 69

2
সংজ্ঞাটি প্রয়োজনীয় যদি আপনি 100 লাইনে ফাংশনটি কল করেন এবং 500 লাইনে এটি ইনস্ট্যান্ট করেন Line লাইন 100 অনির্ধারিত প্রোটোটাইপ ঘোষণা করবে। সুতরাং, আপনি উপরে প্রোটোটাইপ যোগ করুন।
খ্রিস্টান জিঙ্গরাস

15

সিতে, 'এক্সটারন' ফাংশন প্রোটোটাইপগুলির জন্য অন্তর্নিহিত হয়, যেমন একটি প্রোটোটাইপ কোনও ফাংশনটি ঘোষণা করে যা অন্য কোথাও সংজ্ঞায়িত করা হয়। অন্য কথায়, একটি ফাংশন প্রোটোটাইপের ডিফল্টরূপে বাহ্যিক সংযোগ থাকে; 'এক্সটার্ন' ব্যবহার করা ভাল, তবে অতিরিক্ত কাজ নয়।

(যদি স্ট্যাটিক লিঙ্কেজ প্রয়োজন হয় তবে ফাংশনটি অবশ্যই তার প্রোটোটাইপ এবং ফাংশন শিরোনামে 'স্ট্যাটিক' হিসাবে ঘোষণা করতে হবে এবং এগুলি উভয়ই একই .c ফাইলে হওয়া উচিত)।


8

একটি খুব ভাল নিবন্ধ যা আমি externকীওয়ার্ডটি নিয়ে এসেছি , উদাহরণগুলি সহ: http://www.geeksforgeeks.org/ বোঝার জন্য- এক্সটার্ন- কীওয়ার্ড- in-c/

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


3
আমি এখানে আসার আগে আমি geeforforgeeks.org নিবন্ধটি পড়েছি তবে এটি বেশ খারাপ লেখা আছে found ব্যাকরণগত এবং বাক্য গঠন ত্রুটিগুলি ছাড়াও, একই পয়েন্টটি কয়েকবার তৈরি করতে এবং পরে সমালোচনামূলক তথ্যের উপর ঝাঁপিয়ে পড়ে প্রচুর শব্দ ব্যবহার করে। উদাহরণস্বরূপ, উদাহরণ 4-এ, হঠাৎ 'somefile.h' অন্তর্ভুক্ত করা হয়েছে, তবে এটি ব্যতীত অন্য কিছুই বলা হয় না: "ধরুন যে somefile.h এর বর্ণের সংজ্ঞা রয়েছে"। ঠিক আছে, আমরা যে তথ্যটি "অনুমান" করছি তা হ'ল যা আমি সন্ধান করছি be দুর্ভাগ্যক্রমে, এই পৃষ্ঠায় উত্তরগুলি আরও ভাল কিছু নয়।
এলিস ভ্যান লুইজ

6

যদি আপনার প্রোগ্রামের প্রতিটি ফাইল প্রথমে কোনও অবজেক্ট ফাইলে সংকলিত হয়, তবে অবজেক্ট ফাইলগুলি একসাথে লিঙ্কযুক্ত, আপনার প্রয়োজন extern। এটি কম্পাইলারকে বলে "এই ফাংশনটি বিদ্যমান, তবে এর কোডটি অন্য কোথাও রয়েছে pan আতঙ্কিত হবেন না।"


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

আমার মনে হচ্ছে ইদানীং জিনিসগুলি ভুলভাবে পড়ে এই সমস্যাটি হয়েছে। এর জন্যে দুঃখিত. যখন আমি সি-তে নতুন ছিলাম, আমি কেবলমাত্র একটি ফাইলের ফাংশনগুলি সরাসরি অন্য ফাইলে অন্তর্ভুক্ত করার জন্য "file.c" অন্তর্ভুক্ত করব। তারপরে আমি কীভাবে 'এক্সটার্ন' ব্যবহার করব তা ভেবেছিলাম। আমি ভেবেছিলাম সে আমারও একই ভুল করছিল।
ক্রিস লুটজ

4

শিরোনাম ফাইলগুলিতে ফাংশন এবং ভেরিয়েবলের সমস্ত ঘোষণা হওয়া উচিত extern

এই নিয়মের ব্যতিক্রমগুলি শিরোনাম এবং ভেরিয়েবলগুলিতে সংজ্ঞায়িত ইনলাইন ফাংশন যা - যদিও শিরোনামে সংজ্ঞায়িত হয় - অনুবাদ ইউনিটে স্থানীয় হতে হবে (উত্স ফাইলটিতে শিরোনামটি অন্তর্ভুক্ত হয়ে যায়): এগুলি হওয়া উচিত static

উত্স ফাইলগুলিতে, externফাইলে সংজ্ঞায়িত ফাংশন এবং ভেরিয়েবলগুলির জন্য ব্যবহার করা উচিত নয়। স্থানীয় সংজ্ঞাগুলির সাথে কেবল উপসর্গ করুন staticএবং ভাগ করা সংজ্ঞাগুলির জন্য কিছুই করবেন না - এগুলি ডিফল্টরূপে বাহ্যিক প্রতীক হবে।

externউত্স ফাইলটিতে মোটেও ব্যবহার করার একমাত্র কারণ হ'ল ফাংশন এবং ভেরিয়েবলগুলি ঘোষণা করা যা অন্য উত্স ফাইলগুলিতে সংজ্ঞায়িত হয় এবং যার জন্য কোনও শিরোনাম ফাইল সরবরাহ করা হয় না।


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


"হেডার ফাইলগুলিতে ফাংশন এবং ভেরিয়েবলের সমস্ত ঘোষণা বহিরাগত হওয়া উচিত কেন আপনি কোনও কারণ দিতে পারেন?" এটি অন্যান্য প্রতিক্রিয়া থেকে আমার দিকে তাকান যে তারা ডিফল্টরূপে বাহ্যিক are
লিলিক

@ লেন: externফাংশন ঘোষণার জন্য is চ্ছিক , তবে আমি ভেরিয়েবল এবং ফাংশনগুলি একইভাবে আচরণ করতে চাই - কমপক্ষে এটিই আমি সবচেয়ে যুক্তিসঙ্গত জিনিসটি সামনে আসতে পেরেছিলাম, কেননা আমি কেন এটি শুরু করেছিলাম তা ঠিক মনে নেই;)
ক্রিস্টোফ

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

3

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

বেশিরভাগ সময়, আপনার ফাংশনগুলি নিম্নলিখিতগুলির মধ্যে একটি হয়ে উঠবে (আরও ভাল একটি অনুশীলনের মতো):

  • স্ট্যাটিক (স্বাভাবিক ফাংশন যা .c ফাইলের বাইরে দৃশ্যমান নয়)
  • স্ট্যাটিক ইনলাইন (.c বা .h ফাইল থেকে ইনলাইনগুলি)
  • বাহ্যিক (পরবর্তী ধরণের শিরোনামে ঘোষণা (নীচে দেখুন))
  • [কোনও কীওয়ার্ড নেই] (সাধারণ ফাংশনগুলি বহিরাগত ঘোষণা ব্যবহার করে অ্যাক্সেস করা বোঝায়)

যদি এটি পূর্বনির্ধারিত হয় তবে প্রোটোটাইপটি ঘোষণার সময় আপনি কেন বাহ্যিক করবেন?
লিলিক

@ লেন: কিছুটা পক্ষপাতদুষ্ট হতে পারে তবে আমি যে প্রতিটি বুদ্ধিমান প্রকল্পে কাজ করেছি সেগুলি নিম্নলিখিত কনভেনশন ব্যবহার করে: শিরোনামগুলিতে, কেবলমাত্র বাহ্যিক কার্যগুলির জন্য প্রোটোটাইপগুলি ঘোষণা করুন (তাই বাহ্যিক)। .C ফাইলগুলিতে সাদামাটা প্রোটোটাইপগুলি নির্দিষ্ট অর্ডারিংয়ের প্রয়োজনীয়তা বাড়াতে ব্যবহার করা যেতে পারে, তবে সেগুলি শিরোনামে রাখা উচিত নয়।
এডুয়ার্ড -

1

যখন আপনার কোনও ফাংশনটি অন্য কোনও dll বা lib এ সংজ্ঞায়িত করা হয়, যাতে সংকলক এটি খুঁজে পেতে লিংকটিকে পিছিয়ে দেয়। সাধারণ কেসটি হ'ল যখন আপনি ওএস এপিআই থেকে ফাংশনগুলি কল করছেন।

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