সি পয়েন্টার: স্থির আকারের একটি অ্যারেতে নির্দেশ করা


119

এই প্রশ্নটি সি গুরুর কাছে চলে গেল:

সি-তে, নিম্নলিখিত হিসাবে একটি পয়েন্টার ঘোষণা করা সম্ভব:

char (* p)[10];

.. যা মূলত বলেছে যে এই পয়েন্টারটি 10 ​​টি অক্ষরের অ্যারে নির্দেশ করে। এটির মতো একটি পয়েন্টার ঘোষণা করার মতো ঝরঝরে বিষয় হ'ল আপনি যদি বিভিন্ন আকারের অ্যারের একটি পয়েন্টার পিতে নির্ধারণ করার চেষ্টা করেন তবে আপনি একটি সংকলন সময় ত্রুটি পাবেন। আপনি পি কে একটি সাধারণ চর পয়েন্টারের মান নির্ধারণ করার চেষ্টা করলে এটি আপনাকে একটি সংকলন সময় ত্রুটিও দেয়। আমি এটি জিসিসি দিয়ে চেষ্টা করেছি এবং মনে হচ্ছে এটিএসআই, সি 89 এবং সি 99 এর সাথে কাজ করবে।

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

void foo(char * p, int plen);

আপনি যদি একটি নির্দিষ্ট আকারের বাফারটি আশা করেন, আপনি কেবল প্লেনের মানটি পরীক্ষা করে দেখবেন। তবে, আপনার গ্যারান্টি দেওয়া যায় না যে যে ব্যক্তি আপনাকে পি পাঠিয়েছে তিনি আপনাকে সেই বাফারে যথাযথ বৈধ মেমরির অবস্থান দেবেন। আপনাকে বিশ্বাস করতে হবে যে এই ফাংশনটি বলেছেন তিনি ঠিকঠাক কাজ করছেন। অন্য দিকে:

void foo(char (*p)[10]);

.. কলকারীকে আপনাকে নির্দিষ্ট আকারের বাফার দিতে বাধ্য করবে।

এটি খুব দরকারী বলে মনে হচ্ছে তবে আমি কখনও দেখিনি যে কোনও কোডেই আমি আগে কখনও প্রচার করেছি।

আমার প্রশ্ন হ'ল: লোকেরা এভাবে পয়েন্টার ঘোষণা না করার কোনও কারণ আছে কি? আমি কি কিছু সুস্পষ্ট ক্ষতি দেখছি না?


3
দ্রষ্টব্য: C99 যেহেতু শিরোনামের পরামর্শ অনুসারে অ্যারেটি নির্দিষ্ট আকারের 10হবে না, সুযোগের কোনও পরিবর্তনশীল দ্বারা প্রতিস্থাপন করা যেতে পারে
এমএম

উত্তর:


173

আপনি আপনার পোস্টে যা বলছেন তা একেবারে সঠিক। আমি বলব যে প্রতিটি সি বিকাশকারী ঠিক একই আবিষ্কার এবং ঠিক একই সিদ্ধান্তে আসে যখন তারা সি ভাষার সাথে নির্দিষ্ট দক্ষতার পর্যায়ে পৌঁছায়।

আপনার অ্যাপ্লিকেশন ক্ষেত্রের নির্দিষ্টকরণ নির্দিষ্ট নির্দিষ্ট আকারের অ্যারের জন্য ডাকে (অ্যারের আকারটি একটি সংকলন-সময় ধ্রুবক), পয়েন্টার-থেকে-অ্যারে প্যারামিটার ব্যবহার করে কোনও ফাংশনে এই জাতীয় অ্যারে পাস করার একমাত্র সঠিক উপায় is

void foo(char (*p)[10]);

(সি ++ ভাষায় এটিও রেফারেন্স সহ করা হয়

void foo(char (&p)[10]);

)।

