'মাপের' (কীভাবে একটি অ্যারের দিকে নির্দেশকারী একটি পয়েন্টার) সন্ধান করবেন?


309

প্রথম বন্ধ, এখানে কিছু কোড:

int main() 
{
    int days[] = {1,2,3,4,5};
    int *ptr = days;
    printf("%u\n", sizeof(days));
    printf("%u\n", sizeof(ptr));

    return 0;
}

অ্যারে যেটি ptrইঙ্গিত করছে তার আকার বের করার কোনও উপায় আছে (কেবল তার আকার দেওয়ার পরিবর্তে, যা 32-বিট সিস্টেমে চারটি বাইট রয়েছে)?


84
আমি সর্বদা মাপের সাথে প্যারেন্স ব্যবহার করেছি - নিশ্চিত এটি এটি একটি ফাংশন কলের মতো দেখায়, তবে আমি মনে করি এটি আরও পরিষ্কার।
পল টমলিন

20
কেন না? আপনার কি অতিরিক্ত অতিরিক্ত বন্ধনীগুলির বিরুদ্ধে কিছু আছে? আমি মনে করি এটি নিজেই তাদের সাথে আরও কিছুটা সহজে পড়ে।
ডেভিড থর্নলি

6
@ পল: ভাল .. ধরে নিচ্ছি যে এই কলটির বাম হাতটি ইন্টির একটি পয়েন্টার, আমি এটি লিখব int * ptr = malloc (4 * আকারের * পিটিআর) হিসাবে; যা আমার কাছে আরও পরিষ্কার। পড়ার মতো কম প্যারেনস এবং গণিতের মতো আক্ষরিক কনসেন্টকে সামনে এনে দেওয়া।
বিনোদন

4
@ অ্যানবাইন্ড - আপনি যখন ইনটসের অ্যারে বলতে চাচ্ছেন তখন পয়েন্টারের একটি অ্যারে বরাদ্দ করবেন না!
পল টমবলিন

6
এখানে কোনও অ্যারের দিকে নির্দেশকারী "পয়েন্টার" নেই। কেবলমাত্র একটি পয়েন্টারটি কোন ইনটকে নির্দেশ করছে।
newacct

উত্তর:


269

না, আপনি পারবেন না। সংকলকটি জানে না যে পয়েন্টারটি কী নির্দেশ করছে। কৌশলগুলি রয়েছে, যেমন পরিচিত ব্যান্ড-অফ-ব্যান্ড মান সহ অ্যারে শেষ করা এবং তারপরে সেই মান পর্যন্ত আকার গণনা করা, তবে এটি ব্যবহার করে না sizeof()

আরেকটি কৌশলটি জ্যান দ্বারা উল্লিখিত একটি , যা কোথাও আকারকে ছড়িয়ে দেওয়া। উদাহরণস্বরূপ, আপনি যদি গতিশীলভাবে অ্যারে বরাদ্দ করেন তবে আপনার প্রয়োজনের চেয়ে একটি ব্লক একটি বড় ইট বরাদ্দ করুন, প্রথম ইনট্রে আকারটি স্ট্যাশ করুন এবং ptr+1অ্যারেতে পয়েন্টার হিসাবে ফিরে আসুন। আপনার যখন আকারের প্রয়োজন হবে তখন পয়েন্টারটি হ্রাস করুন এবং স্ট্যাশড মানটি দেখুন। শুরু থেকে শুরু করে পুরো ব্লকটি খালি মনে রাখবেন, এবং কেবল অ্যারে নয়।


12
আমি এই মুহুর্তে একটি মন্তব্য পোস্ট করার জন্য দুঃখিত তবে সংকলক যদি পয়েন্টারটি কী নির্দেশ করে তা যদি না জানে তবে ফ্রি কীভাবে জানবে যে কত স্মৃতি পরিষ্কার করতে হবে? আমি জানি যে এই তথ্যটি ব্যবহারের জন্য নিখরচায় ফাংশনের জন্য অভ্যন্তরীণভাবে সঞ্চিত। সুতরাং আমার প্রশ্ন কেন 'সংকলকটিও এটি করতে পারে?
viki.omega9

