অন্তর্নিহিত অর্থ (*) (অন্তর্নিহিত *) = 5 (বা কোনও পূর্ণসংখ্যার মান)


88

আমি এটি বুঝতে পারি না:

int main() {
    int (*) (int *) = 5;
    return 0;
}

উপরের অ্যাসাইনমেন্টটি g ++ c ++ 11 দিয়ে সংকলন করে। আমি জানি যে int (*) (int *)এটি একটি ফাংশনের পয়েন্টার যা একটি (int *)আর্গুমেন্ট হিসাবে গ্রহণ করে এবং কোন পূর্বাবস্থায় ফিরে আসে, তবে আমি বুঝতে পারি না আপনি কীভাবে এটি 5 এর সমতুল্য করতে পারেন আমি প্রথমে ভেবেছিলাম এটি এমন একটি ফাংশন যা ক্রমাগতভাবে 5 ফিরিয়ে দেয় (আমার সাম্প্রতিক শিক্ষায় F #, সম্ভবত, হাহা), তারপরে আমি সংক্ষেপে ভেবেছিলাম যে ফাংশন পয়েন্টারটি মেমরির অবস্থান 5 এর দিকে নির্দেশ করে, তবে এটি কার্যকরভাবে পরিষ্কারভাবে কাজ করে না এবং হেক্সেরও মূল্যবোধ হয় না।

এটি এই কারণ হতে পারে যে ভেবেছিল যে ফাংশনটি কোনও পূর্বাবস্থায় ফিরে আসে, এবং কোনও পূর্বনির্ধারিত কাজটি ঠিক আছে (কোনওভাবে), আমি এটিও চেষ্টা করেছি:

int * (*) (int *) = my_ptr

যেখানে my_ptrটাইপ হয় int *, টাইপ ইন্টের সাথে প্রথম ক্ষেত্রে যেমন দ্বিতীয় ফাংশন পয়েন্টার হিসাবে একই प्रकार। এটি সংকলন করে না। 5 এর পরিবর্তে, বা কোনও অন্তর্গত মান নির্ধারণের পরে, my_ptrএই ফাংশন পয়েন্টারের জন্য সংকলন করা হয় না।

সুতরাং অ্যাসাইনমেন্ট মানে কি?

আপডেট 1

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

সম্পাদনা করুন 1

আমি জিসিসি সংস্করণ ব্যবহার করছি 4.8.2 (উবুন্টু 4.8.2 এ)

সম্পাদনা 2

প্রকৃতপক্ষে, এটিকে কোনও কিছুর সাথে সমান করা আমার সংকলকটিতে কাজ করে। এমনকি এটি একটি std :: স্ট্রিং ভেরিয়েবল, বা একটি ফাংশন নামের যা একটি দ্বিগুণ ফিরিয়ে দেয়, সমান করে।

সম্পাদনা 2.1

মজার বিষয় হচ্ছে, এটিকে কোনও ফাংশনটির জন্য একটি ফাংশন পয়েন্টার তৈরি করে যা কোনও ডাটা টাইপ দেয় যা কোনও পয়েন্টার নয়, এটি সংকলন করতে দেয়, যেমন

std::string (*) () = 5.6;

তবে ফাংশন পয়েন্টারটি কোনও ফাংশনটিতে ফিরে আসে যা কিছু পয়েন্টার দেয়, এটি সংকলন করে না, যেমন এর সাথে

some_data_type ** (*) () = any_value;

4
হুম ... এটি ঠিক দেখাচ্ছে না, এবং ঝনঝন এটি গ্রহণ করে না। একটি সিসি এক্সটেনশন (বা বাগ) হতে পারে।
শীতকালীন

4
g ++ কম্পাইল করে তবে error: expected identifier or '(' before ')' token
জিসিসি

4
@ 0x499602D নোট করুন যে কোডটি পয়েন্টারে কোনও নাম দেয় না। সঙ্গে int *x = 5যদি আপনি এটি নামে xint * (*x) (int *) = 5এটি দিয়ে সংকলন হবে না। (তবে এটি সি কোড হিসাবে সংকলন করবে)।
Nos

4
হ্রাস করা int(*) = 5;int(*);
টেস্টকেস

উত্তর:


60

এটি জি ++ এ একটি বাগ।

 int (*) (int *) 

একটি টাইপ নাম।

সি ++ এ আপনি সনাক্তকারী ছাড়া প্রকারের নাম সহ কোনও ঘোষণা করতে পারবেন না।

সুতরাং এটি g ++ দিয়ে সংকলন করে।

 int (*) (int *) = 5;

এবং এটি পাশাপাশি সংকলন:

 int (*) (int *);

তবে এগুলি উভয়ই অবৈধ ঘোষণা।

সম্পাদনা :

টিসি মন্তব্য বুগজিলা বাগ 60680 তে অনুরূপ পরীক্ষার ক্ষেত্রে উল্লেখ করেছেন তবে এটি এখনও অনুমোদিত হয়নি । বাগটি বুগজিলায় নিশ্চিত হয়ে গেছে।

সম্পাদনা 2 :

উপরোক্ত দুটি ঘোষণাপত্র যখন ফাইল স্কোপে থাকে g ++ সঠিকভাবে একটি ডায়াগনস্টিক ইস্যু করে (এটি ব্লক স্কোপে ডায়াগনস্টিকটি দিতে ব্যর্থ হয়)।

সম্পাদনা 3 :

আমি যাচাই করেছিলাম এবং আমি g ++ সংস্করণ 4 (4.9.2) এর সর্বশেষ প্রকাশ, সর্বশেষ প্রাক-প্রকাশের সংস্করণ 5 (5.0.1 20150412) এবং সর্বশেষ পরীক্ষামূলক সংস্করণ 6 (6.0.0 20150412) এ সমস্যাটি পুনরুত্পাদন করতে পারি।


4
এমএসভিসি সম্পাদিত পোস্ট কোডটি বাতিল করেছেerror C2059: syntax error : ')'
আবহাওয়া ভ্যান

যদি এটি কোনও প্রকারের নাম হয় তবে কেন 'ইনট (*) (ইনট *) ইনট_ফঙ্ক হয় না;' কাজ?
কনরাড

4
জিসিসি বাগজিলার জন্য, "নতুন" একটি নিশ্চিত বাগ। (অসমর্থিত বাগগুলি "UNCONFIRMED")।
টিসি 21

4
@ কনরাডক্যাপ: আপনি যদি বলছেন int (*int_func)(int *); যা কোনও ফাংশন পয়েন্টার নামক হিসাবে ঘোষণা করে তবে এটি ঠিক কাজ করে int_func
এডওয়ার্ড

4
@ কনরাডক্যাপ সি ++ সনাক্তকারী স্থাপনের জন্য ইনফিক্স স্বরলিপি ব্যবহার করে; একই কারণে এটি int x[5];এবং নাint[5] x;
এমএম

28

এটি বৈধ সি ++ নয়। মনে রাখবেন যে আপনার নির্দিষ্ট সংকলকটি সংকলিত হওয়ার কারণে এটি বৈধ হয় না। সমস্ত জটিল সফ্টওয়্যারগুলির মতো সংকলকগুলির মাঝে মাঝে বাগ থাকে এবং এটি এক হিসাবে উপস্থিত হয়।

বিপরীতে clang++অভিযোগ:

funnycast.cpp:3:11: error: expected expression
    int (*) (int *) = 5;
          ^
funnycast.cpp:3:18: error: expected '(' for function-style cast or type construction
    int (*) (int *) = 5;
             ~~~ ^
funnycast.cpp:3:19: error: expected expression
    int (*) (int *) = 5;
                  ^
3 errors generated.

এটি প্রত্যাশিত আচরণ কারণ আপত্তিজনক লাইনটি সি ++ বৈধ নয়। এটি একটি কার্যনির্বাহী হওয়ার কারণ হিসাবে (কারণ =) তবে কোনও সনাক্তকারী নেই identif


9

অন্যান্য উত্তরগুলি যেমন উল্লেখ করেছে, এটি একটি বাগ

int (*) (int *) = 5;

সংকলন। এই বিবৃতিটির একটি যুক্তিসঙ্গত সমীকরণ যার অর্থ আশা করা যায় তা হ'ল:

int (*proc)(int*) = (int (*)(int*))(5);

এখন procএকটি পয়েন্টার-টু-ফাংশন যা প্রত্যাশা করে যে 5ঠিকানাটি কোনও ফাংশনের বেস ঠিকানা হবে যা গ্রহণ করে int*এবং এটির কোনও ফেরত দেয় int

কিছু মাইক্রোকন্ট্রোলার / মাইক্রোপ্রসেসরের 5ক্ষেত্রে একটি বৈধ কোড ঠিকানা হতে পারে এবং সেখানে এই জাতীয় ফাংশনটি সনাক্ত করা সম্ভব হতে পারে।

বেশিরভাগ সাধারণ উদ্দেশ্যে কম্পিউটারগুলিতে, পয়েন্টার অ্যাক্সেসগুলি 0-1023ধরার জন্য মেমোরির প্রথম পৃষ্ঠা ( 4K পৃষ্ঠাগুলির ঠিকানা) উদ্দেশ্যমূলকভাবে অবৈধ (আনম্যাপড) হয় null

সুতরাং, আচরণটি প্ল্যাটফর্মের উপর নির্ভর করে, যখন *procকেউ অনুরোধ করা হয় (উদাঃ (*proc)(&v)) , যখন যুক্তিযুক্তভাবে পৃষ্ঠার ত্রুটি ঘটে যাওয়ার আশা করতে পারে । যে সময়ে অনুরোধ করা হয়েছিল তার আগে *proc, অস্বাভাবিক কিছু ঘটে না।

আপনি যদি ডায়নামিক লিঙ্কার না লিখে থাকেন তবে আপনার প্রায় অবশ্যই সংখ্যাগুলি ঠিকানার গণনা করা এবং পয়েন্টার-টু-ফাংশন ভেরিয়েবলগুলিতে নির্ধারণ করা উচিত নয়।


2
/usr/lib/gcc/x86_64-pc-cygwin/4.9.2/cc1plus.exe -da so.cpp

এই কমান্ড লাইনটি অনেকগুলি মধ্যবর্তী ফাইল তৈরি করে। তাদের মধ্যে প্রথম so.cpp.170r.expand, বলেছেন:

...
int main() ()
{
  int D.2229;
  int _1;

;;   basic block 2, loop depth 0
;;    pred:       ENTRY
  _1 = 0;
;;    succ:       3

;;   basic block 3, loop depth 0
;;    pred:       2
<L0>:
  return _1;
;;    succ:       EXIT

}
...

এটি ঠিক কী ঘটে তা উত্তর দেয় না তবে এটি সঠিক দিকের একটি পদক্ষেপ হওয়া উচিত।


মজাদার. এই মধ্যবর্তী ফাইলগুলির উদ্দেশ্য কী?
কনরাড

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

4
আইআর হওয়ার আরেকটি কারণ হ'ল যদি আপনার একটি ভাল সংজ্ঞায়িত আইআর থাকে তবে আপনি আপনার সংকলকটির ফ্রন্ট-এন্ড এবং ব্যাক-এন্ড আলাদা করতে পারবেন। (যেমন ফ্রন্ট-এন্ড আপনার সিআরটি IR তে কম্পাইল করে, ব্যাক-এন্ডটি আইআরটি ইন্টেল মেশিন কোডে কম্পাইল করে Now এখন আপনি যদি এআরএম সমর্থন যুক্ত করতে চান তবে আপনার কেবল একটি দ্বিতীয় ব্যাক-এন্ড প্রয়োজন And এবং আপনি যদি গো সংকলন করতে চান তবে আপনার কেবল একটি দরকার দ্বিতীয় সম্মুখ-প্রান্তে এবং তার উপরে গো সংকলক তাত্ক্ষণিকভাবে ইন্টেল এবং এআরএম উভয়কে সমর্থন করে যেহেতু আপনি উভয় পিছনের
প্রান্তকে

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

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