এটি ভাষা-স্তরের প্রকারের চেকিং সক্ষম করবে, যা নিশ্চিত করবে যে ঠিক সঠিক আকারের অ্যারেটি আর্গুমেন্ট হিসাবে সরবরাহ করা হয়েছে। প্রকৃতপক্ষে, অনেক ক্ষেত্রে লোকেরা এই কৌশলটি স্পষ্টভাবেই ব্যবহার করে, এমনকি এটি উপলব্ধি না করেই, টাইপডেফ নামের পিছনে অ্যারের প্রকারটি লুকিয়ে রাখে

typedef int Vector3d[3];

void transform(Vector3d *vector);
/* equivalent to `void transform(int (*vector)[3])` */
...
Vector3d vec;
...
transform(&vec);

অতিরিক্ত নোট করুন যে উপরের কোড সম্পর্কিত সঙ্গে পরিবর্তিত হয় Vector3dএকটি অ্যারে অথবা একটি হচ্ছে টাইপ struct। আপনি Vector3dযে কোনও সময় সংজ্ঞাটি আরে থেকে structপিছনে ফিরে যেতে পারেন এবং আপনাকে ফাংশন ঘোষণাটি পরিবর্তন করতে হবে না decla উভয় ক্ষেত্রেই ফাংশনগুলি "রেফারেন্স দ্বারা" একটি সামগ্রিক বস্তু গ্রহণ করবে (এর ব্যতিক্রম আছে তবে এই আলোচনার প্রসঙ্গে এটি সত্য)।

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

কিন্তু বাস্তবে, অ্যারে পাস করার জন্য পয়েন্টারটি প্রথম উপাদানটিতে ব্যবহার করা একটি খুব কুলুঙ্গিক কৌশল, একটি কৌশল, যা খুব নির্দিষ্ট উদ্দেশ্যে কাজ করে: এর এক এবং একমাত্র উদ্দেশ্য হ'ল বিভিন্ন আকারের অ্যারেগুলি পাস করা (যেমন রান-টাইম আকার) । যদি আপনার সত্যিই রান-টাইম আকারের অ্যারেগুলি প্রক্রিয়া করতে সক্ষম হতে হয়, তবে এ জাতীয় অ্যারেটি পাশ করার যথাযথ উপায়টি অতিরিক্ত পরামিতি দ্বারা সরবরাহিত কংক্রিটের আকারের সাথে তার প্রথম উপাদানটির পয়েন্টার দ্বারা হয় is

void foo(char p[], unsigned plen);

আসলে, অনেক ক্ষেত্রে রান-টাইম আকারের অ্যারেগুলি প্রক্রিয়া করতে সক্ষম হওয়া খুব দরকারী, যা পদ্ধতির জনপ্রিয়তায়ও অবদান রাখে। অনেক সি বিকাশকারী কখনও স্থির আকারের অ্যারে প্রক্রিয়া করার প্রয়োজনের মুখোমুখি হন না (বা কখনও চিনতে পারেন না), ফলে সঠিক স্থির-আকারের কৌশলটি থেকে গাফেল থাকেন।

তবুও, যদি অ্যারের আকারটি স্থির থাকে তবে এটি কোনও উপাদানকে নির্দেশক হিসাবে প্রেরণ করে

void foo(char p[])

একটি বড় কৌশল-স্তরের ত্রুটি, যা দুর্ভাগ্যক্রমে আজকের দিনে বরং এটি ব্যাপকভাবে ছড়িয়ে পড়ে। পয়েন্টার-টু-অ্যারে কৌশল এমন ক্ষেত্রে একটি আরও ভাল পদ্ধতির।

স্থির আকারের অ্যারে পাসিং কৌশলটি গ্রহণে বাধা হয়ে উঠতে পারে এমন আরও একটি কারণ হ'ল গতিশীলভাবে বরাদ্দ হওয়া অ্যারেগুলি টাইপ করার ক্ষেত্রে নিষ্পাপ পদ্ধতির আধিপত্য। উদাহরণস্বরূপ, যদি প্রোগ্রামটি নির্দিষ্ট ধরণের অ্যারেগুলির জন্য কল করে char[10](আপনার উদাহরণ হিসাবে), একজন গড় বিকাশকারী mallocযেমন অ্যারেগুলিকে

