নিবন্ধক কীওয়ার্ডটি আসলে সি তে কখন কার্যকর হয়?


10

আমি registerসি তে কীওয়ার্ড ব্যবহার সম্পর্কে বিভ্রান্ত হয়ে পড়েছি সাধারণত বলা হয় স্ট্যাকওভারফ্লোতে এই প্রশ্নের মতো এর ব্যবহারের দরকার নেই ।

এই কিওয়ার্ডটি কি আধুনিক কম্পাইলারগুলির কারণে সিতে সম্পূর্ণ অপ্রয়োজনীয় বা এমন পরিস্থিতি রয়েছে যা এটি এখনও কার্যকর হতে পারে? যদি হ্যাঁ, কিছু পরিস্থিতিতে কী registerকীওয়ার্ড ব্যবহার করা আসলে সহায়ক?


4
আমি মনে করি এটি লিঙ্কিত প্রশ্ন এবং এর উত্তরগুলি এখানে আপনি আশা করতে পারেন একই। সুতরাং এখানে কোনও নতুন তথ্য পাবেন না।
উয়ে প্লোনাস

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

আমি মনে করি constকীওয়ার্ডটি রেজিস্ট্রারের বিপরীতে আলাদা কিছু।
উয়ে প্লোনাস

4
আপনি যদি দুর্ঘটনাক্রমে সময়মতো ফিরে যান এবং প্রারম্ভিক সি সংকলকগুলির মধ্যে একটি ব্যবহার করতে বাধ্য হন তবে এটি কার্যকর। এটি মোটেই কার্যকর নয়, বছরের পর বছর এটি সম্পূর্ণ অপ্রচলিত।
জনবি

@ উয়েপ্লোনাস আমি কেবল বুঝিয়েছি যে আমার কাছে এমন কিছু পরিস্থিতি অজানা থাকতে পারে যাতে কোনও কীওয়ার্ড কার্যকর হতে পারে।
অসীম বানসাল

উত্তর:


11

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


9
এর চেয়েও বড় কথা, এটি প্রায় সবসময়ই
সংকলকটি

6
@ জোজেফগ: আরও খারাপ। আপনি এই ঝুঁকিটি চালান যে সংকলক আপনার অনুরোধ / ইঙ্গিতটিকে সম্মান করে এবং ফলস্বরূপ আরও খারাপ কোড তৈরি করে ।
বার্ট ভ্যান ইনজেন শেেনা

9

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

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

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

আবার, মনে রাখবেন যে উপরোক্ত বিবরণটি অব্যর্থহিত কোডের জন্য প্রযোজ্য ।


6

আপনি মূলত সংকলককে বলুন যে আপনি ভেরিয়েবলের ঠিকানা নেবেন না এবং সংকলকটি অবশ্যই আরও অনুকূলিতকরণ করতে পারে। আমি যতদূর জানি, আধুনিক সংকলকরা কোনও ভেরিয়েবলটিকে একটি রেজিস্টারে রাখা উচিত কিনা তা নির্ধারণ করতে বেশ সক্ষম।

উদাহরণ:

int main(){
        int* ptr;
        int a;
        register int b;
        ptr = &a;
        ptr = &b; //this won't compile
        return 0;
} 

সম্মতি বা ঠিকানা নিবেন?
স্পষ্টভাবে

@ তাত্পর্যপূর্ণ: আপনি অবশ্যই সঠিক
লুকাস

0

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

সংক্ষেপে, আপনি যদি 64-বিট এক্স 86 বা এআরএম চিপে থাকেন তবে বাস্তবে কী চলছে তা নির্ধারণ করতে আপনার কিছুটা সময় লাগবে। আপনি যদি 16-বিট এমবেডড সিপিইউতে থাকেন তবে এটি সম্ভবত আপনাকে কিছু পেতে পারে। তবে, বেশিরভাগ ছোট এমবেডেড চিপগুলি সমালোচনামূলকভাবে কোনও সময় চালায় না - আপনার মাইক্রোওয়েভ ওভেন আপনার টাচপ্যাডকে সেকেন্ডে 10,000 বার স্যাম্পল করছে - যা 4Mhz সিপিইউতে স্ট্রেন করে।


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

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

