সি পয়েন্টার থেকে অ্যারে / অ্যারে পয়েন্টারগুলি দ্ব্যর্থহীন


463

নিম্নলিখিত ঘোষণার মধ্যে পার্থক্য কি:

int* arr1[8];
int (*arr2)[8];
int *(arr3[8]);

আরও জটিল ঘোষণা বোঝার সাধারণ নিয়ম কী?


54
এখানে সি জটিল ঘোষণা পড়া সম্পর্কে একটি মহান নিবন্ধ unixwiz.net/techtips/reading-cdecl.html
Jesper

@ জেস্পার দুর্ভাগ্যক্রমে, গুরুত্বপূর্ণ এবং কৌশলগত উভয়ই constএবং volatileযোগ্যতা অর্জনকারীরা নিবন্ধটিতে অনুপস্থিত।
-এ-এ-ব্যবহারকারী নয়

@ ব্যবহারকারী নয় যারা এই প্রশ্নের সাথে প্রাসঙ্গিক নয়। আপনার মন্তব্য প্রাসঙ্গিক নয়। দয়া করে বিরত থাকুন।
ব্যবহারকারী 64742

উত্তর:


439
int* arr[8]; // An array of int pointers.
int (*arr)[8]; // A pointer to an array of integers

তৃতীয়টি প্রথমটির মতোই।

সাধারণ নিয়ম অপারেটর অগ্রাধিকার । ফাংশন পয়েন্টারগুলি ছবিতে আসার সাথে এটি আরও জটিল হয়ে উঠতে পারে।


4
সুতরাং, 32 বিট সিস্টেমের জন্য: ইনট * আরআর [8]; / * 8x4 বাইট বরাদ্দ, প্রতিটি পয়েন্টার / ইনট (* আরআর) জন্য [8]; / 4 বাইট বরাদ্দ, কেবল একটি পয়েন্টার * /
জর্জ

10
নাঃ। ইন্ট * আরআর [8]: 8x4 বাইট বরাদ্দ মোট , প্রতিটি পয়েন্টারের জন্য 4 বাইট। int (* আরআর) [8] ঠিক, 4 বাইট।
মেহরদাদ আফশারী

2
আমি যা লিখেছি তা আমার পুনরায় পড়া উচিত ছিল। আমি প্রতিটি পয়েন্টার জন্য 4 মানে। সাহায্যের জন্য ধন্যবাদ!
জর্জ

4
প্রথমটি সর্বশেষের সমান হওয়ার কারণ হ'ল এটি সর্বদা ঘোষকগণের কাছাকাছি প্রথম বন্ধনী আবদ্ধ করার অনুমতি দেয়। পি [এন] একটি অ্যারে ডিক্লেয়ারার। পি (....) একটি ফাংশন ঘোষক এবং * পি একটি পয়েন্টার ঘোষক। সুতরাং নীচের সমস্ত কিছুই কোনও প্রথম বন্ধনী ছাড়াই সমান (ফাংশনগুলির মধ্যে একটি "" () "ব্যতীত: অন্তর (((* পি))); শূন্য ((জি (শূন্য))); ইনট * (এ [1]);। অকার্যকর (* (P ()))
জোহানেস Schaub - litb

2
আপনার ব্যাখ্যায় ভাল হয়েছে। অপারেটরদের অগ্রাধিকার এবং সাহচর্য সম্পর্কে গভীরতর উল্লেখের জন্য ব্রায়ান কর্নিগান এবং ডেনিস রিচি লিখিত সি প্রোগ্রামিং ল্যাঙ্গুয়েজের (এএনএসআই সি দ্বিতীয় সংস্করণ) পৃষ্ঠা 53 দেখুন। অপারেটরগুলি ( ) [ ] বাম থেকে ডানদিকে সংযুক্ত থাকে এবং 8 মাপের অ্যারে হিসাবে *পড়ার চেয়ে উচ্চতর প্রাধান্য পায় int* arr[8]যেখানে প্রতিটি উপাদানটি একটি ইন্টি এবং int (*arr)[8]পয়েন্টার হিসাবে 8 মাপের অ্যারেতে ইন্টিজার যুক্ত করে রাখে
মুশি

267

কেএন্ডআর-এর পরামর্শ অনুসারে সিডিসিএল প্রোগ্রাম ব্যবহার করুন ।

$ 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 )