char *p = malloc(10 * sizeof *p);

এই অ্যারেটি হিসাবে ঘোষিত কোনও ফাংশনে পাস করা যাবে না

void foo(char (*p)[10]);

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

char (*p)[10] = malloc(sizeof *p);

এটি অবশ্যই উপরের ঘোষণায় সহজেই পাস করা যেতে পারে foo

foo(p);

এবং সংকলক সঠিক টাইপ চেকিং সঞ্চালন করবে। তবে আবার, এটি অপ্রস্তুত সি বিকাশকারীকে অত্যধিক বিভ্রান্ত করছে, এ কারণেই আপনি এটি প্রায়শই "সাধারণ" দৈনিক গড় কোডে দেখতে পাবেন না।


2
উত্তরটি কীভাবে আকারে সফল হয়, কীভাবে প্রায়শই ব্যর্থ হয় এবং কীভাবে সর্বদা ব্যর্থ হয় তার একটি খুব সংক্ষিপ্ত এবং তথ্যমূলক বিবরণ প্রদান করে। বেশিরভাগ সি / সি ++ ইঞ্জিনিয়ারদের আপনার পর্যবেক্ষণগুলি বুঝতে পারে না, এবং তাই তারা পরিবর্তে তারা বুঝতে পারে এমন কিছু করে যা আমি কিছুক্ষণের মধ্যে দেখলাম এমন আরও ভবিষ্যদ্বাণীমূলক বিষয়গুলির মধ্যে একটি, এবং ঘোমটাটি বর্ণিত নির্ভুলতার সাথে তুলনা করে কিছুই নয়। সিরিয়াসলি, স্যার। দুর্দান্ত উত্তর
WhozCraig

আমি এই উত্তরটির উপর ভিত্তি করে কিছু কোড রিফেক্টর করেছি, ক্যু এবং এ উভয়ের জন্য ব্র্যাভো এবং ধন্যবাদ
পেরি

1
আপনি কীভাবে constএই কৌশলটি দিয়ে সম্পত্তি পরিচালনা করেন তা জানতে আগ্রহী । একটি const char (*p)[N]যুক্তি একটি পয়েন্টারের সাথে সামঞ্জস্যপূর্ণ বলে মনে হয় না char table[N];বিপরীতে, একটি সাধারণ char*পিটিআর একটি const char*যুক্তির সাথে সুসংগত থাকে ।
সায়ান

4
এটি উল্লেখ করা সহায়ক হতে পারে যে আপনার অ্যারের কোনও উপাদান অ্যাক্সেস করতে আপনার করা উচিত (*p)[i]এবং করা উচিত নয় *p[i]। পরেরটি অ্যারের আকারে লাফিয়ে উঠবে, যা আপনি যা চান তা প্রায় নয়। কমপক্ষে আমার জন্য, এই সিনট্যাক্সটি শেখার ফলে একটি ভুল প্রতিরোধ না করে বরং ভুল হয়েছে; আমি ঠিক একটি ফ্লোট * পাস করার সাথে সাথে সঠিক কোডটি পেয়েছি।
অ্যান্ড্রু ওয়াগনার

1
হ্যাঁ @ মিকি, আপনি যা পরামর্শ দিয়েছেন তা হ'ল constপরিবর্তনের উপাদানগুলির একটি অ্যারের নির্দেশক। এবং হ্যাঁ, এটি পয়েন্টার থেকে অপরিবর্তনীয় উপাদানগুলির অ্যারে থেকে সম্পূর্ণ আলাদা।
সায়ান

11

আমি AndreyT এর উত্তরে যুক্ত করতে চাই (যদি কেউ এই বিষয়টিতে আরও তথ্যের সন্ধানে এই পৃষ্ঠায় হোঁচট খায়):

