এই অপ্রচলিত সি কোড কোনও মেইন () ছাড়াই চালানোর দাবি করে তবে এটি কী করে?


84

এটি কি পরোক্ষভাবে কল করে main? কিভাবে?


146
ম্যাক্রো সংজ্ঞায়িত প্রসারিতকে "প্রধান" বলতে শুরু করে। এটা শুধু একটি কৌশল। বিশেষ কিছুই নেই.
rghome

10
আপনার টুলচেইনের একটি ফাইলের মধ্যে প্রাক-প্রসেসড কোডটি রেখে দেওয়ার একটি বিকল্প থাকা উচিত - সংকলিত প্রকৃত ফাইল - যেখানে আপনি এটি দেখতে পাবেন, প্রকৃতপক্ষে একটি প্রধান () রয়েছে

@ rghome উত্তর হিসাবে পোস্ট করবেন না কেন? এবং এটি স্পষ্টভাবে আকর্ষণীয়, upvotes সংখ্যা দেওয়া।
Matsemann

4
@ ম্যাটসমান ওয়া! আমি আপ-ভোট লক্ষ্য করিনি। আমি এটিকে কোনও উত্তরে পরিবর্তন করতে পারতাম, এবং মন্তব্য-আপ-আপ যদি ভোট-আপ উত্তর দেয় তবে এটি আমার সেরা স্কোর হবে, তবে ইতিমধ্যে এখানে একটি বিস্তারিত প্রতিক্রিয়া রয়েছে। আমি মনে করি আমার মন্তব্যের মূল বক্তব্যটি এটি সত্যই আকর্ষণীয় নয় এবং তাই এটি উত্তরটির পক্ষে ভোট দিতে না চাওয়া লোকদের বিকল্প হিসাবে কাজ করে। যদিও এটি দেখানোর জন্য ধন্যবাদ।
rghome

বন্ধুরা, এন্ট্রি পয়েন্ট সেট করার জন্য এটি অপারেটিং সিস্টেমের সরঞ্জাম হিসাবে লিঙ্কারের উপর নির্ভর করে, না ভাষাটি। আপনি আমাদের নিজস্ব এন্ট্রি পয়েন্ট এমনকি সেট করতে পারেন, এবং আপনি একটি লাইব্রেরি তৈরি করতে পারেন যা কার্যকরও হয়! unix.stackexchange.com/a/223415/37799
Ho1

উত্তর:


194

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

আপনার ক্ষেত্রে, mainপ্রিপ্রোসেসর সংজ্ঞা দ্বারা গোপন করা হয়। আরও begin()প্রসারিত হবে decode(a,n,i,m,a,t,e)যা প্রসারিত হবে main


decode(s,t,u,m,p,e,d)7 পরামিতি সহ একটি প্যারামিটারাইজড ম্যাক্রো। এই ম্যাক্রোর প্রতিস্থাপনের তালিকাটি m##s##u##tm, s, uএবং প্রতিস্থাপন তালিকায় ব্যবহৃত t4 , 1 , 3 য় আর 2 তম প্যারামিটার।

বাকীগুলি কোনও কাজে আসে না ( কেবল অবলীলায় )। আর্গুমেন্টটি decode" , এন , আই , এম , এ, টি, ই" হয় তাই শনাক্তকারী m, s, uএবং tযুক্তি m, a, iএবং nযথাক্রমে প্রতিস্থাপন করা হয়।


11
@ গ্রিজেশচৌহান সমস্ত সি সংকলক ম্যাক্রোগুলি প্রক্রিয়া করে, সি 89 এর পরে এটি সমস্ত সি স্ট্যান্ডার্ডের দ্বারা প্রয়োজনীয়।
jdarthenay

17
এটা স্পষ্টতই ভুল। লিনাক্সে আমি ব্যবহার করতে পারি _start()। বা আরও নিম্ন-স্তরের আমি আমার প্রোগ্রামের শুরুটি ঠিক ঠিক ঠিকানা ঠিকঠাক করে চেষ্টা করতে পারি যে বুটের পরে আইপি সেট করা আছে। main()সি স্ট্যান্ডার্ড লাইব্রেরি হয় । সি নিজেই এ নিয়ে কোনও বিধিনিষেধ আরোপ করে না।
ljrk

4
@ হ্যাকস স্ট্যান্ডার্ড লাইব্রেরি একটি প্রবেশ পয়েন্ট নির্ধারণ করে। ভাষা নিজেই যত্ন করে না
ljrk

4
আপনি কি দয়া করে ব্যাখ্যা করতে পারেন কিভাবে decode(a,n,i,m,a,t,e)হয়ে m##a##i##n? এটি চরিত্রগুলি প্রতিস্থাপন করে? আপনি কি decodeফাংশনের ডকুমেন্টেশনের লিঙ্ক সরবরাহ করতে পারেন ? ধন্যবাদ
আওয়ামী লীগের