11
@ viki.omega9, কারণ ফ্রি রানটাইমের সময় আকারটি আবিষ্কার করে। সংকলক আকারটি জানতে পারে না কারণ আপনি রানটাইম কারণগুলির উপর নির্ভর করে অ্যারেটিকে আলাদা আকার তৈরি করতে পারেন (কমান্ড লাইন আর্গুমেন্ট, কোনও ফাইলের বিষয়বস্তু, চাঁদের ধাপ ইত্যাদি)।
পল টমলিন

15
দ্রুত অনুসরণ, কেন এমন কোনও ফাংশন নেই যা ফ্রি আকারের আকার ফিরিয়ে দিতে পারে?
viki.omega9

5
ঠিক আছে, আপনি যদি গ্যারান্টি দিতে পারতেন যে ফাংশনটি কেবল ম্যালোসড মেমরি দিয়ে বলা হয়েছিল এবং লাইব্রেরিটি যেভাবে করল সেগুলি মেমোলেসড মেমরিটিকে সর্বাধিক আমি দেখেছি (ফেরত পয়েন্টারের আগে কোনও int ব্যবহার করে) ট্র্যাক করে তবে আপনি একটি লিখতে পারেন। তবে যদি পয়েন্টারটি স্থির অ্যারে বা এর মতো হয় তবে এটি ব্যর্থ হবে। একইভাবে, কোনও গ্যারান্টি নেই যে ম্যালোডযুক্ত মেমরির আকার আপনার প্রোগ্রামে অ্যাক্সেসযোগ্য।
পল টমবলিন

9
@ ভিকি.ওমেগা ৯: অন্য একটি বিষয় মনে রাখবেন তা হ'ল ম্যালোক / ফ্রি সিস্টেমের দ্বারা রেকর্ড করা আকারটি আপনি যে আকার চেয়েছিলেন তা নাও হতে পারে। আপনি 9 বাইট ম্যালোক করেন এবং 16 পান Mall ম্যালোক 3 কে বাইট এবং 4 কে পান। বা অনুরূপ পরিস্থিতি।
Zan Lynx

85

উত্তরটি হল, "না"

সি প্রোগ্রামাররা যা করে তা হ'ল অ্যারের আকারটি কোথাও সঞ্চয় করে। এটি কোনও কাঠামোর অংশ হতে পারে, বা malloc()অ্যারের শুরু হওয়ার আগে একটি দৈর্ঘ্যের মান সঞ্চয় করার জন্য প্রোগ্রামারটি অনুরোধের চেয়ে কিছুটা বেশি এবং মেমরি প্রতারণা করতে পারে ।


3
এটি কীভাবে প্যাসকালীন স্ট্রিংগুলি প্রয়োগ করা হয়
dsm

6
এবং দৃশ্যত পাস্কাল স্ট্রিংগুলিই কেন এক্সেল এত তাড়াতাড়ি চলে!
আদম নায়লর

8
@ অ্যাডাম: এটি দ্রুত। আমি আমার স্ট্রিং বাস্তবায়নের তালিকায় এটি ব্যবহার করি। রৈখিক অনুসন্ধানে এটি অতি দ্রুত - কারণ এটি: লোড আকার, প্রিফেট পোস্ট + আকার, অনুসন্ধানের আকারের সাথে আকারের তুলনা করুন, সমান স্ট্রান্সকিম্প হলে, পরবর্তী স্ট্রিংয়ে যান, পুনরাবৃত্তি করুন। এটি প্রায় 500 টি স্ট্রিং পর্যন্ত বাইনারি অনুসন্ধানের চেয়ে দ্রুত।
জ্যান লিংস

47

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

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