আমি যখন এই ঘোষণাগুলি নিয়ে আরও খেলতে শুরু করি তখন বুঝতে পারি যে তাদের সাথে সি-তে (স্পষ্টত সি ++ তে নেই) জড়িত বড় ধরনের প্রতিবন্ধকতা রয়েছে। আপনি যে ফোনটি লিখেছেন তাতে কোনও কলারকে কনস্ট পয়েন্টার দিতে চান এমন পরিস্থিতি থাকা মোটামুটি সাধারণ। দুর্ভাগ্যক্রমে, সি তে এই জাতীয় পয়েন্টার ঘোষণা করার পরে এটি সম্ভব নয় অন্য কথায়, সি স্ট্যান্ডার্ড (6..7.৩ - অনুচ্ছেদ ৮) এর সাথে এই জাতীয় কিছু রয়েছে:


   int array[9];

   const int (* p2)[9] = &array;  /* Not legal unless array is const as well */

এই সীমাবদ্ধতা সি ++ তে উপস্থিত বলে মনে হয় না, এই ধরণের ঘোষণাকে আরও কার্যকর করে তোলে। তবে সি এর ক্ষেত্রে, যখনই আপনি স্থির আকারের বাফারের কাছে কোনও কনস্ট পয়েন্টার চান না (যদি না বাফার নিজেই কনস্টেস্ট হিসাবে ঘোষণা না করা হয়) তবে এটি নিয়মিত পয়েন্টার ঘোষণায় ফিরে যেতে হবে। আপনি এই মেল থ্রেডে আরও তথ্য সন্ধান করতে পারেন: লিঙ্ক পাঠ্য

এটি আমার মতে একটি গুরুতর প্রতিবন্ধকতা এবং এটি সি এর মধ্যে সাধারণত লোকেরা সাধারণত এইভাবে পয়েন্টার ঘোষণা না করার অন্যতম প্রধান কারণ হতে পারে অন্যটি হ'ল এটিও যে বেশিরভাগ লোক জানে না যে আপনি এটির মতো একটি পয়েন্টার ঘোষণা করতে পারেন as AndreyT নির্দেশ করেছেন।


2
এটি একটি সংকলক নির্দিষ্ট সমস্যা বলে মনে হচ্ছে। আমি জিসিসি ৪.৯.১ ব্যবহার করে সদৃশ করতে সক্ষম হয়েছি, তবে ঝাঁকুনি ৩.৪.২ কোনও কনস্ট্যান্ট থেকে কোনও সমস্যা ছাড়াই কোনও কনস্ট্যান্ড থেকে যেতে সক্ষম হয়েছিল। আমি সি 11 স্পেস পড়েছিলাম (আমার সংস্করণে পি 9 ... অংশটি দুটি যোগ্য প্রকারের সাথে সামঞ্জস্যপূর্ণ হওয়ার বিষয়ে কথা বলছে) এবং সম্মত হন যে এই রূপান্তরগুলি অবৈধ বলে মনে হচ্ছে। তবে আমরা অনুশীলনে জানি যে আপনি সর্বদা সতর্কতা ছাড়াই স্বয়ংক্রিয়ভাবে চর * থেকে চর কনস্টে রূপান্তর করতে পারেন। আইএমও, ঝাঁকুনি জিসিসি-র চেয়ে এটির ক্ষেত্রে আরও সামঞ্জস্যপূর্ণ, যদিও আমি আপনার সাথে একমত যে এই অনুমানটি এই কোনও স্বয়ংক্রিয় রূপান্তরকে নিষিদ্ধ করেছে বলে মনে হচ্ছে।
ডগ রিচার্ডসন

4

স্পষ্ট কারণ এই কোডটি সংকলন করে না:

extern void foo(char (*p)[10]);
void bar() {
  char p[10];
  foo(p);
}

একটি অ্যারের ডিফল্ট প্রচার কোনও অযোগ্য পয়েন্টার।

আরো দেখুন এই প্রশ্নের ব্যবহার foo(&p)কাজ করা উচিত।


3
অবশ্যই foo (p) কাজ করবে না, foo 10 টি উপাদানের একটি অ্যারেতে একটি পয়েন্টার চেয়েছে যাতে আপনার অ্যারের ঠিকানাটি পাস করতে হবে ...
ব্রায়ান আর বন্ডি

