X [0]! = X [0] [0]! = X [0] [0] [0] কেন?


149

আমি কিছুটা সি ++ অধ্যয়ন করছি এবং আমি পয়েন্টারগুলির সাথে লড়াই করছি। আমি বুঝতে পারি যে আমি ঘোষণা করে আমার 3 স্তরের পয়েন্টার থাকতে পারে:

int *(*x)[5];

সুতরাং এটি *x5 টি উপাদানগুলির একটি অ্যারেরের পয়েন্টার যা পয়েন্টার int। এছাড়াও আমি জানি x[0] = *(x+0);, x[1] = *(x+1)এবং আরও ....

সুতরাং, উপরোক্ত ঘোষণা দেওয়া, কেন হয় x[0] != x[0][0] != x[0][0][0]?


58
x[0], x[0][0]এবং x[0][0][0]বিভিন্ন ধরণের আছে। তাদের তুলনা করা যায় না। আপনি কি বলতে চাইছেন !=?
বলভ

4
@celticminstrel এগুলি এক নয়: int **x[5]5 টি উপাদানের অ্যারে। একটি উপাদান হ'ল ইন্টু
তে

5
@celticminstrel হ'ল int** x[5]পাঁচটি পয়েন্টারের বিন্যাস যা বিন্দুতে বিন্দুতে বিন্দুতে নির্দেশ করে। int *(*x)[5]পাঁচটি পয়েন্টারের একটি অ্যারেরের পয়েন্টার যা আন্তঃ বিন্দুতে নির্দেশ করে।
Emlai

5
@celticminstrel ডান-বাম শাসন , spirale নিয়ম , সি অর্থহীন ↔ ইংরেজি একটি হয়ে উঠছে এবং আপনার 'আপনার পথে তিন তারকা প্রোগ্রামার :)
bolov

5
@ লিও91: প্রথমত, আপনার এখানে দুটি স্তরের পয়েন্টার রয়েছে, তিনটি নয়। দ্বিতীয়ত, এর x[0] != x[0][0] != x[0][0][0]অর্থ কী? এটি সি ++ তে বৈধ তুলনা নয়। এমনকি যদি আপনি এটিকে বিভক্ত করেন x[0] != x[0][0]এবং x[0][0] != x[0][0][0]এটি এখনও বৈধ নয়। তো, আপনার প্রশ্নের অর্থ কী?
এএনটি

উত্তর:


261

x5 টি পয়েন্টারের একটি অ্যারেতে পয়েন্টার int
x[0]একটি অ্যারে 5 পয়েন্টার int
x[0][0]একটি পয়েন্টার হয় int
x[0][0][0]একটি int

                       x[0]
   Pointer to array  +------+                                 x[0][0][0]         
x -----------------> |      |         Pointer to int           +-------+
               0x500 | 0x100| x[0][0]---------------->   0x100 |  10   |
x is a pointer to    |      |                                  +-------+
an array of 5        +------+                        
pointers to int      |      |         Pointer to int                             
               0x504 | 0x222| x[0][1]---------------->   0x222                    
                     |      |                                             
                     +------+                                             
                     |      |         Pointer to int                              
               0x508 | 0x001| x[0][2]---------------->   0x001                    
                     |      |                                             
                     +------+                                             
                     |      |         Pointer to int                              
               0x50C | 0x123| x[0][3]---------------->   0x123                    
                     |      |                                             
                     +------+                                             
                     |      |         Pointer to int                              
               0x510 | 0x000| x[0][4]---------------->   0x000                    
                     |      |                                             
                     +------+                                             

তুমি ইহা দেখতে পারো

  • x[0]একটি অ্যারে এবং কোনও অভিব্যক্তিতে ব্যবহৃত হওয়ার পরে (কিছু ব্যতিক্রম সহ) এটির প্রথম উপাদানটিতে পয়েন্টারে রূপান্তরিত হবে। সুতরাং x[0]এটির প্রথম উপাদানটির ঠিকানা দেবে x[0][0]যা 0x500
  • x[0][0]একটি ঠিকানা থাকে intযা 0x100
  • x[0][0][0]এর একটি intমান রয়েছে 10

সুতরাং, x[0]সমান &x[0][0]এবং তাই &x[0][0] != x[0][0],।
সুতরাং x[0] != x[0][0] != x[0][0][0],।


এই চিত্রটি আমার কাছে কিছুটা বিভ্রান্তিকর: এতে 0x100থাকা বাক্সের বাম দিকে তত্ক্ষণাত উপস্থিত হওয়া উচিত , এটির বাক্সের বামে 10যেভাবে 0x500প্রদর্শিত হয়। এটির পরিবর্তে এটি বাম দিকে এবং নীচে থেকে।
এমএম

@MattMcNabb; আমি মনে করি না এটি বিভ্রান্তিকর হওয়া উচিত, তবে আরও স্পষ্টতার জন্য আপনার পরামর্শ অনুসারে পরিবর্তন হয়েছে।
হ্যাক

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