@ankii বেশিরভাগ লিনাক্স বিতরণে একটি প্যাকেজ থাকা উচিত। আপনি নিজের বাইনারিও তৈরি করতে পারেন।
সিগজুইস

আহ না, উল্লেখ না করার জন্য দুঃখিত এখানে। যদি পাওয়া যায় তবে তা দেখতে পাবে, অন্যথায় ওয়েবসাইটটিও ঠিক আছে। this আমাকে এই সম্পর্কে জানানোর জন্য ধন্যবাদ .. এনএলএন পতাকা বিনামূল্যে নির্দ্বিধায়।
ankii

2
@ankii আপনি হোমব্রেইউ থেকে ইনস্টল করতে পারেন (এবং সম্ভবত ম্যাকপোর্টস?)। যদি সেগুলি আপনার স্বাদে না আসে তবে সিডেক্ল.অর্গ.এর উপরের ডানদিকে গিথুব লিঙ্কটি থেকে আপনার নিজের তৈরি করা তুচ্ছ ((আমি কেবল এটি ম্যাকোস মোজভেতে তৈরি করেছি)। তারপরে আপনার প্যাথ-এ কেবল সিডিকেল বাইনারি অনুলিপি করুন। আমি $ PATH / বিনকে সুপারিশ করি, কারণ এর চেয়ে সহজ কিছুতে রুট জড়িত করার দরকার নেই।
সিগজুইস

ওহ রেডমিমে ইনস্টলেশন সম্পর্কে ছোট্ট অনুচ্ছেদটি পড়েনি। নির্ভরতা পরিচালনা করার জন্য কিছু কমান্ড এবং পতাকা .. বারউ ব্যবহার করে ইনস্টল করা। :)
ankii

1
আমি যখন এটি প্রথম পড়ি তখন আমি ভেবেছিলাম: "আমি কখনই এই স্তরে নেমে আসব না"। পরের দিন, আমি এটি ডাউনলোড করেছি।
সিরো সান্তিলি 郝海东 冠状 病 六四 事件 法轮功

126

এটির কোনও অফিসিয়াল নাম আছে কিনা তা আমি জানি না তবে আমি এটিকে ডান-বাম থিঙ্গি (টিএম) বলি।

চলকটি শুরু করুন, তারপরে ডান এবং বাম দিকে যান এবং ডানদিকে ... এবং আরও কিছু।

int* arr1[8];

arr1 পূর্ণসংখ্যার জন্য 8 পয়েন্টারের একটি অ্যারে।

int (*arr2)[8];

arr2 8 টি পূর্ণসংখ্যার অ্যারেতে একটি পয়েন্টার (প্রথম বন্ধনী ডান-বামে ব্লক করে) হয়।

int *(arr3[8]);

arr3 পূর্ণসংখ্যার জন্য 8 পয়েন্টারের একটি অ্যারে।

এটি আপনাকে জটিল ঘোষণায় সহায়তা করতে পারে।


19
আমি শুনেছি এটি "দ্য সর্পিল বিধি" নামে উল্লেখ করা হয়েছে, যা এখানে পাওয়া যাবে
চৌকিক

6
@ ইঙ্কব্লেন্ড: সর্পিল নিয়ম ডান-বাম নিয়ম থেকে পৃথক । সাবেক ব্যর্থ মত ক্ষেত্রে int *a[][10]যখন আধুনিক সফল।
কিংবদন্তি

1
@ ডিজেইন আমি ভেবেছিলাম যে শব্দটির সাথে বর্জন স্ট্রস্ট্রপের সাথে কিছু সম্পর্ক আছে :)
অনিরুধ রমনাথন

1
যেমন ইনক্লেন্ড এবং কিংবদন্তি 2 কে বলেছেন, এটি সর্পিল বিধি যা আরও জটিল এবং সব ক্ষেত্রে কাজ করে না, সুতরাং এটি ব্যবহার করার কোনও কারণ নেই।
কোটলময়

( ) [ ]বাম থেকে ডান সাহচর্য এবং ডান থেকে বামের বামদিকে ভুলবেন না* &
মুশি

28
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 

তৃতীয়টি হওয়া উচিত নয়: একটি হ'ল 8 মাপের পূর্ণসংখ্য অ্যারেতে নির্দেশকের একটি অ্যারে? মানে প্রতিটি পূর্ণসংখ্যার অ্যারেগুলি 8 মাপের হবে?
রাশিল পল