#if !defined(ARRAY_SIZE)
    #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
#endif

int main()
{
    int days[] = {1,2,3,4,5};
    int *ptr = days;
    printf("%u\n", ARRAY_SIZE(days));
    printf("%u\n", sizeof(ptr));
    return 0;
}

আপনি এই জাতীয় ম্যাক্রো থেকে সাবধান থাকার কারণে গুগল করতে পারেন। সাবধান হও.

যদি সম্ভব হয় তবে C ++ stdlib যেমন ভেক্টর যা অনেক বেশি নিরাপদ এবং ব্যবহার করা সহজ।


11
ARRAY_SIZE হ'ল একটি সাধারণ দৃষ্টান্ত যা ব্যবহারিক প্রোগ্রামাররা সর্বত্র ব্যবহার করে।
সানজায়া আর

5
হ্যাঁ এটি একটি সাধারণ দৃষ্টান্ত। আপনার এখনও এটি সাবধানতার সাথে ব্যবহার করা দরকার যদিও এটি ভুলে যাওয়া এবং এটি একটি গতিশীল অ্যারেতে ব্যবহার করা সহজ।
রায়ান

2
হ্যাঁ, ভাল কথা, তবে জিজ্ঞাসা করা প্রশ্নটি পয়েন্টারটির বিষয়ে ছিল, স্ট্যাটিক অ্যারেটি নয়।
পল টমবলিন

2
Argument ARRAY_SIZEম্যাক্রো সর্বদা কাজ করে যদি এর আর্গুমেন্টটি অ্যারে হয় (অর্থাত্ অ্যারের ধরণের প্রকাশ)। আপনার তথাকথিত "গতিশীল অ্যারে" এর জন্য আপনি কখনই আসল "অ্যারে" পান না (অ্যারের ধরণের এক্সপ্রেশন)। (অবশ্যই, আপনি পারবেন না, যেহেতু অ্যারে প্রকারগুলি তাদের আকারটি সংকলন সময়ে অন্তর্ভুক্ত করে)) আপনি কেবলমাত্র প্রথম উপাদানটির জন্য একটি পয়েন্টার পান। আপনার আপত্তিটি "প্যারামিটারটি আসলে একটি স্ট্যাটিক অ্যারে কিনা তা পরীক্ষা করে না" সত্যই বৈধ নয়, যেহেতু তারা অ্যারে হিসাবে আলাদা এবং অন্যটি নয়।
newacct

2
চারদিকে ভাসমান একটি টেম্পলেট ফাংশন রয়েছে যা একই কাজ করে তবে পয়েন্টার ব্যবহারকে আটকাবে।
নাটালি অ্যাডামস

18

মাপের () ব্যবহার না করে সি ++ টেম্পলেটগুলির সাথে একটি পরিষ্কার সমাধান রয়েছে । নিম্নলিখিত getSize () ফাংশনটি কোনও স্ট্যাটিক অ্যারের আকার প্রদান করে:

#include <cstddef>

template<typename T, size_t SIZE>
size_t getSize(T (&)[SIZE]) {
    return SIZE;
}

এখানে একটি foo_t কাঠামোর উদাহরণ রয়েছে :

#include <cstddef>

template<typename T, size_t SIZE>
size_t getSize(T (&)[SIZE]) {
    return SIZE;
}

struct foo_t {
    int ball;
};

int main()
{
    foo_t foos3[] = {{1},{2},{3}};
    foo_t foos5[] = {{1},{2},{3},{4},{5}};
    printf("%u\n", getSize(foos3));
    printf("%u\n", getSize(foos5));

    return 0;
}

আউটপুট:

3
5

স্বরলিপিটি আমি কখনও দেখিনি T (&)[SIZE]। এর অর্থ কি আপনি ব্যাখ্যা করতে পারেন? এছাড়াও আপনি এই প্রসঙ্গে কনস্টেক্সপ্রের উল্লেখ করতে পারেন।
ওয়ার্ল্ডসেন্ডার