4
@ এএল ফার্স্ট এর beginপরিবর্তে সংজ্ঞায়িত করা হয়েছে decode(a,n,i,m,a,t,e)যা আগে সংজ্ঞায়িত করা হয়েছে। এই ফাংশনটি আর্গুমেন্ট গ্রহণ s,t,u,m,p,e,dকরে এবং এই ফর্মটিতে তাদের সংমিশ্রিত করে m##s##u##t( ##যার অর্থ কনকানেটেট)। অর্থাৎ এটি পি, ই এবং ডি এর মান অগ্রাহ্য করে। আপনি decodes = a, t = n, u = i, m = m দিয়ে "কল" করার সাথে সাথে এটি কার্যকরভাবে প্রতিস্থাপন beginকরে main
ljrk

71

ব্যবহারের চেষ্টা করুন gcc -E source.c, আউটপুট এর সাথে শেষ হয়:

সুতরাং একটি main()ফাংশন আসলে প্রিপ্রসেসর দ্বারা উত্পাদিত হয়।


37

ম্যাক্রো প্রসারণের কারণে প্রশ্নযুক্ত প্রোগ্রামটি কল করেmain() , তবে আপনার অনুমান ত্রুটিযুক্ত - এটিতে কোনও কল main()করতে হবে না!

কড়া কথায় বলতে গেলে আপনার কাছে একটি সি প্রোগ্রাম থাকতে পারে এবং এটি কোনও mainচিহ্ন না রেখে সংকলন করতে সক্ষম হতে পারে । mainএটি এমন একটি জিনিস যা c libraryএটির নিজের সূচনাটি শেষ করার পরেও ঝাঁপিয়ে পড়ার প্রত্যাশা করে। সাধারণত আপনি mainlibc প্রতীক হিসাবে পরিচিত হিসাবে ঝাঁপ দাও _start। কোনও বৈধ প্রোগ্রাম থাকা সর্বদা সম্ভব, এটি কেবল প্রধান না করেই সমাবেশ পরিচালনা করে। এক নজর দেখে নাও:

উপরেরটি দিয়ে এগুলি সংকলন করুন gcc -nostdlib without_main.cএবং Hello World!কেবল ইনলাইন অ্যাসেমব্লিতে সিস্টেম কল (বিঘ্নিত) জারি করে এটি পর্দায় মুদ্রণযোগ্য দেখুন।

এই নির্দিষ্ট সমস্যা সম্পর্কে আরও তথ্যের জন্য, ksplice ব্লগটি দেখুন

আর একটি আকর্ষণীয় বিষয় হ'ল এটি হ'ল আপনার এমন একটি প্রোগ্রামও থাকতে mainপারে যা সি ফাংশনের সাথে প্রতীক না রেখে সংকলন করে। উদাহরণস্বরূপ, আপনার একটি খুব কার্যকর সি প্রোগ্রাম হিসাবে নিম্নলিখিতগুলি থাকতে পারে, যা সতর্কতা স্তরটি আপ করার সময় কেবল সংকলকটিকে আরও সজ্জিত করে।

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

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


4
_startএকটি সংজ্ঞায়িত স্ট্যান্ডার্ডের অংশের নাম , বা এটি কেবল বাস্তবায়ন-নির্দিষ্ট? অবশ্যই আপনার "অ্যারের হিসাবে প্রধান" আর্কিটেকচার-নির্দিষ্ট। এছাড়াও গুরুত্বপূর্ণ, আপনার "প্রধান হিসাবে একটি অ্যারের" কৌশলটি সুরক্ষার বিধিনিষেধের কারণে রান সময়ে ব্যর্থ হওয়া অযৌক্তিক হবে না (যদিও আপনি constকোয়ালিফায়ারটি ব্যবহার না করেন তবে এটি আরও বেশি সম্ভাবনাযুক্ত হতে পারে , এবং এখনও অনেক সিস্টেম এটির অনুমতি দিবে)।
মাহ

4
@ মম: _startইএলএফ স্ট্যান্ডার্ডে নেই, যদিও এএমডি ps৪ পিএসএবিআইতে ৩.৪ প্রক্রিয়া_start শুরুর দিকে উল্লেখ রয়েছে । আনুষ্ঠানিকভাবে, ইএলএফ কেবলমাত্র ইএলএফ শিরোনামের ঠিকানা সম্পর্কে জানে , বাস্তবায়নটি বেছে নেওয়া একটি নাম। e_entry_start
নিনজালজ

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

4
@ স্টিওয়ার্ট: এটি অবশ্যই এআরএমভি 6 এল (বিভাজন ত্রুটি) এ ব্যর্থ হয়। তবে এটি কোনও x86-64 আর্কিটেকচারে কাজ করা উচিত।
বাম দিকের বাইরে

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

30

কেউ যাদুকরের মতো অভিনয় করার চেষ্টা করছেন। সে মনে করে যে সে আমাদের প্রতারিত করতে পারে। তবে আমরা সকলেই জানি, সি প্রোগ্রামের প্রয়োগটি শুরু হয় main()