9
কিভাবে এটি "সুস্পষ্ট কারণ"? এটি স্পষ্টতই বুঝতে পেরেছে যে ফাংশনটি কল করার উপযুক্ত উপায় foo(&p)
এএনটি

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

2

আরও প্রকারের পরীক্ষা করা সক্ষম করতে আমি এই বাক্য গঠনটিও ব্যবহার করতে চাই।

তবে আমি এটিও সম্মত করি যে পয়েন্টার ব্যবহারের বাক্য গঠন এবং মানসিক মডেলটি সহজ, এবং মনে রাখা সহজ।

আমি পেরিয়ে এসেছি আরও কিছু বাধা এখানে।

  • অ্যারে অ্যাক্সেস করতে ব্যবহার করা দরকার (*p)[]:

    void foo(char (*p)[10])
    {
        char c = (*p)[3];
        (*p)[0] = 1;
    }

    পরিবর্তে স্থানীয় পয়েন্টার-টু-চার ব্যবহার করার জন্য এটি লোভনীয়:

    void foo(char (*p)[10])
    {
        char *cp = (char *)p;
        char c = cp[3];
        cp[0] = 1;
    }

    তবে এটি সঠিক ধরণের ব্যবহারের উদ্দেশ্যকে আংশিকভাবে পরাস্ত করবে।

  • পয়েন্টার-থেকে-অ্যারেতে অ্যারের ঠিকানা বরাদ্দ করার সময় একটিকে অ্যাড্রেস-অফ অপারেটরটি ব্যবহার করতে হবে:

    char a[10];
    char (*p)[10] = &a;

    অ্যাড্রেস-অফ অপারেটর &aএটিকে নির্ধারণ করার জন্য সঠিক টাইপের সাহায্যে পুরো অ্যারের ঠিকানা পেয়ে যায় p। অপারেটর ছাড়াই aস্বয়ংক্রিয়ভাবে অ্যারের প্রথম উপাদানটির ঠিকানায় রূপান্তরিত হয় same&a[0] , যার আলাদা ধরন রয়েছে।

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

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

  • পয়েন্টার-থেকে-অ্যারে (সাধারণ শিরোলেখ ফাইলটিতে) জন্য কোনও প্রকার তৈরি করতে কখন ব্যবহৃত typedefহয় না , তারপরে একটি বিশ্বব্যাপী পয়েন্টার-টু অ্যারে externফাইলগুলিতে ভাগ করে নেওয়ার জন্য আরও জটিল ঘোষণার প্রয়োজন:

    fileA:
    char (*p)[10];
    
    fileB:
    extern char (*p)[10];

1

ঠিক আছে, সহজভাবে বলতে গেলে সি সেভাবে কাজ করে না। Tপ্রথম দিকের পয়েন্টার হিসাবে টাইপের একটি অ্যারে প্রায় পাস করা হয়T এবং এটিই আপনি পান।

এটি কিছু শীতল এবং মার্জিত আলগোরিদিম যেমন মঞ্জুরির সাথে অ্যারের মাধ্যমে লুপিংয়ের অনুমতি দেয়

*dst++ = *src++

খারাপ দিকটি হ'ল আকারটির পরিচালনা আপনার উপর নির্ভর করে। দুর্ভাগ্যক্রমে, আন্তরিকতার সাথে এটি করতে ব্যর্থতা সি কোডিংয়ে লক্ষ লক্ষ বাগ, এবং / বা দুর্বোধ্য শোষণের সুযোগ সৃষ্টি করেছে।

আপনি সিতে যা জিজ্ঞাসা করেন তার কাছাকাছি যা হয় তা প্রায় ক struct (মান দ্বারা) বা একটি নির্দেশকের কাছাকাছি (রেফারেন্স সহ)) যতক্ষণ পর্যন্ত এই ক্রিয়াকলাপের উভয় পক্ষেই একই স্ট্রাক্ট প্রকারটি ব্যবহৃত হয় ততক্ষণ, যে কোডটি রেফারেন্সটি দেয় এবং কোড যেগুলি ব্যবহার করে তা উভয়ই হ্যান্ডল করার ডেটার আকার সম্পর্কে একমত হয়।