2
এটি দুর্দান্ত যদি আপনি সি ++ ব্যবহার করেন এবং আপনার কাছে আসলে অ্যারের ধরণের একটি পরিবর্তনশীল থাকে। তাদের উভয়ই প্রশ্নের ক্ষেত্রে নয়: ভাষাটি সি, এবং ওপি যে জিনিসটি থেকে অ্যারের আকার পেতে চায় তা সাধারণ পয়েন্টার।
ওগুক

এই কোডটি প্রতিটি বিভিন্ন আকার / প্রকারের সংমিশ্রণের জন্য একই কোডটি পুনরায় তৈরি করে কোড ফোলাতে পরিচালিত করবে বা সংকলক দ্বারা অস্তিত্বের বাইরে যাদুকরীভাবে অনুকূলিত?
ব্যবহারকারী 2796283

@ ওয়ার্ল্ডসেন্ডার: অ্যারের প্রকারের রেফারেন্সের জন্য এটি সি ++ বাক্য গঠন (কোনও ভেরিয়েবলের নাম, কেবল একটি আকার এবং উপাদান-ধরণের নয়)।
পিটার কর্ডস

@ ব্যবহারকারী 2796283: সংকলনের সময় এই ফাংশনটি পুরোপুরি অপ্টিমাইজ করা হয়েছে; কোন জাদু প্রয়োজন; এটি কোনও সংজ্ঞাটির সাথে কোনও কিছুর সংমিশ্রণ নয়, এটি কেবল একটি সংকলন-সময় ধ্রুবকের সাথে সন্নিবিষ্ট করা হয়। (তবে একটি ডিবাগ বিল্ডে হ্যাঁ, আপনার কাছে আলাদা আলাদা ফাংশন রয়েছে যা বিভিন্ন ধ্রুবককে ফিরিয়ে দেয় Link লিঙ্কার ম্যাজিক একই ধ্রুবক ব্যবহার করে এমন একত্রীকরণ করতে পারে The কলারটি SIZEআরগ হিসাবে পাস হয় না , এটি একটি টেম্পলেট প্যারাম রয়েছে) ইতিমধ্যে ফাংশন সংজ্ঞা দ্বারা পরিচিত হতে হবে।)
পিটার কর্ডস

5

এই নির্দিষ্ট উদাহরণের জন্য, হ্যাঁ, যদি আপনি টাইপডেফ ব্যবহার করেন (নীচে দেখুন)। অবশ্যই, আপনি যদি এটি এভাবে করেন তবে আপনি SIZEOF_DAYS ব্যবহার করার মতোই বন্ধ থাকবেন, যেহেতু আপনি জানেন যে পয়েন্টারটি কী নির্দেশ করছে।

যদি আপনার কাছে কোনও (অকার্যকর *) পয়েন্টার থাকে, যেমন ম্যালোক () বা এর মতো করে ফিরে আসে, তবে, না, পয়েন্টারটি কোন ডাটা স্ট্রাকচারটির দিকে ইশারা করছে এবং তা নির্ধারণ করার কোনও উপায় নেই এবং এর আকার নির্ধারণের কোনও উপায় নেই।

#include <stdio.h>

#define NUM_DAYS 5
typedef int days_t[ NUM_DAYS ];
#define SIZEOF_DAYS ( sizeof( days_t ) )

int main() {
    days_t  days;
    days_t *ptr = &days; 

    printf( "SIZEOF_DAYS:  %u\n", SIZEOF_DAYS  );
    printf( "sizeof(days): %u\n", sizeof(days) );
    printf( "sizeof(*ptr): %u\n", sizeof(*ptr) );
    printf( "sizeof(ptr):  %u\n", sizeof(ptr)  );

    return 0;
} 

আউটপুট:

SIZEOF_DAYS:  20
sizeof(days): 20
sizeof(*ptr): 20
sizeof(ptr):  4

