সি ++ এ কীওয়ার্ডটি নিবন্ধ করুন


89

মধ্যে পার্থক্য কি

int x=7;

এবং

register int x=7;

?

আমি সি ++ ব্যবহার করছি।


8
@ জিএমএন: এএনএসআই সি কোনও রেজিস্টার সামগ্রীর ঠিকানা নেওয়ার অনুমতি দেয় না; এই বিধিনিষেধটি C ++
ব্রায়ান আর বন্ডির

4
@ ব্রায়ান: এইচএম, আপনি ঠিক বলেছেন। এটি এখনই একটি নোটে রয়েছে (যে ঠিকানাটি নেওয়া হলে এটি সম্ভবত উপেক্ষা করা হবে), তবে বাধ্যতামূলক নয়। জানা ভাল. (ভাল, সাজানোর। পি)
GManNGG

8
পুনরায় খোলার জন্য ভোট registerদেওয়াতে সি এবং সি ++ এর মধ্যে বিভিন্ন শব্দার্থক শব্দ রয়েছে।
সিবি বেইলি

4
এর ফলস্বরূপ, সি-তে অ্যারে-পয়েন্টার রূপান্তরকে অ্যারে রেজিস্টার করে নিষেধ করা সম্ভব: register int a[1];সেই ঘোষণার সাথে আপনি এই অ্যারেটিকে সূচক করতে পারবেন না। যদি আপনি চেষ্টা করেন তবে আপনি ইউবি করেন
জোহানেস স্কাউব -

4
সত্যই, আমি আবার খোলার পক্ষে ভোট দিয়েছি। আমি পার্থক্য ছিল জানার আগে বন্ধ করতে ভোট দিয়েছি।
GManNickG

উত্তর:


24

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

ভাষার সি ++ 11 এবং পরবর্তী সংস্করণগুলিতে autoমূলশব্দটি পুনরায় উদ্দিষ্ট বাছাই করা হয়েছিল যা প্রাথমিকভাবে অবজেক্টের জন্য সিউডো-টাইপ হিসাবে কাজ করবে, যা একটি সংকলক স্বয়ংক্রিয়ভাবে আরম্ভের প্রকাশের ধরণের সাথে প্রতিস্থাপন করবে। সুতরাং, সি ++ 03-এ, ঘোষণাটি: কোনও ব্লক প্রসঙ্গে ব্যবহৃত auto int i=(unsigned char)5;হওয়ার সাথে সমান ছিল int i=5;এবং auto i=(unsigned char)5;এটি সীমাবদ্ধ লঙ্ঘন ছিল। সি ++ 11-এ, এর সমতুল্য হয়ে ওঠে auto int i=(unsigned char)5;এবং সীমাবদ্ধতা লঙ্ঘন auto i=(unsigned char)5;হয় auto unsigned char i=5;


22
শেষ বিটের একটি উদাহরণ কার্যকর হতে পারে।
ডেনিস জিকিফুজ

14
এই উত্তরটি আর সঠিক নয়, ২০১১ সাল থেকে কীওয়ার্ডটি autoসহজেই বাদ দেওয়া যাবে না ... সম্ভবত আপনি নিজের উত্তর আপডেট করতে পারেন।
ওয়াল্টার

4
@ ওয়াল্টার: পরিবর্তিত হয়েছে কি আপনি উদ্ধৃত করতে পারেন? আমি ভাষার সমস্ত পরিবর্তন অনুসরণ করি নি।
সুপারক্যাট

4
@ সুপের্যাট, হ্যাঁ, এই মুহুর্তের জন্য, তবে অবহেলিত registerএবং সি ++ 17 এর জন্য এটি অপসারণের প্রস্তাব থাকবে।
জোনাথন ওয়েকেলি