int begin()সঙ্গে প্রতিস্থাপন করা হবে decode(a,n,i,m,a,t,e)প্রাক প্রসেসর পর্যায় এক পাস দ্বারা। তারপরে আবার decode(a,n,i,m,a,t,e)m ## a ## i ## n দিয়ে প্রতিস্থাপন করা হবে। ম্যাক্রো কলের অবস্থানগত সমিতি হিসাবে s, চরিত্রের একটি মান থাকবে a। একইভাবে, u'i' tদ্বারা প্রতিস্থাপিত হবে এবং 'এন' দ্বারা প্রতিস্থাপিত হবে। এবং, এইভাবে, m##s##u##tহয়ে যাবেmain

সম্পর্কিত, ##ম্যাক্রো প্রসারণের প্রতীক, এটি প্রাকপ্রসেসিং অপারেটর এবং এটি টোকন পেস্টিং সম্পাদন করে। যখন কোনও ম্যাক্রো প্রসারিত হয়, প্রতিটি '##' অপারেটরের উভয় পাশের দুটি টোকেনকে একক টোকনে একত্রিত করা হয়, যা ম্যাক্রো প্রসারণে '##' এবং দুটি মূল টোকেনকে প্রতিস্থাপন করে।

আপনি যদি আমাকে বিশ্বাস না করেন তবে আপনি -Eপতাকা সহ আপনার কোডটি সংকলন করতে পারেন । এটি প্রিপ্রোসেসিংয়ের পরে সংকলন প্রক্রিয়া বন্ধ করবে এবং আপনি টোকেন আটকানোর ফলাফল দেখতে পাবেন।


11

decode(a,b,c,d,[...])প্রথম চারটি আর্গুমেন্ট পরিবর্তন করে এবং ক্রমে একটি নতুন সনাক্তকারী পেতে তাদের সাথে যোগ দেয় dacb। (বাকি তিনটি যুক্তি উপেক্ষা করা হয়)) উদাহরণস্বরূপ, decode(a,n,i,m,[...])শনাক্তকারী দেয় main। নোট করুন যে এটি beginম্যাক্রো হিসাবে সংজ্ঞায়িত হয়েছে।

সুতরাং, beginম্যাক্রো কেবল হিসাবে সংজ্ঞায়িত করা হয় main


2

আপনার উদাহরণে, main()ফাংশনটি আসলে উপস্থিত রয়েছে, কারণ beginএকটি ম্যাক্রো যা সংকলকটি decodeম্যাক্রোর সাথে প্রতিস্থাপন করে যা পরিবর্তিতভাবে এম ## এস ## ইউ ## টি অভিব্যক্তি দ্বারা প্রতিস্থাপিত হয়। ম্যাক্রো সম্প্রসারণ ব্যবহার ##, আপনি শব্দ পৌঁছবে mainথেকে decode। এটি একটি ট্রেস:

এটি থাকা মাত্র একটি কৌশল main(), তবে main()প্রোগ্রামিংয়ের প্রবেশ ফাংশনের জন্য নাম ব্যবহার করা সি প্রোগ্রামিং ভাষায় প্রয়োজন হয় না। এটি আপনার অপারেটিং সিস্টেম এবং এর অন্যতম সরঞ্জাম হিসাবে লিঙ্কারের উপর নির্ভর করে।

উইন্ডোজ, আপনি সবসময় ব্যবহার করবেন না main(), কিন্তু বরং WinMainবাwWinMain , যদিও আপনি ব্যবহার করতে পারেন main(), এমনকি Microsoft এর টুলচেইন সঙ্গে । লিনাক্সে, কেউ ব্যবহার করতে পারেন _start

এন্ট্রি পয়েন্ট সেট করার জন্য এটি অপারেটিং সিস্টেমের সরঞ্জাম হিসাবে লিঙ্কারের উপর নির্ভর করে, ভাষাটি নয়। আপনি আমাদের নিজস্ব এন্ট্রি পয়েন্ট এমনকি সেট করতে পারেন, এবং আপনি একটি লাইব্রেরি তৈরি করতে পারেন যা কার্যকরও হয় !


@ ভ্যাক্সকুইস আপনি ঠিক বলেছেন তবে এটি একটি আংশিক উত্তর যা আমি প্রথম উত্তরটির প্রশংসা / সংশোধন করার জন্য লিখেছিলাম যা main()সি প্রোগ্রামিং ভাষার সাথে ফাংশনকে আবদ্ধ করে, যা সঠিক নয়।
Ho1

@ ভ্যাক্সকুইস আমি ধরে নিয়েছি যে সি প্রোগ্রামগুলিতে "মূল () ফাংশনটি ব্যাখ্যা করা অপরিহার্য নয়" একটি আংশিক উত্তর হবে। উত্তরটি সম্পূর্ণ করার জন্য আমি একটি অনুচ্ছেদ যুক্ত করেছি। - Ho1 16 মিনিট আগে
Ho1
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.