5

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

এখানে এতক্ষণ সরবরাহ করা থেকে পৃথক একটি প্রস্তাবনা, এটি কাজ করবে: পরিবর্তে অ্যারেতে একটি পয়েন্টারটি পাস করুন। এই পরামর্শটি সি ++ শৈলীর মতামতের অনুরূপ, বাদে সিটি টেম্পলেট বা রেফারেন্সগুলিকে সমর্থন করে না:

#define ARRAY_SZ 10

void foo (int (*arr)[ARRAY_SZ]) {
    printf("%u\n", (unsigned)sizeof(*arr)/sizeof(**arr));
}

তবে, এই পরামর্শটি আপনার সমস্যার জন্য একদম নির্বোধ, যেহেতু ফাংশনটি সংখ্যায়িত হয়েছে অ্যারেটির আকারটি সঠিকভাবে পাস করার জন্য এটি সংজ্ঞায়িত করা হয়েছে (সুতরাং, অ্যারেটিতে মাপের কিছু ব্যবহার করার প্রয়োজন নেই)। এটি কী করে তা হ'ল কিছু ধরণের সুরক্ষা। এটি আপনাকে অযাচিত আকারের অ্যারেতে যেতে নিষেধ করবে।

int x[20];
int y[10];
foo(&x); /* error */
foo(&y); /* ok */

যদি ফাংশনটি অ্যারের যে কোনও আকারে পরিচালনা করতে সক্ষম হয় বলে মনে করা হয়, তবে আপনাকে অতিরিক্ত তথ্য হিসাবে ফাংশনটির আকার দিতে হবে।


1
"একা অ্যারের ক্ষয়িষ্ণু পয়েন্টার মান থেকে আপনি এই তথ্যটি পেতে পারেন না" এবং একটি কর্মসংস্থান সরবরাহ করার জন্য +1।
সর্বাধিক

4

কোন যাদু সমাধান নেই। সি কোন প্রতিবিম্বিত ভাষা নয়। বস্তুগুলি তারা কী তা স্বয়ংক্রিয়ভাবে জানে না।

তবে আপনার অনেক পছন্দ আছে:

  1. স্পষ্টতই, একটি পরামিতি যুক্ত করুন
  2. কলটি একটি ম্যাক্রোতে মোড়ক করুন এবং স্বয়ংক্রিয়ভাবে একটি প্যারামিটার যুক্ত করুন
  3. আরও জটিল বস্তু ব্যবহার করুন। একটি কাঠামো নির্ধারণ করুন যা গতিশীল অ্যারে এবং অ্যারের আকার ধারণ করে contains তারপরে, কাঠামোর ঠিকানাটি পাস করুন।

বস্তুগুলি তারা কী তা জানে। তবে আপনি যদি কোনও সাবওবজেক্টের দিকে ইঙ্গিত করেন তবে সম্পূর্ণ অবজেক্ট বা বৃহত্তর সাবোবজেক্ট সম্পর্কে তথ্য পাওয়ার কোনও উপায় নেই
এমএম

2

এই সমস্যাটির আমার সমাধান হ'ল অ্যারের দৈর্ঘ্যটি অ্যারে সম্পর্কে একটি মেটা-তথ্য হিসাবে স্ট্রাক্ট অ্যারেতে সংরক্ষণ করা।

#include <stdio.h>
#include <stdlib.h>

struct Array
{
    int length;

    double *array;
};

typedef struct Array Array;

Array* NewArray(int length)
{
    /* Allocate the memory for the struct Array */
    Array *newArray = (Array*) malloc(sizeof(Array));

    /* Insert only non-negative length's*/
    newArray->length = (length > 0) ? length : 0;

    newArray->array = (double*) malloc(length*sizeof(double));

    return newArray;
}

void SetArray(Array *structure,int length,double* array)
{
    structure->length = length;
    structure->array = array;
}

