সংকলকরা যখন স্ট্যাটিকালি "জটিল" এক্সপ্রেশনটি টাইপ করেন তখন সাধারণ পদ্ধতিটি কী?


23

দ্রষ্টব্য: আমি যখন শিরোনামে "জটিল" ব্যবহার করি, তখন আমি বোঝাতে চাই যে এক্সপ্রেশনটিতে অনেক অপারেটর এবং অপারেটস রয়েছে। এমন নয় যে প্রকাশটি নিজেই জটিল।


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

নিম্নলিখিত উদাহরণ বিবেচনা করুন:

আমার সংকলকের পার্সার কোডের এই লাইনটি পড়েছেন:

int a = 1 + 2 - 3 * 4 - 5

এবং এটি নিম্নলিখিত এএসটিতে রূপান্তরিত করেছেন:

       =
     /   \
  a(int)  \
           -
         /   \
        -     5
      /   \
     +     *
    / \   / \
   1   2 3   4

এখন এটি অবশ্যই এএসটি চেক করতে হবে। এটি প্রথম ধরণের =অপারেটর পরীক্ষা করে শুরু হয় । এটি প্রথমে অপারেটরের বাম দিকটি পরীক্ষা করে। এটি দেখেছে যে ভেরিয়েবলটিকে aপূর্ণসংখ্যা হিসাবে ঘোষণা করা হয়। সুতরাং এটি এখন অবশ্যই যাচাই করা উচিত যে ডান হাতের অভিব্যক্তিটি একটি পূর্ণসংখ্যার সাথে মূল্যায়ন করে।

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

কেবলমাত্র অন্য যেভাবে এটি করা সম্ভব তা হ'ল এটিএসটিতে প্রতিটি সুব্রপ্রেসনের পাতাটি পুনরাবৃত্তভাবে পরীক্ষা করা এবং পাতার সমস্ত প্রকার প্রত্যাশিত অপারেটরের ধরণের সাথে যাচাই করা। =অপারেটরের সাথে শুরু করে , টাইপ চেকারটি তারপরে বাম হাতের সমস্ত এএসটি স্ক্যান করবে এবং যাচাই করবে যে পাতাগুলি সমস্ত পূর্ণসংখ্যা are এরপরে এটি প্রতিটি অপারেটরের জন্য স্যুবপ্রেসেশনে পুনরাবৃত্তি করবে।

আমি আমার "দ্য ড্রাগন বুক" এর অনুলিপিটিতে বিষয়টি নিয়ে গবেষণা করার চেষ্টা করেছি , তবে এটি খুব বেশি বিশদে যায়নি বলে মনে হয় এবং আমি ইতিমধ্যে যা জানি তা কেবল পুনরাবৃত্তি করে।

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


8
একটি এক্সপ্রেশন ধরণের চেক করার সুস্পষ্ট এবং সহজ উপায় আছে। আপনি কী এটি এটিকে "বিরক্তিকর" বলছেন তা ভাল করে বলুন।
gnasher729

12
সাধারণ পদ্ধতিটি হ'ল "দ্বিতীয় পদ্ধতি": সংকলকটি এর সুব্যাপ্রেসেশনের ধরণের জটিল জটিল অভিব্যক্তির প্রকারকে অনুমান করে। এটি ছিল ডেনোটেশনাল শব্দার্থবিদ্যার মূল পয়েন্ট এবং আজ অবধি তৈরি বেশিরভাগ টাইপ সিস্টেম systems
জোকার_ভিডি

5
দুটি পদ্ধতির ভিন্ন আচরণ হতে পারে: উপরের-নীচের পদ্ধতির double a = 7/2 ডান দিকের দিকটিকে দ্বিগুণ হিসাবে ব্যাখ্যা করার চেষ্টা করবে, সুতরাং অংকের এবং বর্ণকে দ্বিগুণ হিসাবে ব্যাখ্যা করার চেষ্টা করবে এবং প্রয়োজনে সেগুলি রূপান্তর করতে হবে; ফলে a = 3.5। নীচে আপ বিভাজন পূর্ণসংখ্যা সঞ্চালন এবং শুধুমাত্র গত পদক্ষেপ (নিয়োগ) উপর রূপান্তর হবে, তাই a = 3.0
হেগেন ভন ইটজেন