4
En.cppreferences.com/w/cpp/language/auto এর মতে , সি ++ 11 পোস্টের পোস্টটি autoএখন স্বয়ংক্রিয় টাইপ ছাড়ের জন্য ব্যবহৃত হয় তবে তার আগে এটি নির্দিষ্ট করতে ব্যবহৃত হত যে আপনি নিজের পরিবর্তনশীলটিকে "স্বয়ংক্রিয়ভাবে" সংরক্ষণ করতে চান ( মূলশব্দটির বিপরীতে register(যেমন "প্রসেসরের নিবন্ধ") এর বিপরীতে আমি মনে করি স্ট্যাকের উপরে :
গুইলিউম

96

register সংকলকটির একটি ইঙ্গিত, এটি মেমরির পরিবর্তে প্রসেসরের রেজিস্টারে সেই পরিবর্তনশীলটি সংরক্ষণ করার পরামর্শ দেয় (উদাহরণস্বরূপ, স্ট্যাকের পরিবর্তে)।

সংকলকটি সেই ইঙ্গিতটি অনুসরণ করতে পারে বা নাও করতে পারে।

"কীওয়ার্ডগুলি যেগুলি নয় (বা, অন্য নাম দ্বারা মন্তব্য করা হয়েছে)" তে হার্ব সাটারের মতে :

একজন নিবন্ধকার নির্দিষ্টকরণকারীর একটি অটো স্পেসিফায়ারের মতো একই শব্দার্থবিজ্ঞান রয়েছে ...


4
C ++ 17 যেহেতু, এটি অবচয়, অব্যবহৃত এবং সংরক্ষিত রয়েছে।
ZachB

@ জাচবি, এটি ভুল; রেজিস্টারটি C ++ 17 এ সংরক্ষিত তবে এটি এখনও সি এর রেজিস্টারে প্রায় একইভাবে কাজ করে এবং কার্য করে।
লুইস কেলসি

@ লুইসকেলসি এটি অব্যবহৃত এবং সি ++ ১ 17 টি স্পেসে সংরক্ষিত; এটি storage-class-specifierব্যাকরণের কোনও একটি নয় এবং এর কোনও সংজ্ঞায়িত শব্দার্থবিজ্ঞান নেই। একটি মেনে চলার সংকলক ক্ল্যাংয়ের মতো ত্রুটি ফেলে দিতে পারে। তবুও কিছু বাস্তবায়ন এখনও এটিকে অনুমতি দেয় এবং হয় এটিকে (এমএসভিসি, আইসিসি) উপেক্ষা করে বা এটি একটি অপ্টিমাইজেশন ইঙ্গিত (জিসিসি) হিসাবে ব্যবহার করে। ওপেন- std.org/jtc1/sc22/wg21/docs/papers/2015/p0001r1.html দেখুন । যদিও আমি এক পর্যায়ে ভুল বানান করেছি: এটি সি ++ 11 এ অবচয় করা হয়েছিল।
ZachB


25

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


9

প্রায় অবশ্যই কিছুই।

registerসংকলকটির একটি ইঙ্গিত যা আপনি xপ্রচুর ব্যবহারের পরিকল্পনা করছেন এবং এটি মনে হয় এটি একটি রেজিস্টারে রাখা উচিত।

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



7

registerশব্দ জন্য দরকারী ছিল:

  • ইনলাইন সমাবেশ।
  • বিশেষজ্ঞ সি / সি ++ প্রোগ্রামিং।
  • ক্যাশেবল ভেরিয়েবলের ঘোষণা।

একটি উত্পাদনশীল সিস্টেমের উদাহরণ, যেখানে registerকীওয়ার্ডটির প্রয়োজন ছিল:

typedef unsigned long long Out;
volatile Out out,tmp;
Out register rax asm("rax");
asm volatile("rdtsc":"=A"(rax));
out=out*tmp+rax;

এটি C ++ 11 সাল থেকে অবহেলা করা হয়েছে এবং অব্যবহৃত এবং সি ++ 17 এ সংরক্ষিত রয়েছে ।


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

@ সান্তিয়াগোভিলাফুয়ের্তে আপনি কি উত্তরটি সম্পাদনা করে এটি যুক্ত করতে চান?
এনসি কম্পিউটার 21

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

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

আপনি যে উদাহরণটি দেখিয়েছেন তা হ'ল জিসিসির স্পেসিস্ট রেজিস্টার ভেরিয়েবল এক্সটেনশনটি ব্যবহার করা হচ্ছে যা registerস্টোরেজ ক্লাস নির্দিষ্টকারীর চেয়ে আলাদা এবং এখনও জিসিসি সমর্থন করে।
জ্যাচবি

2

জিসিসি 9.3 পর্যন্ত ব্যবহার সংকলন -std=c++2a, register একটি কম্পাইলার সতর্কবার্তা উৎপন্ন, কিন্তু এটি এখনও সি এর অভিন্নরুপে আকাঙ্ক্ষিত ফল এবং আচরণ করবে হয়েছে registerOfast অপ্টিমাইজেশান পতাকার সম্মান - যখন -O1 ছাড়া সংকলন এই উত্তর। ঝাঁকুনি ++ - 7 ব্যবহারের কারণে তবে একটি সংকলক ত্রুটির কারণ। হ্যাঁ, registerঅপ্টিমাইজেশানগুলি কোনও অপ্টিমাইজেশন-ও পতাকা সহ স্ট্যান্ডার্ড সংকলনটিতে কেবল একটি পার্থক্য রাখে, তবে সেগুলি বেসিক অপটিমেশান যা সংকলকটি -O1 এর সাথেও খুঁজে পাবে।

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

ও -0-তে, আরেকটি পার্থক্য হ'ল জিসিসি const registerসি এবং জিসিসি সি ++ তে একই আচরণ করে না। জিসিসি সি-তে, এর const registerমতো আচরণ করে registerকারণ ব্লক-স্কোপ constগুলি জিসিসিতে অনুকূলিত হয় না। ঝাঁকুনি সি তে, registerকিছুই করে না এবং কেবলমাত্র constব্লক-স্কোপ অপটিমাইজেশন প্রয়োগ হয়। registerজিসিসি সি তে, অপ্টিমাইজেশন প্রয়োগ হয় তবে constব্লক-স্কোপে কোনও অপ্টিমাইজেশন নেই। জিসিসি সি ++ এ, উভয় registerএবং constব্লক-স্কোপ অপটিমাইজেশন একত্রিত।

#include <stdio.h> //yes it's C code on C++
int main(void) {
  const register int i = 3;
  printf("%d", i);
  return 0;
}

int i = 3;:

.LC0:
  .string "%d"
main:
  push rbp
  mov rbp, rsp
  sub rsp, 16
  mov DWORD PTR [rbp-4], 3
  mov eax, DWORD PTR [rbp-4]
  mov esi, eax
  mov edi, OFFSET FLAT:.LC0
  mov eax, 0
  call printf
  mov eax, 0
  leave
  ret

register int i = 3;:

.LC0:
  .string "%d"
main:
  push rbp
  mov rbp, rsp
  push rbx
  sub rsp, 8
  mov ebx, 3
  mov esi, ebx
  mov edi, OFFSET FLAT:.LC0
  mov eax, 0
  call printf
  mov eax, 0
  mov rbx, QWORD PTR [rbp-8] //callee restoration
  leave
  ret

const int i = 3;

.LC0:
  .string "%d"
main:
  push rbp
  mov rbp, rsp
  sub rsp, 16
  mov DWORD PTR [rbp-4], 3 //still saves to stack
  mov esi, 3 //immediate substitution
  mov edi, OFFSET FLAT:.LC0
  mov eax, 0
  call printf
  mov eax, 0
  leave
  ret

const register int i = 3;

.LC0:
  .string "%d"
main:
  push rbp
  mov rbp, rsp
  mov esi, 3 //loads straight into esi saving rbx push/pop and extra indirection (because C++ block-scope const is always substituted immediately into the instruction)
  mov edi, OFFSET FLAT:.LC0 // can't optimise away because printf only takes const char*
  mov eax, 0 //zeroed: https://stackoverflow.com/a/6212755/7194773
  call printf
  mov eax, 0 //default return value of main is 0
  pop rbp //nothing else pushed to stack -- more efficient than leave (rsp == rbp already)
  ret

registerসংস্থাপককে 1 কে বলে) একটি স্থানীয় সঞ্চয়ী ক্যালি সেভ করা রেজিস্টারে সংরক্ষণ করুন rbx, এবং 2) ভেরিয়েবলের ঠিকানা নেওয়া না হলে স্ট্যাক লেখার অনুকূলতা তৈরি করেconstসংকলকটিকে অবিলম্বে মানটির পরিবর্তে (এটি কোনও রেজিস্টার নির্ধারণের পরিবর্তে বা মেমরি থেকে লোড করার পরিবর্তে) পরিবর্তনের জন্য এবং স্থানীয় ভেরিয়েবলটিকে স্ট্যাকের ডিফল্ট আচরণ হিসাবে লিখতে বলে। const registerএই উত্সাহিত অপটিমাইজেশনের সংমিশ্রণ। এটি যতটা পাতলা হয় ততটাই পাতলা।