void PrintArray(Array *structure)
{       
    if(structure->length > 0)
    {
        int i;
        printf("length: %d\n", structure->length);
        for (i = 0; i < structure->length; i++)
            printf("%g\n", structure->array[i]);
    }
    else
        printf("Empty Array. Length 0\n");
}

int main()
{
    int i;
    Array *negativeTest, *days = NewArray(5);

    double moreDays[] = {1,2,3,4,5,6,7,8,9,10};

    for (i = 0; i < days->length; i++)
        days->array[i] = i+1;

    PrintArray(days);

    SetArray(days,10,moreDays);

    PrintArray(days);

    negativeTest = NewArray(-5);

    PrintArray(negativeTest);

    return 0;
}

তবে আপনি যে অ্যারে সঞ্চয় করতে চান তার সঠিক দৈর্ঘ্য নির্ধারণ সম্পর্কে আপনার যত্ন নেওয়া উচিত, কারণ আমাদের বন্ধুরা যেমন ব্যাপকভাবে ব্যাখ্যা করেছেন, এই দৈর্ঘ্যটি পরীক্ষা করার কোনও উপায় নয়।


2

আপনি এর মতো কিছু করতে পারেন:

int days[] = { /*length:*/5, /*values:*/ 1,2,3,4,5 };
int *ptr = days + 1;
printf("array length: %u\n", ptr[-1]);
return 0;

1

না, আপনি sizeof(ptr)অ্যারের আকারটি ptrনির্দেশ করছেন তা সন্ধান করতে ব্যবহার করতে পারবেন না ।

অতিরিক্ত মেমরি বরাদ্দ করা হলেও (অ্যারের আকারের চেয়ে বেশি) আপনি যদি অতিরিক্ত জায়গায় দৈর্ঘ্য সঞ্চয় করতে চান তবে সহায়ক হবে।


1
int main() 
{
    int days[] = {1,2,3,4,5};
    int *ptr = days;
    printf("%u\n", sizeof(days));
    printf("%u\n", sizeof(ptr));

    return 0;
}

দিনের আকার [] 20 যা উপাদানগুলির কোনও নয় * এর ডেটা ধরণের আকার। যদিও পয়েন্টারের আকার 4 তবে তা ইশারা করছে তা বিবেচ্য নয়। কারণ একটি পয়েন্টার তার ঠিকানা সঞ্চয় করে অন্য উপাদানকে নির্দেশ করে।


1
সাইজফুফ (পিটিআর) হ'ল পয়েন্টারের আকার এবং মাপের (* পিটিআর) যা পয়েন্টারের আকার
অমিতাভা