1
আপনি ইয়েড, একটি ডায়াগ্রামিং সফ্টওয়্যারও ব্যবহার করতে পারেন। এটি আমার চিন্তাভাবনাগুলি সংগঠিত করার জন্য আমাকে অনেক সহায়তা করে
rpax

@ গ্রিজেশচৌহান আমি উপস্থাপনার জন্য কোড, ইডি এর মন্তব্যে এসিফ্লো ব্যবহার করি :)
আরপ্যাক্স

133
x[0] != x[0][0] != x[0][0][0]

আপনার নিজের পোস্ট অনুসারে,

*(x+0) != *(*(x+0)+0) != *(*(*(x+0)+0)+0)`  

যা সরলীকৃত হয়

*x != **x != ***x

কেন এটি সমান হবে?
প্রথমটি হ'ল কিছু পয়েন্টারের ঠিকানা।
দ্বিতীয়টি হ'ল অন্য পয়েন্টারের ঠিকানা।
এবং তৃতীয়টি হ'ল কিছু intমান।


আমি বুঝতে পারি না ... যদি x [0], x [0] [0], x [0] [0] [0] * (x + 0), * (x + 0 + 0) এর সমান হয় , * (x + 0 + 0 + 0), কেন তাদের আলাদা ঠিকানা থাকতে হবে?
Leo91

41
@ Leo91 x[0][0]হয় (x[0])[0], অর্থাত্ *((*(x+0))+0), না *(x+0+0)। ডিগ্রিফারেন্স দ্বিতীয়টির আগে ঘটে [0]
Emlai

4
@ Leo91 x[0][0] != *(x+0+0)ঠিক x[2][3] != x[3][2]
5zg

@ লিও91 দ্বিতীয় মন্তব্যটি আপনি "এটি এখন পেয়েছেন" সরানো হয়েছে। আপনি কি কিছু বুঝতে পারছেন না (যা উত্তরে আরও ভাল করে ব্যাখ্যা করা যেতে পারে), বা এটি আপনার কাজ নয়? (কিছু লোক বেশি তথ্যমূলক সামগ্রী ছাড়াই মন্তব্যগুলি মুছতে পছন্দ করে)
ডিভেন্টফ্যান

@ ডিভেন্টফ্যান দুঃখিত, আপনি কী বলতে চাইছেন আমি বুঝতে পারি না। আমি উত্তরগুলি পাশাপাশি অনেক মন্তব্য বুঝতে পেরেছি যা মেটো ধারণাটি পরিষ্কার করতে সহায়তা করেছিল।
লিও 91

50

আপনার পয়েন্টারের মেমরি বিন্যাসটি এখানে:

   +------------------+
x: | address of array |
   +------------------+
            |
            V
            +-----------+-----------+-----------+-----------+-----------+
            | pointer 0 | pointer 1 | pointer 2 | pointer 3 | pointer 4 |
            +-----------+-----------+-----------+-----------+-----------+
                  |
                  V
                  +--------------+
                  | some integer |
                  +--------------+

x[0]"অ্যারেরের ঠিকানা" দেয়,
x[0][0]"পয়েন্টার 0" পাওয়া যায়,
x[0][0][0]"কিছু সংখ্যক" হয়।

আমি বিশ্বাস করি, এটি এখনই সুস্পষ্ট হওয়া উচিত, কেন তারা সবাই আলাদা।


উপরেরটি বুনিয়াদী বোঝার জন্য যথেষ্ট নিকট, যার কারণেই আমি এটি যেভাবে লিখেছি তা লিখেছি। যাইহোক, হ্যাকগুলি যথাযথভাবে উল্লেখ করে, প্রথম লাইনটি 100% সুনির্দিষ্ট নয়। সুতরাং এখানে সমস্ত সূক্ষ্ম বিবরণ আসুন:

সি ভাষার সংজ্ঞা থেকে, এর মান x[0]হ'ল পূর্ণসংখ্যা পয়েন্টারের পুরো অ্যারে। তবে অ্যারে এমন কিছু যা আপনি সিতে আসলে কিছু করতে পারবেন না আপনি সর্বদা তাদের ঠিকানা বা তাদের উপাদানগুলি কোনওভাবেই পুরোপুরি পুরোপুরি পরিচালনা করেন না:

  1. আপনি অপারেটর পাস x[0]করতে পারেন sizeof। তবে এটি সত্যিই মানটির ব্যবহার নয়, এর ফলাফলটি কেবলমাত্র টাইপের উপর নির্ভর করে।

  2. আপনি এটির ঠিকানা নিতে পারেন যা ধরণের সাথে অর্থের xঅর্থ "অ্যারের ঠিকানা" দেয় int*(*)[5]। অন্য কথায়:&x[0] <=> &*(x + 0) <=> (x + 0) <=> x

  3. ইন অন্য সব প্রেক্ষিতে , এর মান x[0]অ্যারের মধ্যে প্রথম উপাদান একটি পয়েন্টার মধ্যে ক্ষয় হবে। এটি হল "অ্যারের ঠিকানা" এবং প্রকারের মান সহ একটি পয়েন্টার int**। প্রভাবটি একইরকম যেমন আপনি কোনও xটাইপের পয়েন্টারটিতে কাস্ট করেছেন int**

3 ক্ষেত্রে অ্যারে-পয়েন্টার ক্ষয়ের কারণে, x[0]চূড়ান্তভাবে সমস্ত ব্যবহারের ফলে পয়েন্টার ফলাফল হয় যা পয়েন্টার অ্যারের শুরুতে নির্দেশ করে; কলটি printf("%p", x[0])"অ্যারের ঠিকানা" হিসাবে লেবেলযুক্ত মেমরি কোষের সামগ্রীগুলি মুদ্রণ করবে।


1
x[0]অ্যারের ঠিকানা নয়।
6:58

1
@ হ্যাকস হ্যাঁ, স্ট্যান্ডার্ডের চিঠিটি অনুসরণ করে x[0]অ্যারের ঠিকানা নয়, এটি অ্যারে নিজেই। আমি এর গভীরতর ব্যাখ্যা যোগ করেছি এবং কেন আমি এটি লিখলাম তা x[0]হল "অ্যারের ঠিকানা"। আশা করি তুমি পছন্দ করেছ.
মাস্টার

দুর্দান্ত চিত্রগুলি যা এটি পুরোপুরি ভালভাবে ব্যাখ্যা করে!
এমকে

"তবে অ্যারে এমন কিছু যা আপনি সিতে আসলেই কিছু করতে পারবেন না" " -> পাল্টা উদাহরণ: printf("%zu\n", sizeof x[0]);অ্যারের আকারের প্রতিবেদন করে, কোনও পয়েন্টারের আকার নয়।
chux - মনিকা পুনরায় ইনস্টল করুন

@ chux-ReinstateMonica আর আমি বলতে "তুমি সবসময় গিয়েছিলাম নিপূণভাবে , শুমার যেখানে আমি প্রভাব সম্পর্কে কথা বলতে বিন্দু 1 দ্বারা অনুসরণ হয় তাদের ঠিকানা অথবা তাদের উপাদান, কখনো সামগ্রিকভাবে সমগ্র অ্যারের" sizeof x[0]...
cmaster - মনিকা পুনরুদ্ধার

18
  • x[0]বাহ্যতমতম পয়েন্টার ( পয়েন্টার থেকে পয়েন্টার 5 মাপের অ্যারে থেকে পয়েন্টার) অবধি এবং পয়েন্টার থেকে 5 আকারের অ্যারের ফলাফল int;
  • x[0][0]দূরতম পয়েন্টার dereferences এবং ইনডেক্স এরে, একটি পয়েন্টার ফলে int;
  • x[0][0][0] সমস্ত কিছু dereferences, ফলস্বরূপ একটি কংক্রিট মান।

যাইহোক, যদি আপনি কখনও এই ধরণের ঘোষণার অর্থ বোঝায় তবেই আপনি বিভ্রান্ত হন, সিডিপেল ব্যবহার করুন


11

ধাপে ধাপে অভিব্যক্তি বিবেচনা করা যাক x[0], x[0][0]এবং x[0][0][0]

যেমন xনিম্নলিখিত উপায়ে সংজ্ঞায়িত করা হয়

int *(*x)[5];

তাহলে অভিব্যক্তি x[0]হ'ল ধরণের অ্যারে int *[5]। খেয়াল করুন যে অভিব্যক্তি অভিব্যক্তির x[0]সমতুল্য *x। এটি একটি বিন্যাসকে একটি অ্যারে রেফারেন্স দিচ্ছে আমরা অ্যারে নিজেই পাই। এটি y এর মতো বোঝাতে দাও যে আমাদের কাছে একটি ঘোষণা আছে

int * y[5];

এক্সপ্রেশন x[0][0]সমান y[0]এবং টাইপ আছে int *। এটি z এর মতো বোঝাতে দাও যে আমাদের কাছে একটি ঘোষণা আছে

int *z;

অভিব্যক্তি অভিব্যক্তির x[0][0][0]সমতুল্য y[0][0]যে পরিবর্তে অভিব্যক্তির সমতুল্য z[0]এবং টাইপ থাকে int

তাহলে আমাদের আছে

x[0] টাইপ আছে int *[5]

x[0][0] টাইপ আছে int *

x[0][0][0] টাইপ আছে int

সুতরাং এগুলি বিভিন্ন ধরণের এবং বিভিন্ন আকারের objects

উদাহরণস্বরূপ চালান

std::cout << sizeof( x[0] ) << std::endl;
std::cout << sizeof( x[0][0] ) << std::endl;
std::cout << sizeof( x[0][0][0] ) << std::endl;

10

প্রথম কথাটি আমাকে বলতে হবে

x [0] = * (x + 0) = * এক্স;

x [0] [0] = * (* (x + 0) + 0) = * * এক্স;

x [0] [0] [0] = * (* (* (x + 0) + 0)) = * * * এক্স;

সুতরাং * x ≠ * * x ≠ * * * এক্স

নিম্নলিখিত ছবি থেকে সমস্ত বিষয় পরিষ্কার।

  x[0][0][0]= 2000

  x[0][0]   = 1001

  x[0]      = 10

এখানে চিত্র বর্ণনা লিখুন

এটি কেবলমাত্র একটি উদাহরণ, যেখানে x [0] [0] [0] = 10 এর মান

এবং x [0] [0] [0] এর ঠিকানা 1001

এই ঠিকানাটি x [0] [0] = 1001 এ সঞ্চয় করা আছে

এবং x [0] [0] এর ঠিকানা 2000

এবং সেই ঠিকানাটি x [0] = 2000 এ সঞ্চয় করা আছে

সুতরাং x [0] [0] [0] x [0] [0] এক্স [0]

EDITINGS

প্রোগ্রাম 1:

{
int ***x;
x=(int***)malloc(sizeof(int***));
*x=(int**)malloc(sizeof(int**));
**x=(int*)malloc(sizeof(int*));
***x=10;
printf("%d   %d   %d   %d\n",x,*x,**x,***x);
printf("%d   %d   %d   %d   %d",x[0][0][0],x[0][0],x[0],x,&x);
}

আউটপুট

142041096 142041112 142041128 10
10 142041128 142041112 142041096 -1076392836

প্রোগ্রাম 2:

{
int x[1][1][1]={10};
printf("%d   %d   %d   %d \n ",x[0][0][0],x[0][0],x[0],&x);
}

আউটপুট

10   -1074058436   -1074058436   -1074058436 

3
আপনার উত্তর বিভ্রান্তিকর। x[0]পিঁপড়া ঠিকানা নেই। এটি একটি অ্যারে। এটি এর প্রথম উপাদানটির দিকে নির্দেশ করতে ক্ষয় হবে।
হ্যাক

উম্মম ... এর মানে কী? আপনার সম্পাদনাটি আপনার ভুল উত্তরের কেকের উপর চেরির মতো। এটি কোনও তাত্পর্যপূর্ণ নয়
হ্যাক

@ হ্যাকস যদি এটি একা পয়েন্টার ব্যবহার করে তবে এই উত্তরটি সঠিক হবে। অ্যারে ব্যবহার করার সময় ঠিকানা বিভাগে কিছু পরিবর্তন হবে
এপিএম

7

আপনি যদি অ্যারেগুলি একটি সত্য-বিশ্বের দৃষ্টিভঙ্গি থেকে দেখতে চান তবে এটি প্রদর্শিত হবে:

x[0]ক্রেট পূর্ণ একটি মালবাহী ধারক।
x[0][0]ফ্রেইটের ধারকটির মধ্যে একক ক্রেট, জুতোবাক্স পূর্ণ।
x[0][0][0]ক্রেটের অভ্যন্তরে, ফ্রেইটের ধারকের ভিতরে একটি একক জুতোবাক্স।

এমনকি যদি ফ্রেইটের পাত্রে কেবল ক্রেটের একমাত্র জুতোবক্স ছিল, এটি এখনও জুতোবক্স এবং ফ্রেইটের ধারক নয়


1
না x[0][0]একটি একক কাগজের টুকরা তাদের উপর লিখিত shoeboxes স্থান আছে পূর্ণ বাক্স হতে পারে?
wchargin

4

সি ++ তে একটি নীতি রয়েছে যাতে: একটি ভেরিয়েবলের ঘোষণাপত্রটি ভেরিয়েবলটি ব্যবহারের সঠিক উপায় নির্দেশ করে। আপনার ঘোষণা বিবেচনা করুন:

int *(*x)[5];

এটিকে (পরিষ্কার করার জন্য) হিসাবে আবার লেখা যেতে পারে:

int *((*x)[5]);

নীতির কারণে, আমাদের রয়েছে:

*((*x)[i]) is treated as an int value (i = 0..4)
 (*x)[i] is treated as an int* pointer (i = 0..4)
 *x is treated as an int** pointer
 x is treated as an int*** pointer

অতএব:

x[0] is an int** pointer
 x[0][0] = (x[0]) [0] is an int* pointer
 x[0][0][0] = (x[0][0]) [0] is an int value

সুতরাং আপনি পার্থক্য নির্ধারণ করতে পারেন।


1
x[0]5 ইন্টের অ্যারে, পয়েন্টার নয়। (এটি বেশিরভাগ প্রসঙ্গে একটি পয়েন্টারের ক্ষয়ে যেতে পারে তবে পার্থক্যটি এখানে গুরুত্বপূর্ণ।
এমএম

ঠিক আছে, তবে আপনার বলা উচিত: x [0] হ'ল 5 পয়েন্টের একটি অ্যারে *
এনঝিয়া বুয়

@MattMcNabb প্রতি সঠিক শিক্ষাদীক্ষা দিতে: *(*x)[5]একটি হল intতাই হয়, (*x)[5]একটি হল int *তাই হয়, *xএকটি হল (int *)[5]তাই হয়, xএকটি হল *((int *)[5])। এটি হ'ল xপয়েন্টারগুলির 5-অ্যারের পয়েন্টার int
wchargin

2

আপনি মান অনুসারে বিভিন্ন ধরণের তুলনা করার চেষ্টা করছেন

আপনি যদি ঠিকানাগুলি নেন তবে আপনি যা আশা করেন তার থেকে আরও বেশি পেতে পারেন

মনে রাখবেন যে আপনার ঘোষণায় কোনও পার্থক্য রয়েছে

 int y [5][5][5];

তুলনা যদি আপনি চান সম্ভব হবে, যেহেতু y, y[0], y[0][0], y[0][0][0]বিভিন্ন মূল্যবোধ ও ধরনের কিন্তু একই ঠিকানায় হবে

int **x[5];

সংক্ষিপ্ত জায়গা দখল করে না।

xএবং x [0]একই ঠিকানা রয়েছে, x[0][0]এবং এবং x[0][0][0]প্রতিটি পৃথক ঠিকানায় রয়েছে


2
int *(*x)[5]এর থেকে আলাদাint **x[5]
এমএম

2

হচ্ছে pএকটি পয়েন্টার: আপনার সাথে এবং dereferences সারিবদ্ধ করছি p[0][0], যা সমতূল্য *((*(p+0))+0)

সি রেফারেন্স (এবং) এবং dereferences (*) স্বরলিপি:

p == &p[0] == &(&p[0])[0] == &(&(&p[0])[0])[0])

এর সমতুল্য:

p == &*(p+0) == &*(&*(p+0))+0 == &*(&*(&*(p+0))+0)+0

দেখুন যে, & * এটি পুনরুদ্ধার করা যেতে পারে, কেবল এটি সরিয়ে ফেলা:

p == p+0 == p+0+0 == p+0+0+0 == (((((p+0)+0)+0)+0)+0)

আপনার প্রথম বাক্যটির পরে আপনি সবকিছু দিয়ে কী দেখানোর চেষ্টা করছেন? আপনার কেবলমাত্র প্রচুর বৈচিত্র্য রয়েছে p == p&(&p[0])[0]এর থেকে আলাদাp[0][0]
এমএম

লোকটি জিজ্ঞাসা করল কেন 'x [0]! = X [0] [0]! = X [0] [0] [0]' যখন এক্স পয়েন্টার হয়, তাই না? আমি তাকে দেখানোর চেষ্টা করেছি, যে তিনি [0] এর স্ট্যাক করে দিলে তিনি সি প্রজ্ঞাপন (*) এর দ্বারা আটকে যেতে পারেন। সুতরাং, এটি x সমান x [0] হওয়ার সঠিক সংকেত প্রদর্শন করার চেষ্টা করুন, x [0] কে আবার & এর সাথে উল্লেখ করেছেন এবং আরও।
লুকিয়ানো

1

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

অন্যান্য উত্তরগুলি থেকে এটি বোঝা যায় না তার কারণ হ'ল সমস্ত চিত্রগুলি বেশিরভাগ পরিস্থিতিতে সহায়ক এবং স্পষ্টভাবে যুক্তিসঙ্গত হলেও পয়েন্টারটি xনিজের দিকে নির্দেশ করে এমন পরিস্থিতিটি coverাকতে ব্যর্থ হয় ।

এটি নির্মাণ করা বেশ সহজ, তবে স্পষ্টভাবে বুঝতে কিছুটা শক্ত। নীচের প্রোগ্রামে আমরা দেখতে পাব কীভাবে আমরা তিনটি মানকে অভিন্ন হতে পারি can

দ্রষ্টব্য: এই প্রোগ্রামের আচরণটি অপরিজ্ঞাত, তবে আমি এখানে এটি শুদ্ধভাবে পোস্ট করছি যাতে কিছু এমন একটি আকর্ষণীয় প্রদর্শন যা পয়েন্টারগুলি করতে পারে তবে তা করা উচিত নয়

#include <stdio.h>

int main () {
  int *(*x)[5];

  x = (int *(*)[5]) &x;

  printf("%p\n", x[0]);
  printf("%p\n", x[0][0]);
  printf("%p\n", x[0][0][0]);
}

এটি C89 এবং C99 উভয় ক্ষেত্রেই সতর্কতা ছাড়াই সংকলন করে এবং আউটপুটটি নিম্নলিখিত:

$ ./ptrs
0xbfd9198c
0xbfd9198c
0xbfd9198c

আকর্ষণীয়ভাবে যথেষ্ট, তিনটি মানই অভিন্ন। তবে এটি আশ্চর্য হওয়া উচিত নয়! প্রথমে প্রোগ্রামটি ভেঙে দেওয়া যাক।

আমরা x5 টি উপাদানের একটি অ্যারে যেখানে পয়েন্টার হিসাবে প্রতিটি উপাদান টাইপ পয়েন্টার টাইপ হয়। এই ঘোষণাপত্রটি রানটাইম স্ট্যাকের 4 বাট বরাদ্দ করে (বা আরও আপনার প্রয়োগের উপর নির্ভর করে; আমার মেশিন পয়েন্টারগুলিতে 4 বাইট রয়েছে), তাই xপ্রকৃত মেমরির অবস্থান উল্লেখ করা হচ্ছে। ভাষার সি পরিবারে বিষয়বস্তুগুলি xকেবল আবর্জনা, অবস্থানের আগের ব্যবহার থেকে কিছু বাদ পড়েছে, তাই xনিজেই কোথাও নির্দেশ করে না - অবশ্যই বরাদ্দ স্থানকে নয়।

সুতরাং, স্বাভাবিকভাবেই, আমরা চলকটির ঠিকানা নিতে পারি xএবং এটি কোথাও রেখে দিতে পারি, তাই আমরা যা করি ঠিক তেমনই। তবে আমরা এগিয়ে যাব এবং এটিকে x এর মধ্যে রেখে দেব। যেহেতু &xভিন্ন ধরণের রয়েছে xতাই আমাদের একটি কাস্ট করা দরকার যাতে আমাদের সতর্কতা না পাওয়া যায়।

মেমরির মডেলটি এরকম কিছু দেখবে:

0xbfd9198c
+------------+
| 0xbfd9198c |
+------------+

সুতরাং ঠিকানায় মেমরির 4-বাইট ব্লকে 0xbfd9198cহেক্সাডেসিমাল মানের সাথে সম্পর্কিত বিট প্যাটার্ন রয়েছে 0xbfd9198c। যথেষ্ট সহজ।

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

আমরা দেখতে পাচ্ছি যে মানগুলি একই, তবে কেবলমাত্র খুব নিম্ন স্তরের অর্থে ... তাদের বিট নিদর্শনগুলি অভিন্ন, তবে প্রতিটি অভিব্যক্তির সাথে সম্পর্কিত টাইপের ডেটা বলতে বোঝায় যে তাদের ব্যাখ্যা করা মানগুলি আলাদা। উদাহরণস্বরূপ, আমরা যদি x[0][0][0]ফর্ম্যাট স্ট্রিংটি ব্যবহার করে মুদ্রণ করি তবে আমরা %dএকটি বিশাল নেতিবাচক সংখ্যা পাই, সুতরাং "মানগুলি", বাস্তবে ভিন্ন, তবে বিট প্যাটার্নটি একই।

এটি আসলেই খুব সহজ ... ডায়াগ্রামগুলিতে তীরগুলি কেবল একই মেমরি ঠিকানার দিকে আলাদা করে নির্দেশ করে ones যাইহোক, আমরা অপরিবর্তিত আচরণের কারণে একটি প্রত্যাশিত ফলাফলকে জোর করতে সক্ষম হয়েছি, এটি কেবল — অপরিজ্ঞাত। এটি প্রোডাকশন কোড নয় বরং সম্পূর্ণতার স্বার্থে কেবল একটি প্রদর্শনী।

যুক্তিসঙ্গত পরিস্থিতিতে আপনি malloc5 টি ইনট পয়েন্টারগুলির অ্যারে তৈরি করতে এবং আবার সেই অ্যারেটিতে নির্দেশিত ইনসটি তৈরি করতে ব্যবহার করবেন। mallocসর্বদা একটি অনন্য ঠিকানা ফেরত দেয় (যদি না আপনি স্মৃতি থেকে দূরে থাকেন, তবে এটি যদি নুল বা 0 ফেরত দেয়), তাই আপনাকে কখনই এই জাতীয় স্ব-রেফারেন্সিয়াল পয়েন্টার সম্পর্কে চিন্তা করতে হবে না।

আশা করি এটি আপনি সম্পূর্ণ উত্তরটি সন্ধান করছেন। আপনি আশা করতে পারে না x[0], x[0][0]আর x[0][0][0]সমান হতে, কিন্তু তারা যদি বাধ্য হতে পারে। যদি আপনার মাথার উপরে কিছু চলে যায় তবে আমাকে জানিয়ে দিন যাতে আমি স্পষ্ট করে বলতে পারি!


আমি বলব যে আমি দেখিবার পয়েন্টারগুলির আর একটি অদ্ভুত ব্যবহার।
হ্যাক

@ হ্যাকস হ্যাঁ, এটি বেশ অদ্ভুত, তবে আপনি যখন এটি ভেঙে ফেলেন তখন এটি অন্যান্য উদাহরণগুলির মতোই মৌলিক। এটি কেবল এমন এক ক্ষেত্রে ঘটে যেখানে বিট প্যাটার্নগুলি সমস্ত একই।
পুরগ

আপনার কোড অনির্ধারিত আচরণের কারণ। x[0]প্রকৃতপক্ষে সঠিক ধরণের কোনও বৈধ অবজেক্টের প্রতিনিধিত্ব করে না
এমএম

@ ম্যাটম্যাকনাব এটি অপরিজ্ঞাত, এবং আমি এটি সম্পর্কে খুব স্পষ্ট। আমি টাইপ সম্পর্কে একমত না। xএকটি অ্যারের পয়েন্টার, তাই আমরা []সেই পয়েন্টার থেকে একটি অফসেট নির্দিষ্ট করতে এবং এটি ডিফারেন্সিং করে অপারেটরটি ব্যবহার করতে পারি। সেখানে কি আশ্চর্য? ফলাফলটি x[0]একটি অ্যারে হয়, এবং সি প্রিন্ট করে যদি অভিযোগ করে না যে %pএটি যেভাবেই এর নীচে বাস্তবায়িত হয় using
পুরাগ

এবং -pedanticপতাকাটির সাথে এটি সংকলন করে কোনও সতর্কতা তৈরি হয় না, সুতরাং সি ধরণের সাথে ঠিক আছে ...
পুরগ

0

প্রকারটি int *(*x)[5]হ'ল int* (*)[5]ইন্টি টু 5 পয়েন্টারের অ্যারেতে পয়েন্টার।

  • xints to 5 পয়েন্টার প্রথম অ্যারের ঠিকানা (টাইপ সহ একটি ঠিকানা int* (*)[5])
  • x[0]ints to 5 পয়েন্টারের প্রথম অ্যারের ঠিকানা (টাইপের সাথে একই ঠিকানা int* [5]) (অফসেট অ্যাড্রেস x 0*sizeof(int* [5])অর্থাত্ সূচক দ্বারা * আকারের-টাইপ-হচ্ছে-পয়েন্ট-টু এবং ডিরিফারেন্স)
  • x[0][0]অ্যারেতে কোনও আন্তের প্রথম পয়েন্টার (টাইপ সহ একই ঠিকানা int*) (অ্যাড্রেস এক্স দ্বারা বাই 0*sizeof(int* [5])ডিरेফারেন্স এবং তারপরে 0*sizeof(int*)এবং ডিरेফারেন্স)
  • x[0][0][0]পয়েন্টার দ্বারা কোন প্রথম দিকে ইন্টেন্ট করা হচ্ছে (অফসেট অ্যাড্রেস এক্স দ্বারা 0*sizeof(int* [5])এবং ডিरेফারেন্স এবং সেই ঠিকানাটি অফসেট দ্বারা 0*sizeof(int*)এবং ডিरेফারেন্স করে এবং সেই ঠিকানাটি অফসেট 0*sizeof(int)এবং ডিরেফারেন্স দ্বারা অফসেট করা হবে )

প্রকারটি int *(*y)[5][5][5]হ'ল int* (*)[5][5][5]অর্থ 5x5x5 পয়েন্টারকে ইনটগুলিতে 3 ডি অ্যারের পয়েন্টার

  • x টাইপযুক্ত ইনটগুলিতে 5x5x5 পয়েন্টারগুলির প্রথম 3 ডি অ্যারের ঠিকানা int*(*)[5][5][5]
  • x[0]ints থেকে 5x5x5 পয়েন্টার এর প্রথম 3 ডি অ্যারের ঠিকানা (অ্যাড্রেস এক্স দ্বারা বাই 0*sizeof(int* [5][5][5])এবং ডিসেরেন্স)
  • x[0][0]ints থেকে পয়েন্টার 5x5 এর প্রথম 2 ডি অ্যারের ঠিকানা (অ্যাড্রেস এক্স দ্বারা বাই 0*sizeof(int* [5][5][5])এবং ডিপ্রেশন তারপরে সেই ঠিকানাটি অফসেট করুন 0*sizeof(int* [5][5]))
  • x[0][0][0]অন্তর্নিহিত 5 পয়েন্টারের প্রথম অ্যারের ঠিকানা (অ্যাড্রেস এক্স দ্বারা 0*sizeof(int* [5][5][5])এবং ডিरेফারেশন এবং সেই ঠিকানাটি 0*sizeof(int* [5][5])অফসেটটি অফসেট করে এবং সেই ঠিকানাটি অফসেট করে 0*sizeof(int* [5]))
  • x[0][0][0][0]অ্যারেতে কোনও ইনটেলের প্রথম পয়েন্টার (অ্যাড্রেস এক্স বাই 0*sizeof(int* [5][5][5])এবং ডিসিটারেন্স এবং সেই ঠিকানাটি 0*sizeof(int* [5][5])অফসেট করে 0*sizeof(int* [5])অফসেট করে সেই ঠিকানাটি অফসেট করে এবং সেই ঠিকানাটি অফসেট 0*sizeof(int*)এবং ডিरेফারেন্স দ্বারা অফসেট করা হয় )
  • x[0][0][0][0][0]প্রথম ইন্টিটি পয়েন্টার দ্বারা ইন্টেন্টে ইন্টেন্ট করা হচ্ছে (অফসেট অ্যাড্রেস এক্স দ্বারা 0*sizeof(int* [5][5][5])এবং ডিरेফারেন্স এবং সেই ঠিকানাটি 0*sizeof(int* [5][5])অফসেট করে সেই ঠিকানাটি 0*sizeof(int* [5])অফসেট করে এবং সেই ঠিকানাটি অফসেট করে 0*sizeof(int*)এবং সেই অবস্থানটিকে অফসেট করে 0*sizeof(int)এবং সেই ঠিকানাটি অফসেট এবং ডিরেইফার করে)

অ্যারে ক্ষয় হিসাবে:

void function (int* x[5][5][5]){
  printf("%p",&x[0][0][0][0]); //get the address of the first int pointed to by the 3d array
}

এটি উত্তীর্ণের সমতুল্য int* x[][5][5]বা int* (*x)[5][5]তারা সকলেই পরেরটির ক্ষয়। এই কারণেই আপনি ফাংশনটিতে ব্যবহারের জন্য একটি সংকলক সতর্কতা পাবেন x[6][0][0]না তবে আপনি হবেন x[0][6][0]কারণ সেই আকারের তথ্য সংরক্ষণ করা হয়েছে

void function (int* (*x)[5][5][5]){
  printf("%p",&x[0][0][0][0][0]); //get the address of the first int pointed to by the 3d array
}
  • x[0] ints থেকে 5x5x5 পয়েন্টারের প্রথম 3 ডি অ্যারের ঠিকানা
  • x[0][0] ints থেকে 5x5 পয়েন্টারের প্রথম 2 ডি অ্যারের ঠিকানা
  • x[0][0][0] ints থেকে 5 পয়েন্টারের প্রথম অ্যারের ঠিকানা
  • x[0][0][0][0] অ্যারেতে কোনও আন্তের প্রথম পয়েন্টার
  • x[0][0][0][0][0] পয়েন্টার দ্বারা কোন int এর দিকে নির্দেশ করা হচ্ছে প্রথম INT

শেষ উদাহরণে, শব্দাবলীর চেয়ে এটি ব্যবহার *(*x)[0][0][0]করার চেয়ে আরও স্পষ্ট x[0][0][0][0][0], কারণ এখানে প্রথম এবং শেষটি [0]এক ধরণের বহুমাত্রিক অ্যারেতে সূচক না করে পয়েন্টার ডিরিফারেন্স হিসাবে ব্যাখ্যা করা হয়। তারা যদিও অভিন্ন কারণ (*x) == x[0]শব্দার্থবিজ্ঞান নির্বিশেষে। আপনি এটিও ব্যবহার করতে পারেন *****x, যা দেখে মনে হয় যে আপনি পয়েন্টারটি 5 বার অবজ্ঞাপন করছেন, তবে এটি আসলে একইরূপে ব্যাখ্যা করা হয়েছে: অফসেট, একটি অবলম্বন, একটি বিন্যাস, 2 অফসেটগুলিকে একটি অ্যারে এবং একটি বিন্যাসে নিখুঁতভাবে কারণ আপনি অপারেশন প্রয়োগ করছেন।

মূলত যখন আপনি [0]বা *একটি *নন অ্যারে টাইপ করেন, এটি অগ্রাধিকারের ক্রমের কারণে এটি অফসেট এবং একটি অবজ্ঞা *(a + 0)

যখন আপনি [0]বা *একটি *একটি অ্যারের টাইপ তারপর এটি একটি অফসেট তত্কালীন একটি idempotent ডি-রেফারেন্স (- এটি একটি idempotent অপারেশন ডি-রেফারেন্স একই ঠিকানায় উত্পাদ কম্পাইলার দ্বারা সমাধান করা)।

আপনি [0]বা *1d অ্যারের প্রকারের সাথে টাইপ করার পরে এটি একটি অফসেট হয় তারপরে একটি অবলম্বন

যদি আপনি [0]বা **2 ডি অ্যারে টাইপ করেন তবে এটি কেবল একটি অফসেট অর্থাত্ একটি অফসেট এবং তারপরে একটি আদর্শ পন্থা।

যদি আপনি [0][0][0]বা ***3 ডি অ্যারে টাইপ করেন তবে এটি অফসেট + আইডিম্পোটেন্ট ডিरेফারেন্সের পরে অফসেট + আইডিম্পোটেন্ট ডেরেফারেন্স এবং পরে অফসেট + আইডিম্পোটেন্ট ডিरेফারেন্স একটি ডিরিফরেন্স। আসল প্রকারটি তখনই ঘটে যখন অ্যারের ধরণটি পুরোপুরি বন্ধ হয়ে যায়।

int* (*x)[1][2][3]প্রকারের উদাহরণের জন্য ক্রম মোড়ানো হয়।

  • x একটি প্রকার আছে int* (*)[1][2][3]
  • *xএর একটি প্রকার রয়েছে int* [1][2][3](অফসেট 0 + আইডেম্পোটেন্ট ডিসেন্টারেন্স)
  • **xএর একটি প্রকার রয়েছে int* [2][3](অফসেট 0 + আইডেম্পোটেন্ট ডিসেন্টারেন্স)
  • ***xএর একটি প্রকার রয়েছে int* [3](অফসেট 0 + আইডেম্পোটেন্ট ডিসেন্টারেন্স)
  • ****xএকটি প্রকার আছে int*(অফসেট 0 + ডিরিফারেন্স)
  • *****xটাইপ আছে int(অফসেট 0 + ডিসেরেন্স)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.