বহির্মুখী ইনলাইন কী করে?


93

আমি বুঝতে পারি যে inlineনিজে থেকেই এটি সংকলকটির জন্য পরামর্শ এবং তার বিবেচনার ভিত্তিতে এটি ফাংশনটি ইনলাইন করতে পারে বা নাও পারে এবং এটি লিঙ্কযোগ্য অবজেক্ট কোডও তৈরি করে।

আমি মনে করি static inlineএটি একই কাজ করে (মেলে বা নাও পারে) তবে লিংকযোগ্য অবজেক্ট কোড তৈরি করবে না যখন ইনলাইন করা হবে (যেহেতু অন্য কোনও মডিউল এর সাথে লিঙ্ক করতে পারে না)।

extern inlineছবিতে কোথায় ফিট?

অনুমান করছি যে (যেমন কারণ এটি ব্যবহার করে একটি ইনলাইন ফাংশন দ্বারা একটি প্রাক প্রসেসর ম্যাক্রো প্রতিস্থাপন করতে চান এবং প্রয়োজন এই ফাংশন inlined পরার যে __FILE__এবং __LINE__ম্যাক্রো যা আহ্বানকারী জন্য সমাধান করা উচিত কিন্তু এই নামক ফাংশন)। অর্থাত, ফাংশনটি অন্তর্ভুক্ত না হওয়ার ক্ষেত্রে আমি একটি সংকলক বা লিংক ত্রুটি দেখতে চাই want এটা কি করে extern inline? (আমি ধরে নিলাম, যদি এটি না হয় তবে ম্যাক্রো দিয়ে আটকে থাকা ছাড়া এই আচরণটি অর্জন করার কোনও উপায় নেই))

সি ++ এবং সি এর মধ্যে পার্থক্য রয়েছে কি?

বিভিন্ন সংকলক বিক্রেতাদের এবং সংস্করণগুলির মধ্যে পার্থক্য রয়েছে?

উত্তর:


129

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