3
লক্ষ্য করুন যে আপনার এএসটি-র চিত্রটি আপনার অভিব্যক্তির সাথে int a = 1 + 2 - 3 * 4 - 5নয় তবে এর সাথে int a = 5 - ((4*3) - (1+2))
মিলছে

22
আপনি মানের পরিবর্তে ধরণের অভিব্যক্তিটি "চালানো" করতে পারেন; যেমন int + intহয়ে যায় int

উত্তর:


14

পুনরাবৃত্তি উত্তর, তবে আপনি অপারেশন পরিচালনা করার আগে প্রতিটি সাবট্রিতে নেমেছেন:

int a = 1 + 2 - 3 * 4 - 5

গাছ আকারে:

(assign (a) (sub (sub (add (1) (2)) (mul (3) (4))) (5))

প্রথমে বাম হাত দিয়ে, তারপরে ডান হাত দিয়ে এবং পরে অপারেটরগুলির ধরণগুলি নির্ধারিত হওয়ার সাথে সাথে অপারেটরটিকে পরিচালনা করার মাধ্যমে প্রকারটি নির্দেশ করে:

(assign*(a) (sub (sub (add (1) (2)) (mul (3) (4))) (5))

-> lh অবতরণ

(assign (a*) (sub (sub (add (1) (2)) (mul (3) (4))) (5))

-> আভাসিত করা aaহিসাবে পরিচিত হয় int। আমরা assignএখন নোডে ফিরে এসেছি :

(assign (int:a)*(sub (sub (add (1) (2)) (mul (3) (4))) (5))

-> আরএইচএসে নামুন, তারপরে অভ্যন্তরীণ অপারেটরদের LHS তে নেমে যাওয়া যতক্ষণ না আমরা কোনও আকর্ষণীয় কিছু আঘাত করি না

(assign (int:a) (sub*(sub (add (1) (2)) (mul (3) (4))) (5))
(assign (int:a) (sub (sub*(add (1) (2)) (mul (3) (4))) (5))
(assign (int:a) (sub (sub (add*(1) (2)) (mul (3) (4))) (5))
(assign (int:a) (sub (sub (add (1*) (2)) (mul (3) (4))) (5))

-> কোন ধরণের 1, তা intনির্ধারণ করুন এবং পিতামাতার কাছে ফিরে যান

(assign (int:a) (sub (sub (add (int:1)*(2)) (mul (3) (4))) (5))

-> আরএইচএসে যান

(assign (int:a) (sub (sub (add (int:1) (2*)) (mul (3) (4))) (5))

-> কোন ধরণের 2, তা intনির্ধারণ করুন এবং পিতামাতার কাছে ফিরে যান

(assign (int:a) (sub (sub (add (int:1) (int:2)*) (mul (3) (4))) (5))

-> কোন ধরণের add(int, int), তা intনির্ধারণ করুন এবং পিতামাতার কাছে ফিরে যান

(assign (int:a) (sub (sub (int:add (int:1) (int:2))*(mul (3) (4))) (5))

-> আরএইচএসে নামুন

(assign (int:a) (sub (sub (int:add (int:1) (int:2)) (mul*(3) (4))) (5))

ইত্যাদি, যতক্ষণ না আপনার শেষ হয়

(assign (int:a) (int:sub (int:sub (int:add (int:1) (int:2)) (int:mul (int:3) (int:4))) (int:5))*

অ্যাসাইনমেন্ট নিজেই কোনও প্রকারের সাথে একটি অভিব্যক্তি কিনা তা আপনার ভাষার উপর নির্ভর করে।

গুরুত্বপূর্ণ অবলম্বন: গাছে কোনও অপারেটর নোডের ধরণ নির্ধারণ করতে, আপনাকে কেবলমাত্র তার নিকটবর্তী বাচ্চাদের দিকে নজর দিতে হবে, যার জন্য তাদের ইতিমধ্যে একটি ধরণের নিয়োগ করা প্রয়োজন।


43

যখন কোনও সংকলক অনেক অপারেটর এবং অপারেটরগুলির সাথে টাইপ চেক এক্সপ্রেশন থাকে তখন সাধারণত কোন পদ্ধতিটি ব্যবহৃত হয়?

টাইপ সিস্টেম এবং টাইপ অনুমান এবং উইন্ডি -মিলনার টাইপ সিস্টেমে উইকিপেজ পড়ুন , যা একীকরণ ব্যবহার করেডায়নোটেশনাল শব্দার্থক এবং অপারেশনাল শব্দার্থক সম্পর্কেও পড়ুন ।

টাইপ চেকিং সহজ হতে পারে যদি:

  • আপনার সমস্ত ভেরিয়েবলগুলি aএকটি প্রকারের সাথে স্পষ্টভাবে ঘোষণা করা হয়। এটি সি বা পাস্কাল বা সি ++ 98 এর মতো, তবে সি ++ 11 এর মতো নয় যা কিছু ধরণের সহন করে auto
  • সমস্ত আক্ষরিক মান যেমন 1, 2বা 'c'একটি অন্তর্নিহিত টাইপ থাকে: একটি অন্তর্গত আক্ষরিক সবসময় টাইপ থাকে int, একটি অক্ষর আক্ষরিক সবসময় টাইপ থাকে char,…।
  • ফাংশন এবং অপারেটরগুলি ওভারলোড হয় না, যেমন +অপারেটরের সর্বদা টাইপ থাকে (int, int) -> int। সিতে অপারেটরগুলির জন্য ওভারলোডিং রয়েছে ( +স্বাক্ষরিত এবং স্বাক্ষরযুক্ত স্বাক্ষরযুক্ত পূর্ণ সংখ্যার জন্য এবং ডাবলসের জন্য কাজ করে) তবে কোনও ক্রিয়াকলাপের ওভারলোডিং নেই।

এই সীমাবদ্ধতার অধীনে, একটি ডাউন আপ রিকার্সিভ এএসটি ধরণের সাজসজ্জা অ্যালগরিদম যথেষ্ট হতে পারে (এটি কেবল প্রকারের বিষয়ে চিন্তা করে , কংক্রিটের মানগুলি নিয়ে নয়, তাই এটি একটি সংকলন-সময় পদ্ধতির):

  • প্রতিটি সুযোগের জন্য, আপনি সমস্ত দৃশ্যমান ভেরিয়েবলের (যেমন পরিবেশ বলা হয়) প্রকারের জন্য একটি টেবিল রাখেন। একটি ঘোষণার পরে int a, আপনি a: intটেবিলে এন্ট্রি যুক্ত করবেন।

  • পাতাগুলির টাইপিং হ'ল তুচ্ছ পুনরাবৃত্তি বেস কেস: লেটারেলের ধরণ 1ইতিমধ্যে জানা যায়, এবং এর মতো চলকের ধরণটি aপরিবেশে দেখা যায়।

  • পূর্ববর্তী গণিত ধরণের (নেস্টেড সাব-এক্সপ্রেশন) অপারেশন অনুসারে কিছু অপারেটর এবং অপারেটরগুলির সাথে একটি এক্সপ্রেশন টাইপ করতে, আমরা অপারেন্ডগুলিতে পুনরাবৃত্তি ব্যবহার করি (সুতরাং আমরা প্রথমে এই উপ-এক্সপ্রেশনগুলি টাইপ করি) এবং অপারেটর সম্পর্কিত টাইপিং বিধি অনুসরণ করি ।

সুতরাং আপনার উদাহরণে, 4 * 3এবং 1 + 2টাইপ করা হয়েছে intকারণ 4& 3এবং 1& 2আগে টাইপ করা হয়েছিল intএবং আপনার টাইপিং বিধিগুলি বলে যে দুই-এর যোগফল বা পণ্য intএকটি intএবং তাই (4 * 3) - (1 + 2)

তারপরে পিয়েরের প্রকার এবং প্রোগ্রামিং ভাষার বই পড়ুন। আমি Ocaml এবং λ-ক্যালকুলাস একটি সামান্য বিট শিখতে সুপারিশ

আরও গতিশীল টাইপ করা ভাষার জন্য (লিস্পের মতো) ছোট পিসগুলিতে কুইনেকের লিসপও পড়ুন

স্কটের প্রোগ্রামিং ল্যাঙ্গুয়েজস প্রাগমিক্স বইটিও পড়ুন

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


2
সি ++ 11 কীভাবে autoসহজ নয়? এটি ছাড়াই আপনাকে ডান পাশের ধরণটি বের করতে হবে, তারপরে দেখুন বাম পাশে টাইপের সাথে কোনও মিল বা রূপান্তর আছে কিনা see আপনার সাথে autoকেবল ডান পাশের ধরণটি বের করুন এবং আপনার কাজ শেষ হয়েছে।
এনপিওপি

3
@nwp সি ++ auto, সি # varএবং গো :=ভেরিয়েবল সংজ্ঞাগুলির সাধারণ ধারণাটি খুব সহজ: টাইপ করুন সংজ্ঞাটির ডানদিকে পরীক্ষা করুন। ফলস্বরূপ টাইপটি বাম পাশের চলকের ধরণ। তবে শয়তানটি বিশদে রয়েছে। উদাহরণস্বরূপ, সি ++ সংজ্ঞা স্ব-উল্লেখ হতে পারে তাই আপনি পরিবর্তনশীল RHS উপর ঘোষিত হওয়ার যেমন পড়ুন পারে int i = f(&i)। প্রকারটি iযদি অনুমান করা হয় তবে উপরের অ্যালগরিদমটি ব্যর্থ হবে: আপনার প্রকারটি নির্ধারণ iকরার ধরনটি জানতে হবে i। পরিবর্তে, আপনার টাইপ ভেরিয়েবলগুলির সাথে পুরো এইচএম-স্টাইলের ধরণের ইনফেরেন্সের প্রয়োজন হবে।
আমন

13

সিতে (এবং সি এর ভিত্তিতে খাঁটিভাবে বেশিরভাগ স্ট্যাটিক্যালি টাইপ করা ভাষাগুলি) প্রতিটি অপারেটরকে একটি ফাংশন কলের জন্য সিনট্যাকটিক চিনিরূপে দেখা যায়।

সুতরাং আপনার অভিব্যক্তিটি আবার লিখিত হতে পারে:

int a{operator-(operator-(operator+(1,2),operator*(3,4)),5)};

তারপরে ওভারলোড রেজোলিউশনটি কিক করে সিদ্ধান্ত নেবে যে প্রতিটি ফাংশনটি (int, int)বা (const int&, const int&)টাইপের of

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

কোনও কারণ হিসাবে এটি double x = 1/2;ফলাফল হবে x == 0কারণ 1/2একটি অন্তঃপ্রকাশ হিসাবে মূল্যায়ন করা হয়।


6
সি এর ক্ষেত্রে প্রায় সত্য, যেখানে +ফাংশন কলগুলির মতো পরিচালনা করা হয় না (যেহেতু এটির জন্য doubleএবং int
অপারেশনগুলির

2
@BasileStarynkevitch: এটা ওভারলোড ফাংশন একটি সিরিজ মত বাস্তবায়িত আছে: operator+(int,int), operator+(double,double), operator+(char*,size_t), ইত্যাদি পার্সার শুধু ট্র্যাকের রাখা হয়েছে যা এক নির্বাচিত হয়।
হাঁসকে

3
@ এস্পেল্পার কেউই পরামর্শ দিচ্ছিল না যে উত্স- এবং নির্দিষ্ট স্তরের সি আসলে ওভারলোডড ফাংশন বা অপারেটর ক্রিয়াকলাপ
বিড়াল

1
অবশ্যই না. কেবল এটিকে ইঙ্গিত করে যে সি পার্সারের ক্ষেত্রে, "ফাংশন কল" হ'ল আপনাকে অন্যরকম কিছু করতে হবে যা এখানে বর্ণিত হিসাবে "ফাংশন কল হিসাবে অপারেটর" এর সাথে খুব বেশি মিল নেই। আসলে, সিতে ধরণের ধরণটি নির্ধারণ করা ধরণের প্রকারটি নির্ধারণের f(a,b)চেয়ে কিছুটা সহজ a+b
aschepler

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

6

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


6

এটি আসলে বেশ সহজ, যতক্ষণ না আপনি +একক ধারণার চেয়ে বিভিন্ন ফাংশন হিসাবে ভাবেন ।

    int operator=(int)
     /   \
  a(int)  \
        int operator-(int,int)
         /                  \
    int operator-(int,int)    5
         /              \
int operator+(int,int) int operator*(int,int)
    / \                      / \
   1   2                    3   4

ডানদিকে পার্সিংয়ের সময়, পার্সার পুনরুদ্ধার করে 1, জানে যে এটি একটি int, তারপরে পার্স +এবং স্টোরগুলি যে "অমীমাংসিত ফাংশন নাম" হিসাবে, তারপর এটি পার্স করে 2, জানে যে এটি একটি int, এবং তারপরে স্ট্যাকটি ফিরে আসে। +ফাংশন নোড এখন উভয় প্যারামিটার ধরনের জানেন, তাই সমাধান করতে পারেন +মধ্যে int operator+(int, int), তাই এখন এই উপ-অভিব্যক্তি ধরণ জানেন, পার্সার এটা শুভ পথে চলতে থাকে।

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

char* ptr = itoa(3);

গাছটি এখানে:

    char* itoa(int)
     /           \
  ptr(char*)      3

4

টাইপ চেকিংয়ের ভিত্তিটি সংকলক যা করে তা নয়, ভাষাটি যা সংজ্ঞায়িত করে এটি।

সি ভাষায়, প্রতিটি অপারেন্ডের একটি প্রকার থাকে। "abc" এ "কনস্টের চরের অ্যারে" টাইপ রয়েছে। 1 এর "int" টাইপ রয়েছে। 1 এল এর "লম্বা" টাইপ রয়েছে। যদি x এবং y এক্সপ্রেশন হয় তবে x + y প্রকারের জন্য নিয়ম রয়েছে। সুতরাং সংকলক স্পষ্টতই ভাষা নিয়ম অনুসরণ করতে হবে।

সুইফ্টের মতো আধুনিক ভাষাগুলিতে নিয়মগুলি আরও জটিল are কিছু ক্ষেত্রে সি এর মত সহজ হয়। অন্যান্য ক্ষেত্রে, সংকলকটি একটি অভিব্যক্তি দেখায়, এক্সপ্রেশনটি কী ধরণের হওয়া উচিত তা আগেই বলা হয়েছিল এবং তার ভিত্তিতে সুব এক্সপ্রেসনের ধরণগুলি নির্ধারণ করে। যদি x এবং y বিভিন্ন ধরণের ভেরিয়েবল হয় এবং একটি অভিন্ন এক্সপ্রেশন নির্ধারিত হয় তবে সেই অভিব্যক্তিটি ভিন্ন উপায়ে মূল্যায়ন করা যেতে পারে। উদাহরণস্বরূপ 12 * (2/3) বরাদ্দকরণ একটি ডাবলকে 8.0 এবং একটি ইন্টারকে 0 প্রদান করবে। এবং আপনার এমন কেস রয়েছে যেখানে সংকলক জানে যে দুটি ধরণের সম্পর্কযুক্ত এবং সেগুলি কিসের ভিত্তিতে রয়েছে তা নির্ধারণ করে।

দ্রুত উদাহরণ:

var x: Double
var y: Int

x = 12 * (2 / 3)
y = 12 * (2 / 3)

print (x, y)

"8.0, 0" মুদ্রণ।

অ্যাসাইনমেন্টে x = 12 * (2/3): বাম হাতের দিকটি একটি পরিচিত টাইপ ডাবল রয়েছে, তাই ডান হাতের পাশে ডাবল টাইপ থাকতে হবে। "*" অপারেটরের ডাবল ফিরতে কেবল একটি ওভারলোড রয়েছে এবং এটি ডাবল * ডাবল -> ডাবল। সুতরাং 12 টিতে অবশ্যই ডাবল টাইপ থাকতে হবে, পাশাপাশি 2 / 3. অবশ্যই 12 ইন্টিগ্রেটারলিটারাল কনভার্টেবল "প্রোটোকল" সমর্থন করে। "IntegerLiteralConvertible" টাইপের একটি আর্গুমেন্ট গ্রহণ করে ডাবলটির একটি ইনিশিয়ালসর রয়েছে, সুতরাং 12 টি ডাবলে রূপান্তরিত। 2/3 এর অবশ্যই টাইপ ডাবল থাকতে হবে। "/" অপারেটরের ডাবল ফিরতে কেবল একটি ওভারলোড রয়েছে এবং তা ডাবল / ডাবল -> ডাবল। 2 এবং 3 ডাবল রূপান্তরিত হয়। 2/3 এর ফলাফল 0.6666666। 12 * (2/3) এর ফলাফল 8.0। 8.0 এক্স নির্ধারিত হয়।

অ্যাসাইনমেন্টে y = 12 * (2/3) এ y এর বাম পাশে ইন্ট টাইপ আছে তাই ডান হাতের প্রান্তটি টাইপ করতে হবে তাই 12, 2, 3 ফলাফল 2/3 = এর সাথে ইন্টারে রূপান্তরিত হবে 0, 12 * (2/3) = 0।

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