2
@ রুশিল: না, শেষ সাবস্ক্রিপ্টটি ( [5]) অন্তঃকরণের মাত্রা উপস্থাপন করে। এর অর্থ (*a[8])এটি প্রথম মাত্রা এবং এটি অ্যারের বাইরের উপস্থাপনা। কি মধ্যে প্রতিটি উপাদান a পয়েন্ট আকার 5. একটি ভিন্ন পূর্ণসংখ্যা অ্যারে
zeboidlund

তৃতীয়টির জন্য ধন্যবাদ। আমি কীভাবে পয়েন্টার অ্যারে লিখতে হবে তা সন্ধান করছি।
Deqing

15

শেষ দুটিটির উত্তরটিও সি-তে সুবর্ণ নিয়ম থেকে কেটে নেওয়া যেতে পারে:

ঘোষণা অনুসরণ অনুসরণ।

int (*arr2)[8];

আপনি যদি ডিফারেন্স করেন তবে কী হবে arr2? আপনি 8 টি পূর্ণসংখ্যার একটি অ্যারে পাবেন।

int *(arr3[8]);

আপনি যদি কোনও উপাদান থেকে নেন তবে কী হবে arr3? আপনি একটি পূর্ণসংখ্যার পয়েন্টার পান।

ফাংশনগুলিতে পয়েন্টারগুলির সাথে ডিল করার সময় এটিও সহায়তা করে। সিগজাইসের উদাহরণ নিতে:

float *(*x)(void )

আপনি যখন অবজ্ঞাপূর্ণ হন তখন কী হয় x? আপনি একটি ফাংশন পাবেন যা আপনি কোনও যুক্তি ছাড়াই কল করতে পারবেন। আপনি যখন ফোন করবেন তখন কি হবে? এটি একটিতে একটি পয়েন্টার ফিরিয়ে দেবে float

অপারেটর অগ্রাধিকার সর্বদা কৃপণ, যদিও। তবে, প্রথম বন্ধনী ব্যবহার করা আসলে বিভ্রান্তিকর হতে পারে কারণ ঘোষণাপত্রটি ব্যবহারের অনুসরণ করে। কমপক্ষে, আমার কাছে, স্বজ্ঞাতসারে arr28 টি পয়েন্টার ইন্টিতে একটি অ্যারের মতো দেখায়, তবে এটি আসলে অন্যভাবে। কিছুটা অভ্যস্ত হয়ে যায়। আপনি যদি আমাকে জিজ্ঞাসা করেন তবে এই ঘোষণাগুলিতে সর্বদা একটি মন্তব্য যুক্ত করার পর্যাপ্ত কারণ :)

সম্পাদনা: উদাহরণ

যাইহোক, আমি কেবল নিম্নলিখিত পরিস্থিতিটি পেরিয়ে গিয়েছি: একটি ফাংশন যা একটি স্ট্যাটিক ম্যাট্রিক্স এবং এটি পয়েন্টার গাণিতিক ব্যবহার করে সারি পয়েন্টারটি সীমা ছাড়িয়েছে কিনা তা দেখতে। উদাহরণ:

#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 &lt; 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: এই নমুনা উন্নত করতে নির্দ্বিধায়!)



3

একটি চলতি নিয়ম, ডান ইউনারী অপারেটর (যেমন হিসাবে [], ()ইত্যাদি) বাম বেশী বেশী অগ্রাধিকার নিতে। সুতরাং, 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
ক্যাকাহুয়েট ফ্রেটো

1
সংস্থাপকটিকে ত্রুটিটি দেওয়ার কারণটি হ'ল এটি ফাংশনটিকে একটি অ্যারে ফেরত হিসাবে ব্যাখ্যা করছে, যেমন পূর্ববর্তী নিয়মের সঠিক ব্যাখ্যা বলে। এটি একটি ঘোষণাপত্র হিসাবে ইলিগাল, তবে আইনী ঘোষণাটি (বা ) এর int *(*ptr)();মতো অভিব্যক্তিটি পরে ব্যবহার করার অনুমতি দেয় । p()[3](*p)()[3]
লুইস কলোরাডো

