নিম্নলিখিত ঘোষণার মধ্যে পার্থক্য কি:
int* arr1[8];
int (*arr2)[8];
int *(arr3[8]);
আরও জটিল ঘোষণা বোঝার সাধারণ নিয়ম কী?
const
এবং volatile
যোগ্যতা অর্জনকারীরা নিবন্ধটিতে অনুপস্থিত।
নিম্নলিখিত ঘোষণার মধ্যে পার্থক্য কি:
int* arr1[8];
int (*arr2)[8];
int *(arr3[8]);
আরও জটিল ঘোষণা বোঝার সাধারণ নিয়ম কী?
const
এবং volatile
যোগ্যতা অর্জনকারীরা নিবন্ধটিতে অনুপস্থিত।
উত্তর:
int* arr[8]; // An array of int pointers.
int (*arr)[8]; // A pointer to an array of integers
তৃতীয়টি প্রথমটির মতোই।
সাধারণ নিয়ম অপারেটর অগ্রাধিকার । ফাংশন পয়েন্টারগুলি ছবিতে আসার সাথে এটি আরও জটিল হয়ে উঠতে পারে।
( ) [ ]
বাম থেকে ডানদিকে সংযুক্ত থাকে এবং 8 মাপের অ্যারে হিসাবে *
পড়ার চেয়ে উচ্চতর প্রাধান্য পায় int* arr[8]
যেখানে প্রতিটি উপাদানটি একটি ইন্টি এবং int (*arr)[8]
পয়েন্টার হিসাবে 8 মাপের অ্যারেতে ইন্টিজার যুক্ত করে রাখে
কেএন্ডআর-এর পরামর্শ অনুসারে সিডিসিএল প্রোগ্রাম ব্যবহার করুন ।
$ cdecl
Type `help' or `?' for help
cdecl> explain int* arr1[8];
declare arr1 as array 8 of pointer to int
cdecl> explain int (*arr2)[8]
declare arr2 as pointer to array 8 of int
cdecl> explain int *(arr3[8])
declare arr3 as array 8 of pointer to int
cdecl>
এটি অন্যান্য ভাবে কাজ করে।
cdecl> declare x as pointer to function(void) returning pointer to float
float *(*x)(void )
এটির কোনও অফিসিয়াল নাম আছে কিনা তা আমি জানি না তবে আমি এটিকে ডান-বাম থিঙ্গি (টিএম) বলি।
চলকটি শুরু করুন, তারপরে ডান এবং বাম দিকে যান এবং ডানদিকে ... এবং আরও কিছু।
int* arr1[8];
arr1
পূর্ণসংখ্যার জন্য 8 পয়েন্টারের একটি অ্যারে।
int (*arr2)[8];
arr2
8 টি পূর্ণসংখ্যার অ্যারেতে একটি পয়েন্টার (প্রথম বন্ধনী ডান-বামে ব্লক করে) হয়।
int *(arr3[8]);
arr3
পূর্ণসংখ্যার জন্য 8 পয়েন্টারের একটি অ্যারে।
এটি আপনাকে জটিল ঘোষণায় সহায়তা করতে পারে।
int *a[][10]
যখন আধুনিক সফল।
( ) [ ]
বাম থেকে ডান সাহচর্য এবং ডান থেকে বামের বামদিকে ভুলবেন না* &
int *a[4]; // Array of 4 pointers to int
int (*a)[4]; //a is a pointer to an integer array of size 4
int (*a[8])[5]; //a is an array of pointers to integer array of size 5
[5]
) অন্তঃকরণের মাত্রা উপস্থাপন করে। এর অর্থ (*a[8])
এটি প্রথম মাত্রা এবং এটি অ্যারের বাইরের উপস্থাপনা। কি মধ্যে প্রতিটি উপাদান a
পয়েন্ট আকার 5. একটি ভিন্ন পূর্ণসংখ্যা অ্যারে
শেষ দুটিটির উত্তরটিও সি-তে সুবর্ণ নিয়ম থেকে কেটে নেওয়া যেতে পারে:
ঘোষণা অনুসরণ অনুসরণ।
int (*arr2)[8];
আপনি যদি ডিফারেন্স করেন তবে কী হবে arr2
? আপনি 8 টি পূর্ণসংখ্যার একটি অ্যারে পাবেন।
int *(arr3[8]);
আপনি যদি কোনও উপাদান থেকে নেন তবে কী হবে arr3
? আপনি একটি পূর্ণসংখ্যার পয়েন্টার পান।
ফাংশনগুলিতে পয়েন্টারগুলির সাথে ডিল করার সময় এটিও সহায়তা করে। সিগজাইসের উদাহরণ নিতে:
float *(*x)(void )
আপনি যখন অবজ্ঞাপূর্ণ হন তখন কী হয় x
? আপনি একটি ফাংশন পাবেন যা আপনি কোনও যুক্তি ছাড়াই কল করতে পারবেন। আপনি যখন ফোন করবেন তখন কি হবে? এটি একটিতে একটি পয়েন্টার ফিরিয়ে দেবে float
।
অপারেটর অগ্রাধিকার সর্বদা কৃপণ, যদিও। তবে, প্রথম বন্ধনী ব্যবহার করা আসলে বিভ্রান্তিকর হতে পারে কারণ ঘোষণাপত্রটি ব্যবহারের অনুসরণ করে। কমপক্ষে, আমার কাছে, স্বজ্ঞাতসারে arr2
8 টি পয়েন্টার ইন্টিতে একটি অ্যারের মতো দেখায়, তবে এটি আসলে অন্যভাবে। কিছুটা অভ্যস্ত হয়ে যায়। আপনি যদি আমাকে জিজ্ঞাসা করেন তবে এই ঘোষণাগুলিতে সর্বদা একটি মন্তব্য যুক্ত করার পর্যাপ্ত কারণ :)
সম্পাদনা: উদাহরণ
যাইহোক, আমি কেবল নিম্নলিখিত পরিস্থিতিটি পেরিয়ে গিয়েছি: একটি ফাংশন যা একটি স্ট্যাটিক ম্যাট্রিক্স এবং এটি পয়েন্টার গাণিতিক ব্যবহার করে সারি পয়েন্টারটি সীমা ছাড়িয়েছে কিনা তা দেখতে। উদাহরণ:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUM_ELEM(ar) (sizeof(ar) / sizeof((ar)[0]))
int *
put_off(const int newrow[2])
{
static int mymatrix[3][2];
static int (*rowp)[2] = mymatrix;
int (* const border)[] = mymatrix + NUM_ELEM(mymatrix);
memcpy(rowp, newrow, sizeof(*rowp));
rowp += 1;
if (rowp == border) {
rowp = mymatrix;
}
return *rowp;
}
int
main(int argc, char *argv[])
{
int i = 0;
int row[2] = {0, 1};
int *rout;
for (i = 0; i < 6; i++) {
row[0] = i;
row[1] += i;
rout = put_off(row);
printf("%d (%p): [%d, %d]\n", i, (void *) rout, rout[0], rout[1]);
}
return 0;
}
আউটপুট:
0 (0x804a02c): [0, 0]
1 (0x804a034): [0, 0]
2 (0x804a024): [0, 1]
3 (0x804a02c): [1, 2]
4 (0x804a034): [2, 4]
5 (0x804a024): [3, 7]
নোট করুন যে সীমানার মান কখনই পরিবর্তন হয় না, তাই সংকলক এটিকে অপ্টিমাইজ করতে পারে। এটি প্রাথমিকভাবে আপনি const int (*border)[3]
যেটি ব্যবহার করতে চাইতে পারেন তার থেকে পৃথক :: এটি 3 পূর্ণসংখ্যার অ্যারের পয়েন্টার হিসাবে সীমানা ঘোষনা করে যা ভেরিয়েবলের অস্তিত্বের মধ্যে মান পরিবর্তন করবে না। যাইহোক, যে পয়েন্টার যে কোনও সময় এই জাতীয় অন্য অ্যারে নির্দেশ করা যেতে পারে। পরিবর্তে আমরা যুক্তির জন্য এই জাতীয় আচরণ চাই (কারণ এই ফাংশনটি those কোনও পূর্ণসংখ্যার কোনও পরিবর্তন করে না)। ঘোষণা অনুসরণ অনুসরণ।
(PS: এই নমুনা উন্নত করতে নির্দ্বিধায়!)
typedef int (*PointerToIntArray)[];
typedef int *ArrayOfIntPointers[];
একটি চলতি নিয়ম, ডান ইউনারী অপারেটর (যেমন হিসাবে []
, ()
ইত্যাদি) বাম বেশী বেশী অগ্রাধিকার নিতে। সুতরাং, int *(*ptr)()[];
এমন একটি পয়েন্টার হবে যা কোনও ফাংশনকে নির্দেশ করে যা বিন্দুতে বিন্যাসের অ্যারে প্রদান করে (প্যারেন্টেসিস থেকে বেরিয়ে আসার সাথে সাথে সঠিক অপারেটরগুলি পান)
error: ‘foo’ declared as function returning an array int foo(int arr_2[5][5])[5];
জিসিসি 8 এর অধীনে$ gcc -std=c11 -pedantic-errors test.c
int *(*ptr)();
মতো অভিব্যক্তিটি পরে ব্যবহার করার অনুমতি দেয় । p()[3]
(*p)()[3]
int *foo(int arr_2[5][5]) { return &(arr_2[2][0]); }
এবং এটিকে কল করুন: foo(arr)[4];
যা থাকা উচিত arr[2][4]
, তাই না?
আমি মনে করি আমরা সাধারণ নিয়মটি ব্যবহার করতে পারি ..
example int * (*ptr)()[];
start from ptr
" ptr
এটি" ডানদিকে যেতে .. পয়েন্টার " হ'ল") "এখন যান এটির একটি" ("বাইরে চলে আসুন ডান" () "সুতরাং" এমন কোনও ফাংশনে যা কোনও আর্গুমেন্ট নেয় না "বামে যান" এবং একটি পয়েন্টার ফেরত "যান" পূর্ণসংখ্যার ডানদিকে "অ্যারে" বাম দিকে যান "
)
, এখন বাম দিকে যান ... এটি *
"পয়েন্টার" ডানদিকে যেতে ... এটি )
, এখন বামে যান ... এটি একটি (
বেরিয়ে আসুন, ডানদিকে যান ()
"এমন একটি ফাংশনে যা" গো ডান ... []
" কোনও আর্গুমেন্ট নেয় না এবং" ডান ;
প্রান্তে যান, সুতরাং বামে যান ... *
"পয়েন্টারগুলিকে" বামে যান ... int
"পূর্ণসংখ্যার" নির্দেশ দেয়
এখানে একটি আকর্ষণীয় ওয়েবসাইট রয়েছে যা সি: http://www.unixwiz.net/techtips/reading-cdecl.html- এ জটিল প্রকারগুলি কীভাবে পড়তে হবে তা ব্যাখ্যা করে's
এখানে আমি এটি কীভাবে ব্যাখ্যা করি:
int *something[n];
অগ্রাধিকারের উপর নোট: অ্যারে সাবস্ক্রিপ্ট অপারেটর (
[]
) এর dereferences অপারেটর (*
) এর চেয়ে বেশি অগ্রাধিকার রয়েছে ।
সুতরাং, এখানে আমরা []
পূর্বে প্রয়োগ করব *
, বিবৃতিটির সমতুল্য করে:
int *(something[i]);
কীভাবে কোনও ঘোষণাপত্রটি বোঝায়: দ্রষ্টব্য:
int num
অর্থnum
হ'ল একটিint
,int *ptr
বাint (*ptr)
অর্থ, (মানptr
হ'ল) একটিint
, যাptr
একটি পয়েন্টার করেint
।
এটি হিসাবে পড়তে পারেন, (এর মান (কোনও কিছুর ith সূচকের মান)) একটি পূর্ণসংখ্যা। সুতরাং, (কোনও কিছুর ith সূচকের মান) একটি (পূর্ণসংখ্যার পয়েন্টার), যা কিছুকে পূর্ণসংখ্যার পয়েন্টারের অ্যারে করে তোলে।
দ্বিতীয়টিতে,
int (*something)[n];
এই বিবৃতিটি বোঝার জন্য, আপনাকে অবশ্যই এই সত্যটির সাথে পরিচিত হতে হবে:
অ্যারের পয়েন্টার উপস্থাপনায় নোট:
somethingElse[i]
সমান*(somethingElse + i)
সুতরাং, প্রতিস্থাপন somethingElse
সঙ্গে (*something)
, আমরা পেতে *(*something + i)
, যা প্রতি ঘোষণা যেমন একটি পূর্ণসংখ্যা। সুতরাং, (*something)
আমাদের একটি অ্যারে দেওয়া হয়েছে, যা সমান কিছু তৈরি করে (অ্যারেতে পয়েন্টার) ।
আমার ধারণা দ্বিতীয় ঘোষণাটি অনেকের কাছে বিভ্রান্তিকর। এটি বোঝার একটি সহজ উপায় এখানে।
এর পূর্ণসংখ্যার অ্যারে রাখতে দেয়, যেমন int B[8]
।
আসুন একটি ভেরিয়েবল এও রয়েছে যা বিকে নির্দেশ করে এখন, A এর মান হ'ল B, অর্থাৎ (*A) == B
। সুতরাং একটি পূর্ণসংখ্যার একটি অ্যারে নির্দেশ করে। আপনার প্রশ্নে, আরারটি এ এর মতো is
তেমনিভাবে, int* (*C) [8]
সি-তে পূর্ণসংখ্যার সাথে পয়েন্টারগুলির একটি অ্যারের পয়েন্টার।
int *arr1[5]
এই ঘোষণাপত্রে, arr1
পূর্ণসংখ্যার সাথে 5 পয়েন্টারের অ্যারে হয়। কারণ: স্কোয়ার বন্ধনী * (ডিফারিং অপারেটর) এর চেয়ে বেশি অগ্রাধিকার পেয়েছে। এবং এই ধরণের ক্ষেত্রে, সারিগুলির সংখ্যা স্থির করা হয় (এখানে 5) তবে কলামগুলির সংখ্যা পরিবর্তনশীল।
int (*arr2)[5]
এই ঘোষণাপত্রে, arr2
5 টি উপাদানের একটি পূর্ণসংখ্য অ্যারের পয়েন্টার। কারণ: এখানে, () বন্ধনীগুলিতে [] এর চেয়ে বেশি অগ্রাধিকার রয়েছে। এবং এই ধরণের ক্ষেত্রে, সারিগুলির সংখ্যা পরিবর্তনশীল, কিন্তু কলামগুলির সংখ্যা স্থির (এখানে 5)।
একটি পূর্ণসংখ্যার সাথে পয়েন্টারে যদি পয়েন্টারটি বাড়ানো হয় তবে এটি পরবর্তী পূর্ণসংখ্যায় যায়।
পয়েন্টারের অ্যারেতে যদি পয়েন্টার বাড়ানো হয় তবে তা পরবর্তী অ্যারেতে চলে যায়