0
 #define array_size 10

 struct {
     int16 size;
     int16 array[array_size];
     int16 property1[(array_size/16)+1]
     int16 property2[(array_size/16)+1]
 } array1 = {array_size, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

 #undef array_size

অ্যারে_সাইজ আকারের পরিবর্তনশীলটিতে চলে যাচ্ছে :

#define array_size 30

struct {
    int16 size;
    int16 array[array_size];
    int16 property1[(array_size/16)+1]
    int16 property2[(array_size/16)+1]
} array2 = {array_size};

#undef array_size

ব্যবহার হ'ল:

void main() {

    int16 size = array1.size;
    for (int i=0; i!=size; i++) {

        array1.array[i] *= 2;
    }
}

0

স্ট্রিংগুলিতে '\0'শেষে একটি অক্ষর থাকে যাতে স্ট্রিংয়ের দৈর্ঘ্য এর মতো ফাংশনগুলি ব্যবহার করে বাড়ানো যায় strlen। উদাহরণস্বরূপ, একটি পূর্ণসংখ্যার অ্যারে সহ সমস্যাটি হ'ল আপনি কোনও মানকে শেষ মান হিসাবে ব্যবহার করতে পারবেন না তাই একটি সম্ভাব্য সমাধান হ'ল অ্যারে সম্বোধন করা এবং বিন্দুটিকে শেষের মান হিসাবে ব্যবহার করা NULL

#include <stdio.h>
/* the following function will produce the warning:
 * ‘sizeof’ on array function parameter ‘a’ will
 * return size of ‘int *’ [-Wsizeof-array-argument]
 */
void foo( int a[] )
{
    printf( "%lu\n", sizeof a );
}
/* so we have to implement something else one possible
 * idea is to use the NULL pointer as a control value
 * the same way '\0' is used in strings but this way
 * the pointer passed to a function should address pointers
 * so the actual implementation of an array type will
 * be a pointer to pointer
 */
typedef char * type_t; /* line 18 */
typedef type_t ** array_t;
int main( void )
{
    array_t initialize( int, ... );
    /* initialize an array with four values "foo", "bar", "baz", "foobar"
     * if one wants to use integers rather than strings than in the typedef
     * declaration at line 18 the char * type should be changed with int
     * and in the format used for printing the array values 
     * at line 45 and 51 "%s" should be changed with "%i"
     */
    array_t array = initialize( 4, "foo", "bar", "baz", "foobar" );

    int size( array_t );
    /* print array size */
    printf( "size %i:\n", size( array ));

    void aprint( char *, array_t );
    /* print array values */
    aprint( "%s\n", array ); /* line 45 */

    type_t getval( array_t, int );
    /* print an indexed value */
    int i = 2;
    type_t val = getval( array, i );
    printf( "%i: %s\n", i, val ); /* line 51 */

    void delete( array_t );
    /* free some space */
    delete( array );

    return 0;
}
/* the output of the program should be:
 * size 4:
 * foo
 * bar
 * baz
 * foobar
 * 2: baz
 */
#include <stdarg.h>
#include <stdlib.h>
array_t initialize( int n, ... )
{
    /* here we store the array values */
    type_t *v = (type_t *) malloc( sizeof( type_t ) * n );
    va_list ap;
    va_start( ap, n );
    int j;
    for ( j = 0; j < n; j++ )
        v[j] = va_arg( ap, type_t );
    va_end( ap );
    /* the actual array will hold the addresses of those
     * values plus a NULL pointer
     */
    array_t a = (array_t) malloc( sizeof( type_t *) * ( n + 1 ));
    a[n] = NULL;
    for ( j = 0; j < n; j++ )
        a[j] = v + j;
    return a;
}
int size( array_t a )
{
    int n = 0;
    while ( *a++ != NULL )
        n++;
    return n;
}
void aprint( char *fmt, array_t a )
{
    while ( *a != NULL )
        printf( fmt, **a++ );   
}
type_t getval( array_t a, int i )
{
    return *a[i];
}
void delete( array_t a )
{
    free( *a );
    free( a );
}

আপনার কোড মন্তব্যে পূর্ণ, তবে আমি মনে করি আপনি কোডের বাইরে কীভাবে এটি সাধারণ পাঠ্য হিসাবে কাজ করে তার কিছু সাধারণ ব্যাখ্যা যুক্ত করলে এটি সবকিছু সহজ করে তুলবে। আপনি কি আপনার প্রশ্নটি সম্পাদনা করে তা করতে পারেন? ধন্যবাদ!
ফ্যাবিও বলেছেন মনিকা

প্রতিটি এলিমেন্টের জন্য পয়েন্টারের একটি অ্যারে তৈরি করা যাতে আপনি এটির লিনিয়ার সন্ধান করতে পারেন NULLসম্ভবত কোনও পৃথক sizeসরাসরি সংরক্ষণ করার জন্য সম্ভবত সবচেয়ে কম দক্ষ বিকল্প কল্পনাযোগ্য । বিশেষত আপনি যদি অতিরিক্ত সময় জুড়ে এই অতিরিক্ত স্তরটি ব্যবহার করেন।
পিটার কর্ডস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.