1
"কেবলমাত্র একটি দ্রুত চিপ পাওয়া এবং পণ্যটি দরজা থেকে সরিয়ে নেওয়া" সর্বদা সম্ভব নয়। রিয়েল-টাইম চিত্র প্রক্রিয়াকরণ বিবেচনা করুন। 640x480 পিক্সেল / ফ্রেম এক্স 60 ফ্রেম / সেকেন্ড এক্স এন নির্দেশাবলী প্রতি পিক্সেল দ্রুত যুক্ত করে। (রিয়েল-টাইম চিত্র প্রক্রিয়াকরণের পাঠটি হ'ল যে আপনি আপনার পিক্সেল কার্নেলের উপর রক্ত ​​ঘামছেন এবং আপনি কেবল সমস্ত কিছু উপেক্ষা করছেন, কারণ এটি প্রতি লাইনে একবার বা একবার প্যাচ প্রতি একবার বা ফ্রেমে প্রতি একবার সঞ্চালিত হয়, প্রতি লাইন প্রতি শত শত বার বিপরীতে বা প্যাচ বা দশক বা কয়েক ফ্রেমে কয়েক হাজার বার))
জন আর স্ট্রোহম

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

-3

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

/* reg_or_not.c */  

#include <stdio.h>
#include <time.h>
#include <stdlib> //not requiered for Linux
#define LAPSb 50
#define LAPS 50000
#define MAXb 50
#define MAX 50000


int main (void)
{
/* 20 ints and 2 register ints */   

register int k,l;
int a,aa,b,bb,c,cc,d,dd,e,ee,f,ff,g,gg,h,hh,i,ii,j,jj;


/* measure some ticks also */  

clock_t start_1,start_2; 
clock_t finish_1,finish_2;
long tmp; //just for the workload 


/* pointer declarations of all ints */

int *ap, *aap, *bp, *bbp, *cp, *ccp, *dp, *ddp, *ep, *eep;
int *fp, *ffp, *gp, *ggp, *hp, *hhp, *ip, *iip, *jp, *jjp;
int *kp,*lp;

/* end of declarations */
/* read memory addresses, if possible - which can't be done in a CPU-register */     

ap=&a; aap=&aa; bp=&b; bbp=&bb;
cp=&c; ccp=&cc; dp=&d; ddp=&dd;
ep=&e; eep=&ee; fp=&f; ffp=&ff;
gp=&g; ggp=&gg; hp=&h; hhp=&hh;
ip=&i; iip=&ii; jp=&j; jjp=&jj;

//kp=&k;  //won't compile if k is stored in a CPU register  
//lp=&l;  //same - but try both ways !


/* what address , isn't the issue in this case - but if stored in memory    some "crazy" number will be shown, whilst CPU-registers can't be read */

printf("Address a aa: %u     %u\n",a,aa);
printf("Address b bb: %u     %u\n",b,bb);
printf("Address c cc: %u     %u\n",c,cc);
printf("Address d dd: %u     %u\n",d,dd);
printf("Address e ee: %u     %u\n",e,ee);
printf("Address f ff: %u     %u\n",f,ff);
printf("Address g gg: %u     %u\n",g,gg);
printf("Address h hh: %u     %u\n",h,hh);
printf("Address i ii: %u     %u\n",i,ii);
printf("Address j jj: %u     %u\n\n",j,jj);

//printf("Address k:  %u \n",k); //no reason to try "k" actually is in a CPU-register 
//printf("Address l:  %u \n",l); 


start_2=clock(); //just for fun      

/* to ensure workload */
for (a=1;a<LAPSb;a++) {for (aa=0;aa<MAXb;aa++);{tmp+=aa/a;}}
for (b=1;b<LAPSb;b++) {for (bb=0;bb<MAXb;bb++);{tmp+=aa/a;}}
for (a=1;c<LAPSb;c++) {for (cc=0;cc<MAXb;cc++);{tmp+=bb/b;}}
for (d=1;d<LAPSb;d++) {for (dd=0;dd<MAXb;dd++);{tmp+=cc/c;}}
for (e=1;e<LAPSb;e++) {for (ee=0;ee<MAXb;ee++);{tmp+=dd/d;}}
for (f=1;f<LAPSb;f++) {for (ff=0;ff<MAXb;ff++);{tmp+=ee/e;}}
for (g=1;g<LAPSb;g++) {for (gg=0;gg<MAXb;gg++);{tmp+=ff/f;}}
for (h=1;h<LAPSb;h++) {for (hh=0;hh<MAXb;hh++);{tmp+=hh/h;}}
for (jj=1;jj<LAPSb;jj++) {for (ii=0;ii<MAXb;ii++);{tmp+=ii/jj;}}

start_1=clock(); //see following printf
for (i=0;i<LAPS;i++) {for (j=0;j<MAX;j++);{tmp+=j/i;}} /* same double   loop - in supposed memory */
finish_1=clock(); //see following printf

printf ("Memory: %ld ticks\n\n", finish_1 - start_1); //ticks for memory

start_1=clock(); //see following printf
for (k=0;k<LAPS;k++) {for (l=0;l<MAX;l++);{tmp+=l/k;}}  /* same double       loop - in supposed register*/
finish_1=clock(); //see following printf     

printf ("Register: %ld ticks\n\n", finish_1 - start_1); //ticks for CPU register (?) any difference ?   

finish_2=clock();

printf ("Total: %ld ticks\n\n", finish_2 - start_2); //really for fun only           

system("PAUSE"); //only requiered for Windows, so the CMD-window doesn't vanish     

return 0;

} 

উপরে শূন্যের সাথে একটি বিভাগ থাকবে, দয়া করে please tmp + = ii / jj;} থেকে {tmp + = jj / ii; change পরিবর্তন করুন - এর জন্য সত্যই দুঃখিত
জন পি এরিকসন

কে এবং আমি 1 দিয়ে শুরু করি - শূন্য নয়। খুব দুঃখিত.
জন পি এরিকসন

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