ঠিক আছে, যদি আমি এটি বুঝতে পারি তবে আপনি এমন একটি ফাংশন তৈরির কথা বলছেন যা কোনও অ্যারের প্রথম উপাদানকে (কোনও অ্যারে নিজেই নয়) একটি পয়েন্টার দেয় এবং পরে সেই ফাংশনটি ব্যবহার করে যেমন এটি অ্যারে ফিরিয়ে দিচ্ছে? আকর্ষণীয় ধারণা। আমি ইহা চেস্টা করব. int *foo(int arr_2[5][5]) { return &(arr_2[2][0]); }এবং এটিকে কল করুন: foo(arr)[4];যা থাকা উচিত arr[2][4], তাই না?
ক্যাকাহুয়েত ফ্রিটো

ঠিক আছে ... তবে আপনি ঠিক ছিলেন, এবং ঘোষণাটি ইগালাল ছিল। :)
লুইস কলোরাডো

2

আমি মনে করি আমরা সাধারণ নিয়মটি ব্যবহার করতে পারি ..

example int * (*ptr)()[];
start from ptr 

" ptrএটি" ডানদিকে যেতে .. পয়েন্টার " হ'ল") "এখন যান এটির একটি" ("বাইরে চলে আসুন ডান" () "সুতরাং" এমন কোনও ফাংশনে যা কোনও আর্গুমেন্ট নেয় না "বামে যান" এবং একটি পয়েন্টার ফেরত "যান" পূর্ণসংখ্যার ডানদিকে "অ্যারে" বাম দিকে যান "


আমি কিছুটা উন্নতি করব: "পিটিআর হ'ল একটি নাম যা" ডানদিকে যান ... এটি ), এখন বাম দিকে যান ... এটি *"পয়েন্টার" ডানদিকে যেতে ... এটি ), এখন বামে যান ... এটি একটি (বেরিয়ে আসুন, ডানদিকে যান ()"এমন একটি ফাংশনে যা" গো ডান ... []" কোনও আর্গুমেন্ট নেয় না এবং" ডান ;প্রান্তে যান, সুতরাং বামে যান ... *"পয়েন্টারগুলিকে" বামে যান ... int"পূর্ণসংখ্যার" নির্দেশ দেয়
কাকাহুতে ফ্রেটো


2

এখানে আমি এটি কীভাবে ব্যাখ্যা করি:

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)আমাদের একটি অ্যারে দেওয়া হয়েছে, যা সমান কিছু তৈরি করে (অ্যারেতে পয়েন্টার)


0

আমার ধারণা দ্বিতীয় ঘোষণাটি অনেকের কাছে বিভ্রান্তিকর। এটি বোঝার একটি সহজ উপায় এখানে।

এর পূর্ণসংখ্যার অ্যারে রাখতে দেয়, যেমন int B[8]

আসুন একটি ভেরিয়েবল এও রয়েছে যা বিকে নির্দেশ করে এখন, A এর মান হ'ল B, অর্থাৎ (*A) == B। সুতরাং একটি পূর্ণসংখ্যার একটি অ্যারে নির্দেশ করে। আপনার প্রশ্নে, আরারটি এ এর ​​মতো is

তেমনিভাবে, int* (*C) [8]সি-তে পূর্ণসংখ্যার সাথে পয়েন্টারগুলির একটি অ্যারের পয়েন্টার।


0
int *arr1[5]

এই ঘোষণাপত্রে, arr1পূর্ণসংখ্যার সাথে 5 পয়েন্টারের অ্যারে হয়। কারণ: স্কোয়ার বন্ধনী * (ডিফারিং অপারেটর) এর চেয়ে বেশি অগ্রাধিকার পেয়েছে। এবং এই ধরণের ক্ষেত্রে, সারিগুলির সংখ্যা স্থির করা হয় (এখানে 5) তবে কলামগুলির সংখ্যা পরিবর্তনশীল।

int (*arr2)[5]

এই ঘোষণাপত্রে, arr25 টি উপাদানের একটি পূর্ণসংখ্য অ্যারের পয়েন্টার। কারণ: এখানে, () বন্ধনীগুলিতে [] এর চেয়ে বেশি অগ্রাধিকার রয়েছে। এবং এই ধরণের ক্ষেত্রে, সারিগুলির সংখ্যা পরিবর্তনশীল, কিন্তু কলামগুলির সংখ্যা স্থির (এখানে 5)।


-7

একটি পূর্ণসংখ্যার সাথে পয়েন্টারে যদি পয়েন্টারটি বাড়ানো হয় তবে এটি পরবর্তী পূর্ণসংখ্যায় যায়।

পয়েন্টারের অ্যারেতে যদি পয়েন্টার বাড়ানো হয় তবে তা পরবর্তী অ্যারেতে চলে যায়


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