এছাড়াও, জিসিসি সি এবং সি ++ এ, registerনিজের থেকে স্ট্যাকের প্রথম স্থানীয় লোকের জন্য স্ট্যাকের মধ্যে একটি এলোমেলো 16 বাইট ফাঁক তৈরি করে বলে মনে হচ্ছে যা এর সাথে ঘটে না const register

-ওফেষ্ট ব্যবহার করে সংকলন; register০ টি অপ্টিমাইজেশান প্রভাব রয়েছে কারণ এটি যদি একটি রেজিস্টারে রাখা বা তাত্ক্ষণিকভাবে তৈরি করা যায় তবে এটি সর্বদা থাকবে এবং যদি তা নাও হয়; constএখনও সি এবং সি ++ এ লোডটি অপ্টিমাইজ করে তবে কেবল ফাইল স্কোপে ; volatileএখনও মানগুলি স্ট্যাক থেকে সংরক্ষণ এবং লোড করতে বাধ্য করে।

.LC0:
  .string "%d"
main:
  //optimises out push and change of rbp
  sub rsp, 8 //https://stackoverflow.com/a/40344912/7194773
  mov esi, 3
  mov edi, OFFSET FLAT:.LC0
  xor eax, eax //xor 2 bytes vs 5 for mov eax, 0
  call printf
  xor eax, eax
  add rsp, 8
  ret

1

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

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

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