জিএনইউ 89:

  • inline: ফাংশনটি ইনলাইন করা যেতে পারে (এটি কেবল একটি ইঙ্গিত যদিও)। একটি বহির্মুখী সংস্করণ সর্বদা নির্গত এবং বাহ্যিকভাবে দৃশ্যমান visible অতএব আপনি কেবল একটি সংকলন ইউনিটে এই জাতীয় ইনলাইন সংজ্ঞায়িত করতে পারেন এবং অন্য প্রত্যেককে এটির বাইরে থাকা লাইন হিসাবে দেখতে হবে (অথবা আপনি লিঙ্কের সময় সদৃশ প্রতীক পাবেন)।
  • extern inline আউট-অফ-লাইন সংস্করণ তৈরি করবে না, তবে একটিটিকে কল করতে পারে (যা আপনাকে তাই অন্য কোনও সংকলন ইউনিটে ব্যাখ্যা করতে হবে ine এখানে ইনলাইন অফার করা হয়েছে, যদি সংকলক তার পরিবর্তে কল করে।
  • static inlineবাহ্যিকভাবে দৃশ্যমান আউট-অফ-লাইন সংস্করণ তৈরি করবে না, যদিও এটি কোনও ফাইল স্থিতিশীল তৈরি করতে পারে। এক-সংজ্ঞা নিয়ম প্রযোজ্য নয়, যেহেতু কখনই নিঃসৃত বাহ্যিক প্রতীক বা একটিতে কল নেই।

C99 (বা GNU99):

  • inline: GNU89 "বাহ্যিক ইনলাইন" এর মতো; কোনও বাহ্যিকভাবে দৃশ্যমান ফাংশন নির্গত হয় না, তবে একটি কল হতে পারে এবং তাই উপস্থিত থাকতে হবে
  • extern inline: GNU89 "ইনলাইন" এর মতো: বাহ্যিকভাবে দৃশ্যমান কোড নির্গত হয়, সুতরাং বেশিরভাগ একটি অনুবাদ ইউনিট এটি ব্যবহার করতে পারে।
  • static inline: GNU89 "স্ট্যাটিক ইনলাইন" এর মতো। এটি gnu89 এবং c99 এর মধ্যে একমাত্র পোর্টেবল

সি ++:

কোনও ফাংশন যা কোথাও ইনলাইন হয় একই সংজ্ঞা সহ সর্বত্র ইনলাইন হওয়া আবশ্যক। সংকলক / লিঙ্কার প্রতীকটির একাধিক দৃষ্টান্ত বাছাই করবে। static inlineবা এর কোনও সংজ্ঞা নেই extern inline, যদিও অনেক সংকলক তাদের এ আছে (সাধারণত gnu89 মডেল অনুসরণ করে)।


4
ক্লাসিক ক্লাসিক সি তে, 'ইনলাইন' কোনও মূলশব্দ ছিল না; এটি একটি চলক নাম হিসাবে ব্যবহারের জন্য উপলব্ধ ছিল। এটি C89 এবং প্রাক-মান (K&R) সি এর জন্য প্রযোজ্য হবে
জোনাথন লেফলার

আপনি ঠিক বলেছেন, মনে হচ্ছে। স্থির। আমি ভেবেছিলাম এটি
সি -৮৮ তে মূলশব্দ

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

সি 99 "এক্সটার্নাল ইনলাইন" এবং কোনও স্পেসিফায়ারগুলির মধ্যে কোনও পার্থক্য নেই?
জো সো

শব্দার্থিকভাবে না; একটি অন-ইনলাইন ফাংশনের মতোই, একটি extern inlineসংজ্ঞা নিয়মের সাপেক্ষে এবং এটিই সংজ্ঞা। তবে যদি বাস্তবায়িত-সংজ্ঞায়িত অপ্টিমাইজেশান হিউরিস্টিকস inlineকীওয়ার্ডটি একটি পরামর্শ হিসাবে ব্যবহার করার পরামর্শটি অনুসরণ করে যা "ফাংশনটিতে কলগুলি যত দ্রুত সম্ভব হয়" (আইএসও 9899: 1999 §6.7.4 (5), extern inlineগণনা
পিতজক

31

আমি বিশ্বাস করি আপনি এই বক্তব্যের ভিত্তিতে __FILE__ এবং __LINE__ ভুল বুঝেছেন:

কারণ এটি __FILE__ এবং __LINE__ ম্যাক্রোগুলি ব্যবহার করে যা কলারের জন্য সমাধান করা উচিত তবে এটি বলা ফাংশন নয়

সংকলনের বেশ কয়েকটি ধাপ রয়েছে এবং প্রাকপ্রসেসিং প্রথম। এই পর্যায়ে __FILE__ এবং __LINE__ প্রতিস্থাপন করা হয়। সুতরাং কম্পাইলার ইনলাইনের জন্য ফাংশনটি বিবেচনা করতে পারে সেগুলি ইতিমধ্যে প্রতিস্থাপন করা হয়েছে।


14

মনে হচ্ছে আপনি এই জাতীয় কিছু লেখার চেষ্টা করছেন:

inline void printLocation()
{
  cout <<"You're at " __FILE__ ", line number" __LINE__;
}

{
...
  printLocation();
...
  printLocation();
...
  printLocation();

এবং আশা করি আপনি প্রতিবার মুদ্রিত বিভিন্ন মান পাবেন। ডন যেমন বলেছে, আপনি তা করবেন না, কারণ __FILE__ এবং __LINE__ প্রিপ্রসেসর দ্বারা প্রয়োগ করা হয়েছে, তবে ইনलाइनটি সংকলক দ্বারা প্রয়োগ করা হয়েছে। সুতরাং আপনি যেখান থেকে মুদ্রণ অবস্থানকে কল করবেন না কেন আপনি একই ফলাফল পাবেন।

শুধুমাত্র আপনি কাজ করার জন্য এই পেতে পারেন printLocation একটি ম্যাক্রো করা হয়। (হ্যা আমি জানি...)

#define PRINT_LOCATION  {cout <<"You're at " __FILE__ ", line number" __LINE__}

...
  PRINT_LOCATION;
...
  PRINT_LOCATION;
...

18
একটি সাধারণ কৌতুক একটি ম্যাক্রো PRINT_LOCATION একটি ফাংশন printLocation ডাকতে জন্য, ক্ষণস্থায়ী হয় ফাইল এবং লাইন পরামিতি হিসেবে। ফাংশন বডিটি যখন তুচ্ছ-তুচ্ছ হয় তখন এটি আরও ভাল ডিবাগার / সম্পাদক / ইত্যাদি আচরণের ফলে তৈরি হতে পারে।
স্টিভ জেসোপ

@ রডি আমার সমাধান দেখুন - আপনার এক্সটেনশন তবে আরও ব্যাপক এবং এক্সটেনসিবল।
উত্সাহী

@ স্টেভ জেসপ কিছু নীচের সমাধানে আমি তালিকাভুক্ত করেছি?
উত্সাহী

3

ইনলাইন, স্ট্যাটিক ইনলাইন এবং বহির্মুখী ইনলাইন সহ পরিস্থিতি জটিল, কমপক্ষে নয় কারণ জিসিসি এবং সি 99 তাদের আচরণের জন্য কিছুটা পৃথক অর্থ সংজ্ঞায়িত করে (এবং সম্ভবত সি ++ হিসাবেও)। আপনি কি তারা সি না সম্পর্কে কিছু দরকারী এবং বিস্তারিত তথ্য জানতে পারেন এখানে


2

ইনলাইন ফাংশনগুলির চেয়ে ম্যাক্রোগুলি এখানে আপনার পছন্দ। একটি বিরল উপলক্ষ্য যেখানে ম্যাক্রোগুলি ইনলাইন ফাংশনগুলিতে কর্তৃত্ব করে। নিম্নলিখিতটি ব্যবহার করে দেখুন: আমি এই "ম্যাক্রো ম্যাজিক" কোডটি লিখেছি এবং এটি কাজ করা উচিত! Gcc / g ++ উবুন্টু 10.04 এ পরীক্ষিত

//(c) 2012 enthusiasticgeek (LOGGING example for StackOverflow)

#ifdef __cplusplus

#include <cstdio>
#include <cstring>

#else

#include <stdio.h>
#include <string.h>

#endif

//=========== MACRO MAGIC BEGINS ============

//Trim full file path
#define __SFILE__ (strrchr(__FILE__,'/') ? strrchr(__FILE__,'/')+1 : __FILE__ )

#define STRINGIFY_N(x) #x
#define TOSTRING_N(x) STRINGIFY_N(x)
#define _LINE (TOSTRING_N(__LINE__))

#define LOG(x, s...) printf("(%s:%s:%s)"  x "\n" , __SFILE__, __func__, _LINE, ## s);

//=========== MACRO MAGIC ENDS ============

int main (int argc, char** argv) {

  LOG("Greetings StackOverflow! - from enthusiasticgeek\n");

  return 0;
}

একাধিক ফাইলের জন্য প্রতিটি সি / সিসি / সিএক্সএক্স / সিপিপি ফাইলগুলির মধ্যে একটি পৃথক শিরোনামের ফাইলগুলিতে এই ম্যাক্রোগুলি সংজ্ঞায়িত করে। যেখানেই সম্ভব ম্যাক্রোগুলির চেয়ে দয়া করে ইনলাইন ফাংশন বা কনস্ট আইডেন্টিফায়ার (কেস যেমন দাবি করা হয়) পছন্দ করুন।


2

"এটি কী করে?" এর উত্তর না দিয়ে আমি উত্তর দিচ্ছি "আমি কী চাই তা কীভাবে করব?" এখানে 5 ধরণের ইনলাইনিং রয়েছে, সমস্ত জিএনইউ সি 89, স্ট্যান্ডার্ড সি 99 এবং সি ++ এ উপলব্ধ:

সর্বদা ইনলাইন, যদি না ঠিকানা না নেওয়া হয়

যোগ __attribute__((always_inline))কোনো ঘোষণা, তারপর তার ঠিকানা সম্ভাবনা নেওয়া হচ্ছে হ্যান্ডেল করতে ক্ষেত্রেই নিচের ব্যবহার করুন।

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

ইনলাইন করুন এবং একটি দুর্বল প্রতীক নির্গমন করুন (যেমন সি ++, ওরফে "কেবল এটি কাজ করুন")

__attribute__((weak))
void foo(void);
inline void foo(void) { ... }

নোট করুন যে এটি একই কোডের একগুচ্ছ চারপাশে পড়ে আছে এবং লিঙ্কারটি নির্বিচারে একটি বাছাই করে।

ইনলাইন, তবে কখনই কোনও চিহ্ন প্রকাশ করবেন না (বাহ্যিক রেফারেন্সগুলি রেখে)

__attribute__((gnu_inline))
extern inline void foo(void) { ... }

সর্বদা নির্গত (এক টিউ এর জন্য, পূর্ববর্তী সমাধানের জন্য)

ইঙ্গিতযুক্ত সংস্করণটি সি ++ তে একটি দুর্বল প্রতীক প্রকাশ করে তবে সি এর উভয় উপভাষায় একটি শক্তিশালী প্রতীক:

void foo(void);
inline void foo(void) { ... }

অথবা আপনি ইঙ্গিত ছাড়াই এটি করতে পারেন, যা উভয় ভাষায়ই একটি শক্তিশালী প্রতীক প্রকাশ করে:

void foo(void) { ... }

সাধারণত আপনি যখন জানেন যে আপনি সংজ্ঞা প্রদান করছেন তখন আপনার টিউ কী ভাষা হয় এবং সম্ভবত খুব বেশি ইনলাইনিংয়ের প্রয়োজন হয় না।

প্রতিটি টিইউতে ইনলাইন এবং নির্গত হয়

static inline void foo(void) { ... }

এই ব্যতীত অন্যগুলির জন্য static, আপনি void foo(void)উপরে একটি ঘোষণা যুক্ত করতে পারেন । এটি পরিষ্কার শিরোনাম লেখার "সেরা অনুশীলন", তারপরে #includeইনলাইন সংজ্ঞা সহ একটি পৃথক ফাইল তৈরি করতে সহায়তা করে। তারপরে, যদি সি-স্টাইলের ইনলাইনগুলি ব্যবহার করা হয়, তবে #defineকোনও ম্যাক্রো আলাদাভাবে আলাদা আলাদা আলাদা আলাদা সংজ্ঞা সরবরাহ করতে একটি উত্সর্গীকৃত টিইউতে আলাদা করে দেয়।

extern "C"হেডারটি সি এবং সি ++ উভয় থেকেই ব্যবহার করা যেতে পারে তা ভুলে যাবেন না !


অনুপস্থিত: এমএসভিসির কী হবে? এটিতে কিছু সি 89 ডায়ালেক্ট এক্সটেনশন রয়েছে তবে আমি কখনই এমএসভিসি ব্যবহার করি না এবং এর nmসমতুল্য কীভাবে চালাতে হয় তা আমি জানি না ।
o11c

কেস # 4 void foo(void); inline void foo(void) { ... }শিরোনামটি "সর্বদা নির্গত হয় (এক টিউর জন্য, পূর্ববর্তীটি সমাধান করার জন্য)"। অন্যান্য 4 টি "ইনলাইন ...." দিয়ে শুরু হয়। ক্ষেত্রে 4: এটিও ইনলাইন করে?
chux - মনিকা 17

@ chux-ReinstateMonica ইনলাইনিং পারফরম্যান্সের চেয়ে প্রতীক আচরণ সম্পর্কে বেশি। কম্পাইলার হয় অনুমতি পারফরম্যান্সের জন্য ইনলাইন করা হবে কিনা তা শব্দ উপস্থিত না থাকলে বা না (হস্তক্ষেপ বিধি সাপেক্ষে)। কেস # 4 এর সমালোচনামূলক অংশটি এটি কেস # 3 এর অমীমাংসিত চিহ্নগুলির সাথে কীভাবে সম্পর্কিত; প্রায়ই সেখানে নয় (ড) যাহাই হউক না কেন যে TU কোনো কলারের।
o11c

আমার মন্তব্য কেন এই উত্তরটি 1,2,3,5 ক্ষেত্রে তাদের শিরোনামের বর্ণনায় ইনলাইন করেছে, সে সম্পর্কে আরও ছিল , কিন্তু 4 তা করেনি। আপনি কি পরামর্শ দিচ্ছেন যে ক্ষেত্রে 4 কোডটি কখনই ইনলাইনড, সর্বদা ইনলাইনড, কখনও কখনও ইনলাইনড হয় না? কেস # 4 ইনলাইন সম্ভাবনা অন্যান্য 4 এর চেয়ে আলাদা?
chux - মনিকা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.