সি-তে, কোনও এই জাতীয় ঘোষণায় স্ট্রিং আক্ষরিক ব্যবহার করতে পারে:
char s[] = "hello";
বা এই মত:
char *s = "hello";
তাহলে পার্থক্য টা কি? সংকলন এবং রান সময় উভয় সময়ে সঞ্চয়স্থানের সময়কালের ক্ষেত্রে আসলে কী ঘটে তা আমি জানতে চাই।
সি-তে, কোনও এই জাতীয় ঘোষণায় স্ট্রিং আক্ষরিক ব্যবহার করতে পারে:
char s[] = "hello";
বা এই মত:
char *s = "hello";
তাহলে পার্থক্য টা কি? সংকলন এবং রান সময় উভয় সময়ে সঞ্চয়স্থানের সময়কালের ক্ষেত্রে আসলে কী ঘটে তা আমি জানতে চাই।
উত্তর:
পার্থক্য এখানে
char *s = "Hello world";
স্থাপন করবে "Hello world"
মধ্যে মেমরি শুধুমাত্র পাঠযোগ্য অংশের , এবং উপার্জন s
একটি পয়েন্টার যে এই মেমরিতে কোনো লেখা অপারেশন অবৈধ তোলে।
করার সময়:
char s[] = "Hello world";
আক্ষরিক স্ট্রিংটি কেবল পঠনযোগ্য মেমরিতে রাখে এবং স্ট্রিকে নতুন বরাদ্দকৃত মেমরিতে স্ট্রিংটি অনুলিপি করে। এইভাবে তৈরি
s[0] = 'J';
আইনগত।
"Hello world"
উভয় উদাহরণে "মেমরির কেবল পঠনযোগ্য অংশগুলিতে" রয়েছে। সেখানে অ্যারে পয়েন্টগুলির সাথে উদাহরণটি, অ্যারের সাথে উদাহরণটি অ্যারে উপাদানগুলিতে অক্ষরগুলি অনুলিপি করে।
char msg[] = "hello, world!";
প্রাথমিক পর্যায়ে থাকা বিভাগে শেষ হয়ে একটি ফাইলের একটি পরিষ্কার সংকলন পেয়েছি । যখন char * const
কেবলমাত্র পঠনযোগ্য ডেটা বিভাগে শেষ হওয়ার ঘোষণা দেওয়া হয়। gcc-4.5.3
প্রথম প্রথম, ফাংশন আর্গুমেন্ট এ, তারা ঠিক সমতুল্য:
void foo(char *x);
void foo(char x[]); // exactly the same in all respects
অন্যান্য প্রসঙ্গে, একটি বিন্যাস বরাদ্দ করার char *
সময় একটি পয়েন্টার char []
বরাদ্দ করে। আগের ক্ষেত্রে স্ট্রিংটি কোথায় যায়, আপনি জিজ্ঞাসা করেন? সংকলকটি গোপনে স্ট্রিং আক্ষরিক ধরে রাখতে স্থির বেনামে অ্যারে বরাদ্দ করে। তাই:
char *x = "Foo";
// is approximately equivalent to:
static const char __secret_anonymous_array[] = "Foo";
char *x = (char *) __secret_anonymous_array;
মনে রাখবেন যে আপনাকে এই বেনামে অ্যারের সামগ্রীগুলি এই পয়েন্টারটির মাধ্যমে কখনও পরিবর্তন করার চেষ্টা করতে হবে না; প্রভাবগুলি অপরিশোধিত (প্রায়শই ক্রাশের অর্থ):
x[1] = 'O'; // BAD. DON'T DO THIS.
অ্যারে সিনট্যাক্স ব্যবহার করে এটি সরাসরি নতুন স্মৃতিতে বরাদ্দ করে। সুতরাং পরিবর্তনটি নিরাপদ:
char x[] = "Foo";
x[1] = 'O'; // No problem.
তবে অ্যারে কেবল তার সংশ্লেষের সুযোগ হিসাবে দীর্ঘকাল বেঁচে থাকে, সুতরাং আপনি যদি কোনও ফাংশনে এটি করেন তবে ফিরে বা এই অ্যারেটিতে কোনও পয়েন্টার ফাঁস করবেন না - এর পরিবর্তে strdup()
বা অনুরূপ একটি অনুলিপি তৈরি করুন । অ্যারেটি যদি বিশ্বব্যাপী সুযোগে বরাদ্দ করা হয় তবে অবশ্যই কোনও সমস্যা নেই।
এই ঘোষণা:
char s[] = "hello";
একটি অবজেক্ট তৈরি করে - char
size আকারের অ্যারে, বলা হয়s
হয় মানগুলির সাথে আরম্ভ করা 'h', 'e', 'l', 'l', 'o', '\0'
। এই অ্যারেটি কোথায় মেমোরিতে বরাদ্দ করা হয় এবং এটি কতক্ষণ বাঁচে তা নির্ভর করে যেখানে ঘোষণাটি প্রদর্শিত হবে appears যদি ঘোষণাটি কোনও ফাংশনের মধ্যে থাকে তবে এটি যে ব্লকটিতে ঘোষণা করা হয়েছে তার শেষ অবধি এটি বেঁচে থাকবে এবং প্রায় অবশ্যই স্ট্যাকের জন্য বরাদ্দ দেওয়া হবে; যদি এটি কোনও ফাংশনের বাইরে থাকে তবে সম্ভবত এটি একটি "আরম্ভিত ডেটা বিভাগ" এর মধ্যে সংরক্ষণ করা হবে যা প্রোগ্রামটি চালিত হওয়ার পরে এক্সিকিউটেবল ফাইল থেকে লেখার যোগ্য মেমরিতে লোড করা হয়।
অন্যদিকে, এই ঘোষণা:
char *s ="hello";
তৈরি করা হয় দুটি বস্তু করে:
char
মানগুলি রয়েছে গুলি 'h', 'e', 'l', 'l', 'o', '\0'
, যা কোন নাম আছে এবং আছে স্থিতিশীল স্টোরেজ সময়কাল (অর্থাত্ এটি প্রোগ্রামের পুরো জীবন ধরে বেঁচে থাকে); এবংs
, যা নামবিহীন, কেবল পঠনযোগ্য অ্যারেতে প্রথম অক্ষরের অবস্থানের সাথে সূচনা করা হয়।নামবিহীন পঠনযোগ্য কেবল অ্যারে সাধারণত প্রোগ্রামটির "পাঠ্য" বিভাগে অবস্থিত, যার অর্থ এটি কোডের সাথে ডিস্ক থেকে কেবল পঠনযোগ্য মেমরিতে লোড হয়। s
মেমোরিতে পয়েন্টার ভেরিয়েবলের অবস্থান নির্ভর করে যেখানে ঘোষণাটি প্রদর্শিত হবে (ঠিক প্রথম উদাহরণের মতো)।
char s[] = "hello"
, এটি "hello"
কেবলমাত্র একটি আরম্ভকারী যা সংকলককে বলছে অ্যারে কীভাবে আরম্ভ করা উচিত। এটি পাঠ্য বিভাগে সংশ্লিষ্ট স্ট্রিংয়ের ফলস্বরূপ বা নাও হতে পারে - উদাহরণস্বরূপ, যদি s
স্ট্যাটিক স্টোরেজ সময়কাল থাকে তবে সম্ভবত এটির একমাত্র উদাহরণটি "hello"
আরম্ভকৃত ডেটা বিভাগে থাকবে - অবজেক্টটি s
নিজেই। এমনকি যদি s
স্বয়ংক্রিয় স্টোরেজ সময়কাল থাকে, তবে এটি অনুলিপি (উদাহরণস্বরূপ movl $1819043176, -6(%ebp); movw $111, -2(%ebp)
) পরিবর্তে আক্ষরিক স্টোরের ক্রম দ্বারা সূচনা করা যেতে পারে ।
.rodata
, যা লিঙ্কার স্ক্রিপ্টটি একই বিভাগে ফেলে দেয় .text
। আমার উত্তর দেখুন ।
char s[] = "Hello world";
আক্ষরিক স্ট্রিংটি কেবল পঠনযোগ্য মেমরিতে রাখে এবং স্ট্রিকে নতুন বরাদ্দ মেমরিতে স্ট্রিংটি অনুলিপি করে। কিন্তু আপনার উত্তর শুধুমাত্র শুধুমাত্র পাঠযোগ্য মেমরি আক্ষরিক স্ট্রিং করা সম্পর্কে কথা বলে এবং বাক্য যা বলে দ্বিতীয় অংশ অগ্রাহ্য: copies the string to newly allocated memory on the stack
। সুতরাং, আপনার উত্তরটি দ্বিতীয় অংশটি নির্দিষ্ট না করার জন্য অসম্পূর্ণ?
char s[] = "Hellow world";
কেবলমাত্র একটি আরম্ভকারী এবং এটি পৃথক পঠনযোগ্য কেবল অনুলিপি হিসাবে সংরক্ষণ করা হয় না। যদি s
স্ট্যাটিক স্টোরেজ সময়কাল থাকে তবে স্ট্রিংয়ের একমাত্র অনুলিপিটি সম্ভবত অবস্থানে অবস্থিত একটি পঠন-লেখার অংশে থাকতে s
পারে এবং তা না হলেও সংকলক অনুলিপি না করে লোড-তাত্ক্ষণিক নির্দেশাবলী বা অনুরূপের সাথে অ্যারে আরম্ভ করতে বেছে নিতে পারে কেবল পঠনযোগ্য স্ট্রিং থেকে। মুল বক্তব্যটি এই ক্ষেত্রে, আরম্ভকারী স্ট্রিংয়ের নিজেই কোনও রানটাইম উপস্থিতি নেই।
ঘোষণা দেওয়া
char *s0 = "hello world";
char s1[] = "hello world";
নিম্নলিখিত অনুমানের মেমরি মানচিত্র ধরুন:
0x01 0x02 0x03 0x04 0x00008000: 'এইচ' 'ই' 'ল' 'এল' 0x00008004: 'ও' '' 'ডাব্লু' 'ও' 0x00008008: 'r' 'l' 'd' 0x00 ... s0: 0x00010000: 0x00 0x00 0x80 0x00 এস 1: 0x00010004: 'এইচ' 'ই' 'ল' 'এল' 0x00010008: 'ও' '' 'ডাব্লু' 'ও' 0x0001000C: 'r' 'l' 'd' 0x00
স্ট্রিং আক্ষরিক "hello world"
একটি 12-উপাদান অ্যারের char
( const char
সি ++ এ) স্থির স্টোরেজ সময়কাল সহ, যখন প্রোগ্রামটি শুরু হয় এবং প্রোগ্রামটি শেষ না হওয়া অবধি বরাদ্দ থাকে তখন এর জন্য মেমরি বরাদ্দ করা হয়। একটি স্ট্রিং আক্ষরিক বিষয়বস্তু সংশোধন করার চেষ্টা অনির্ধারিত আচরণ ডাকে।
লাইন
char *s0 = "hello world";
অটো স্টোরেজ সময়কাল সহ s0
একটি পয়েন্টার হিসাবে সংজ্ঞায়িত করে char
(যার অর্থ পরিবর্তনশীল s0
কেবলমাত্র এটি ঘোষিত স্কোপের জন্য বিদ্যমান) এবং এতে স্ট্রিংয়ের ঠিকানাটি ( 0x00008000
এই উদাহরণে) অনুলিপি করে । নোট যে যেহেতু s0
একটি স্ট্রিং আক্ষরিক পয়েন্ট, এটা (যেমন, কোনো ফাংশন যা এটি পরিবর্তন করার চেষ্টা করবে একটি আর্গুমেন্ট হিসাবে ব্যবহার করা উচিত নয় strtok()
, strcat()
, strcpy()
, ইত্যাদি)।
লাইন
char s1[] = "hello world";
অটো স্টোরেজ সময়কাল সহ s1
12-উপাদান অ্যারের char
(দৈর্ঘ্যটি স্ট্রিং আক্ষরিক থেকে নেওয়া হয়) হিসাবে সংজ্ঞায়িত করে এবং আক্ষরিকের সামগ্রীগুলি অ্যারেতে অনুলিপি করে । আপনি মেমরির মানচিত্র থেকে দেখতে পাচ্ছেন, আমাদের কাছে স্ট্রিংয়ের দুটি অনুলিপি রয়েছে "hello world"
; পার্থক্যটি হ'ল আপনি এতে থাকা স্ট্রিংটি সংশোধন করতে পারেন s1
।
s0
এবং s1
বেশিরভাগ প্রসঙ্গেই বিনিময়যোগ্য; ব্যতিক্রম এখানে:
sizeof s0 == sizeof (char*)
sizeof s1 == 12
type of &s0 == char **
type of &s1 == char (*)[12] // pointer to a 12-element array of char
আপনি ভেরিয়েবলটিকে আবার s0
ভিন্ন ভিন্ন স্ট্রিংকে আক্ষরিক বা অন্য ভেরিয়েবলের দিকে নির্দেশ করতে পারেন। আপনি s1
ভিন্ন অ্যারেতে নির্দেশ করতে ভেরিয়েবলটি পুনরায় নিয়োগ করতে পারবেন না ।
C99 N1256 খসড়া
অক্ষর স্ট্রিং আক্ষরিক দুটি ভিন্ন ব্যবহার আছে:
আরম্ভ করুন char[]
:
char c[] = "abc";
এটি "আরও যাদু" এবং 6..7.৮ / ১৪ "ইনিশিয়ালাইজেশন" এ বর্ণিত:
অক্ষর ধরণের একটি অ্যারে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে সংক্ষেপিত বন্ধনী দ্বারা আরম্ভ করা যেতে পারে। অক্ষরের স্ট্রিং আক্ষরিকের ধারাবাহিক অক্ষর (ঘর থাকলে অবিরাম আকারে টার্মিনেটিং নাল চরিত্র সহ) অ্যারের উপাদানগুলির সূচনা করে।
সুতরাং এটি কেবল একটি শর্টকাট:
char c[] = {'a', 'b', 'c', '\0'};
অন্য কোনও নিয়মিত অ্যারের মতো, c
পরিবর্তন করা যেতে পারে।
অন্য যে কোনও জায়গায়: এটি একটি উত্পন্ন করে:
সুতরাং আপনি যখন লিখুন:
char *c = "abc";
এটি এর অনুরূপ:
/* __unnamed is magic because modifying it gives UB. */
static char __unnamed[] = "abc";
char *c = __unnamed;
নোট থেকে অন্তর্নিহিত ঢালাই char[]
করার char *
, যা সবসময় বৈধ।
তারপরে আপনি যদি সংশোধন করেন c[0]
, __unnamed
আপনিও সংশোধন করুন , যা ইউবি।
এটি 6.4.5 "স্ট্রিং লিটারালস" এ নথিভুক্ত করা হয়েছে:
5 অনুবাদ পর্বে 7 এ, বাইট বা মান শূন্যের কোডটি প্রতিটি মাল্টবাইট চরিত্রের অনুক্রমের সাথে যুক্ত হয় যা স্ট্রিং আক্ষরিক বা আক্ষরিক থেকে ফলাফল। মাল্টিবাইট চরিত্রের সিক্যুয়েন্সটি পরে স্থির স্টোরেজ সময়কাল এবং সিক্যুয়েন্সটি পর্যাপ্ত রাখার জন্য যথেষ্ট দৈর্ঘ্যের একটি অ্যারে শুরু করতে ব্যবহৃত হয়। চরিত্রের স্ট্রিং লিটারালগুলির জন্য, অ্যারের উপাদানগুলিতে টাইপ চর থাকে এবং মাল্টিবাইট অক্ষর ক্রমের পৃথক বাইটগুলির সাথে আরম্ভ করা হয় [...]
These এই অ্যারেগুলি পৃথক পৃথক কিনা তাদের উপাদানগুলির উপযুক্ত মান রয়েছে কিনা তা অনির্দিষ্ট। প্রোগ্রামটি যদি এমন অ্যারে সংশোধন করার চেষ্টা করে তবে আচরণটি সংজ্ঞায়িত।
Initial.7.৮ / 32 "ইনিশিয়ালাইজেশন" এর প্রত্যক্ষ উদাহরণ দেয়:
উদাহরণ 8: ঘোষণা
char s[] = "abc", t[3] = "abc";
"প্লেইন" চর অ্যারে অবজেক্টগুলি সংজ্ঞায়িত করে
s
এবংt
যার উপাদানগুলি অক্ষর স্ট্রিং ল্যাটারাল দিয়ে শুরু করা হয়।এই ঘোষণাটি সমান
char s[] = { 'a', 'b', 'c', '\0' }, t[] = { 'a', 'b', 'c' };
অ্যারের সামগ্রীগুলি পরিবর্তনযোগ্য if অন্যদিকে, ঘোষণা
char *p = "abc";
p
"পয়েন্টার টু চর" টাইপ দিয়ে সংজ্ঞায়িত করে এবং এটি দৈর্ঘ্য 4 দিয়ে "চরের অ্যারে" টাইপযুক্ত কোনও বস্তুর দিকে নির্দেশ করতে ইনিশিয়ালাইজ করে যার উপাদানগুলি একটি অক্ষর স্ট্রিং আক্ষরিক দিয়ে প্রাথমিক হয়।p
অ্যারের বিষয়বস্তুগুলি সংশোধন করার জন্য যদি চেষ্টা করা হয় , তবে আচরণটি সংজ্ঞায়িত।
জিসিসি 4.8 x86-64 ELF বাস্তবায়ন
কার্যক্রম:
#include <stdio.h>
int main(void) {
char *s = "abc";
printf("%s\n", s);
return 0;
}
সংকলন এবং পচনশীল:
gcc -ggdb -std=c99 -c main.c
objdump -Sr main.o
আউটপুট রয়েছে:
char *s = "abc";
8: 48 c7 45 f8 00 00 00 movq $0x0,-0x8(%rbp)
f: 00
c: R_X86_64_32S .rodata
উপসংহার: জিসিসি char*
এটিকে .rodata
বিভাগে রাখে, না .text
।
তবে খেয়াল করুন যে ডিফল্ট লিঙ্কার স্ক্রিপ্টটি একই বিভাগে রাখে .rodata
এবং এতে লেখার অনুমতি নেই। এটি দিয়ে পর্যবেক্ষণ করা যেতে পারে:.text
readelf -l a.out
যেটা বহন করে:
Section to Segment mapping:
Segment Sections...
02 .text .rodata
আমরা যদি এর জন্য একই করি char[]
:
char s[] = "abc";
আমরা প্রাপ্ত:
17: c7 45 f0 61 62 63 00 movl $0x636261,-0x10(%rbp)
সুতরাং এটি স্ট্যাকের মধ্যে (আপেক্ষিক %rbp
) সংরক্ষণ করা হয়।
char s[] = "hello";
প্রাথমিকের (5 + 1 গুলি) ধরে রাখার জন্য যথেষ্ট দীর্ঘ s
এবং একটি অ্যারে হিসাবে ঘোষিত হয় এবং প্রদত্ত স্ট্রিংয়ের সদস্যদের অ্যারেতে অনুলিপি করে অ্যারে আরম্ভ করে।char
char
char *s = "hello";
s
এক বা একাধিক (এই ক্ষেত্রে আরও) char
এর পয়েন্টার হিসাবে ঘোষণা করে এবং এটি সরাসরি আক্ষরিক সমন্বিত একটি নির্দিষ্ট (কেবলমাত্র পঠনযোগ্য) অবস্থানের দিকে নির্দেশ করে "hello"
।
s
একটি পয়েন্টার const char
।
char s[] = "Hello world";
এখানে s
একটি অক্ষরের অ্যারে রয়েছে, যা আমরা চাইলে ওভাররাইট করা যেতে পারে।
char *s = "hello";
এই পয়েন্টারটি s
নির্দেশ করে মেমরির কোথাও এই অক্ষর ব্লক তৈরি করতে একটি স্ট্রিং আক্ষরিক ব্যবহৃত হয়। আমরা এখানে এটি পরিবর্তন করে অবজেক্টের দিকে নির্দেশ করতে পারি, তবে যতক্ষণ না এটি একটি স্ট্রিংকে আক্ষরিক অর্থে অক্ষরের ব্লকটি চিহ্নিত করা যেতে পারে যা এটি পরিবর্তন করতে পারে না।
সংযোজন হিসাবে, বিবেচনা করুন যে, কেবলমাত্র পঠনের উদ্দেশ্যে উভয়ের ব্যবহার একরকম, আপনি উভয়কে
ফর্ম্যাট করে []
বা *(<var> + <index>)
ফর্ম্যাট করে একটি চর অ্যাক্সেস করতে পারেন :
printf("%c", x[1]); //Prints r
এবং:
printf("%c", *(x + 1)); //Prints r
স্পষ্টতই, আপনি যদি চেষ্টা করার চেষ্টা করেন
*(x + 1) = 'a';
আপনি কেবলমাত্র পঠনযোগ্য মেমরিটিতে অ্যাক্সেস করার চেষ্টা করছেন আপনি সম্ভবত সেগমেন্টেশন ফল্ট পাবেন।
x[1] = 'a';
কোনওভাবেই সেগফল্ট হিসাবে পৃথক হবে না (প্ল্যাটফর্মের উপর নির্ভর করে অবশ্যই)।
char *str = "Hello";
উপরের সেটগুলি অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে চিহ্নিত করা হয়েছে যা এই স্ট্রিং আক্ষরিক কোনও পরিবর্তন অবৈধ এবং এর ফলে বিভাজন ত্রুটি ঘটবে।
char str[] = "Hello";
স্ট্যাকের নতুন বরাদ্দ হওয়া মেমরিতে স্ট্রিংটি অনুলিপি করে। সুতরাং এতে কোনও পরিবর্তন আনার অনুমতি এবং আইনী is
means str[0] = 'M';
আরআরটি "মেলো" তে পরিবর্তন করবে।
আরও তথ্যের জন্য, অনুরূপ প্রশ্নের মাধ্যমে যান:
এর ব্যাপারে:
char *x = "fred";
এক্স হল একটি মূল্যবান - এটি নির্ধারিত হতে পারে। তবে এর ক্ষেত্রে:
char x[] = "fred";
এক্স কোনও মূল্য নয়, এটি একটি মূল্য - আপনি এটি বরাদ্দ করতে পারবেন না assign
x
এটি একটি অ-সংশোধনযোগ্য লভ্যালু। যদিও প্রায় সমস্ত প্রসঙ্গে, এটি তার প্রথম উপাদানটির একটি পয়েন্টারকে মূল্যায়ন করবে এবং সেই মানটি একটি মূল্য val
এখানে মন্তব্যের আলোকে এটি সুস্পষ্ট হওয়া উচিত: চর * এস = "হ্যালো"; একটি খারাপ ধারণা, এবং খুব সংকীর্ণ সুযোগে ব্যবহার করা উচিত।
"দৃ const় সংশোধন" একটি "ভাল জিনিস" এটি উল্লেখ করার জন্য এটি একটি ভাল সুযোগ হতে পারে। আপনি যখনই এবং যেখানেই পারেন, আপনার কোডটি সুরক্ষিত করতে "কনস্ট" কীওয়ার্ডটি ব্যবহার করুন, "রিলাক্সড" কলার বা প্রোগ্রামারদের থেকে, যা পয়েন্টারগুলি খেলায় আসে যখন সাধারণত বেশিরভাগ "রিলাক্সড" হয়।
পর্যাপ্ত মেলোড্রামা, "কনস্ট" এর সাথে শোভাকর পয়েন্টারগুলি যখন কেউ অর্জন করতে পারে তা এখানে। (দ্রষ্টব্য: একজনকে ডান থেকে বামে পয়েন্টার ঘোষণাগুলি পড়তে হবে)) পয়েন্টারগুলির সাথে খেললে নিজেকে রক্ষা করার জন্য এখানে 3 টি ভিন্ন উপায়:
const DBJ* p means "p points to a DBJ that is const"
- অর্থাৎ, ডিবিজে অবজেক্টটি পি এর মাধ্যমে পরিবর্তন করা যায় না।
DBJ* const p means "p is a const pointer to a DBJ"
- অর্থাৎ, আপনি পি এর মাধ্যমে ডিবিজে অবজেক্ট পরিবর্তন করতে পারেন, তবে আপনি পয়েন্টার পি নিজেই পরিবর্তন করতে পারবেন না।
const DBJ* const p means "p is a const pointer to a const DBJ"
- অর্থাৎ, আপনি পয়েন্টার পি নিজেই পরিবর্তন করতে পারবেন না, আপনি পি এর মাধ্যমে ডিবিজে অবজেক্টও পরিবর্তন করতে পারবেন না।
চেষ্টা করা কনস্ট-পিঁপড়া পরিবর্তনের সাথে সম্পর্কিত ত্রুটিগুলি সংকলন সময়ে ধরা পড়ে। কনস্টের জন্য কোনও রানটাইম স্পেস বা স্পিড পেনাল্টি নেই।
(অনুমান যে আপনি অবশ্যই সি ++ সংকলক ব্যবহার করছেন?)
--DBJ