আপনার স্ট্রাক্টে আপনি যা চান ডেটা থাকতে পারে; এটিতে আপনার নির্ধারিত আকারের অ্যারে থাকতে পারে contain

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


1

আপনি বিভিন্ন ধরণের অক্ষরের অ্যারে ঘোষণা করতে পারেন:

char p[10];
char* p = (char*)malloc(10 * sizeof(char));

কোনও ফাংশনের প্রোটোটাইপ যা মান অনুসারে একটি অ্যারে নেয়:

void foo(char* p); //cannot modify p

বা রেফারেন্স দ্বারা:

void foo(char** p); //can modify p, derefernce by *p[0] = 'f';

বা অ্যারের সিনট্যাক্স দ্বারা:

void foo(char p[]); //same as char*

2
ভুলে যাবেন না যে একটি স্থির-আকারের অ্যারেটিও গতিময় হিসাবে বরাদ্দ করা যেতে পারে char (*p)[10] = malloc(sizeof *p)
এএনটি

চর অ্যারে [] এবং চর * পিটিআর এর পার্থক্যের মধ্যে আরও বিস্তারিত আলোচনার জন্য এখানে দেখুন। stackoverflow.com/questions/1807530/...
t0mm13b

1

আমি এই সমাধানটি সুপারিশ করব না

typedef int Vector3d[3];

যেহেতু এটি সত্যটিকে অস্পষ্ট করে যে ভেক্টর 3 ডি এর একটি প্রকার রয়েছে যা আপনার অবশ্যই জানা উচিত। প্রোগ্রামাররা সাধারণত একই ধরণের বিভিন্ন ধরণের ভেরিয়েবল আশা করে না। বিবেচনা :

void foo(Vector3d a) {
   Vector3D b;
}

যেখানে আকারের এক! = আকারের বি


তিনি এটিকে সমাধান হিসাবে পরামর্শ দিচ্ছিলেন না। তিনি কেবল উদাহরণ হিসাবে এটি ব্যবহার করছিলেন।
ফিগারাসেসা

হুঁ। কেন একরকম sizeof(a)নয় sizeof(b)?
sherrellbc

0

সম্ভবত আমি কিছু মিস করছি, তবে ... যেহেতু অ্যারেগুলি ধ্রুবক পয়েন্টার, মূলত এর অর্থ এটি পয়েন্টারগুলির কাছে যাওয়ার কোনও মানে নেই passing

আপনি কি শুধু ব্যবহার করতে পারবেন না void foo(char p[10], int plen);?


4
অ্যারেগুলি ধ্রুবক পয়েন্টার নয়। দয়া করে অ্যারে সম্পর্কে কিছু জিজ্ঞাসিত প্রশ্নাবলী পড়ুন।
এএনটি

2
এখানে গুরুত্বপূর্ণ বিষয়গুলির জন্য (পরামিতি হিসাবে ইউনিফিমেনশনাল অ্যারে), আসল বিষয়টি হ'ল তারা ধ্রুবক পয়েন্টারগুলিতে ক্ষয় হয়। দয়া করে কীভাবে কম প্যাডেন্টিক হবেন সে সম্পর্কে একটি FAQ পড়ুন।
-তে

-2

আমার সংকলকটিতে (বনাম ২০০৮) এটি char (*p)[10]চরিত্রের পয়েন্টারের অ্যারে হিসাবে আচরণ করে , যেমন কোনও বন্ধনী নেই, এমনকি যদি আমি সি ফাইল হিসাবে সংকলন করি। সংকলক এই "পরিবর্তনশীল" জন্য সমর্থন? যদি তাই হয় তবে এটি ব্যবহার না করার একটি বড় কারণ।


1
-১ ভুল। এটি vs2008, বনাম 2010, জিসিসিতে দুর্দান্ত কাজ করে। : বিশেষ করে এই উদাহরণে কাজ করে জরিমানা stackoverflow.com/a/19208364/2333290
kotlomoy
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.