অ্যারের প্যারামিটারের আকার কেন মূলের মতো নয়?


104

একটি অ্যারের আকার কেন প্যারামিটার হিসাবে প্রধান হিসাবে প্রেরণ করা হয় না?

#include <stdio.h>

void PrintSize(int p_someArray[10]);

int main () {
    int myArray[10];
    printf("%d\n", sizeof(myArray)); /* As expected, 40 */
    PrintSize(myArray);/* Prints 4, not 40 */
}

void PrintSize(int p_someArray[10]){
    printf("%d\n", sizeof(p_someArray));
}

উত্তর:


103

একটি অ্যারে-টাইপ স্পষ্টভাবে পয়েন্টার টাইপে রূপান্তরিত হয় যখন আপনি এটি কোনও ফাংশনে পাস করেন।

সুতরাং,

void PrintSize(int p_someArray[10]) {
    printf("%zu\n", sizeof(p_someArray));
}

এবং

void PrintSize(int *p_someArray) {
    printf("%zu\n", sizeof(p_someArray));
}

সমতুল্য সুতরাং আপনি যা পাবেন তার মানsizeof(int*)


1
সি ++ তে আপনি ফাংশনটি উল্লেখ করে অ্যারে পাস করতে পারেন তবে আপনি সিতে এটি করতে পারবেন না
প্রসূন সৌরভ

13
আপনাকে আলাদা প্যারামিটার হিসাবে অ্যারের আকারটি পাস করতে হবে। তারপরে অ্যারের আকার আকারের (* p_someArray) * দৈর্ঘ্য হবে
আরিক টেনিক

13
গৌণ নিট: sizeofঅপারেটর কোনও ধরণের অবজেক্ট ফেরত দেয় size_t, তাই আপনার এটি %zu(সি 99) দিয়ে মুদ্রণ করা উচিত , বা intযদি আপনি %dআপনার printfকলগুলিতে উপরের মতো ব্যবহার করেন তবে এটি কাস্ট করা উচিত ।
অলোক সিংহল

4
অলোকের বক্তব্য সঠিক। মুদ্রণ (..) এ ভুল ফর্ম্যাট স্পেসিফায়ার ব্যবহার হ'ল ইউবি B
প্রসূন সৌরভ

1
@ Chris_45: গ এর কোন রেফারেন্স আছে, কিন্তু সি আপনি হিসাবে সমগ্র অ্যারের পয়েন্টার দ্বারা একটি অ্যারের পাস করতে পারেন: void PrintSize(int (*p_someArray)[10])। ফাংশন ভিতরে আপনি dereference অপারেটর ব্যবহার করে অ্যারের অ্যাক্সেস করতে পারেন *: sizeof(*p_someArray)। এটি সি ++ তে রেফারেন্স ব্যবহার করার মতোই প্রভাব ফেলবে।
এ্যান্ট

18

এটি একটি পয়েন্টার, এজন্য ফাংশনে দ্বিতীয় প্যারামিটার হিসাবে অ্যারের আকার পাস করার জন্য এটি একটি সাধারণ বাস্তবায়ন


16

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

#include <stdio.h>

void PrintSize1 ( int someArray[][10] );
void PrintSize2 ( int someArray[10] );

int main ()
{
    int myArray[10];
    printf ( "%d\n", sizeof myArray ); /* as expected 40 */
    printf ( "%d\n", sizeof ( int[10] ) ); /* requires parens */
    PrintSize1 ( 0 ); /* prints 40, does not evaluate 0[0] */
    PrintSize2 ( 0 ); /* prints 40, someArray unused */
}

void PrintSize1 ( int someArray[][10] )
{
    printf ( "%d\n", sizeof someArray[0] );
}

void PrintSize2 ( int someArray[10] )
{
    printf ( "%d\n", sizeof ( int[10] ) );
}

12

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

কে ও আর উদ্ধার উদ্ধার:

#define N_ELEMENTS(array) (sizeof(array)/sizeof((array)[0])) 

সুতরাং এখন আপনি যেমন করতে পারেন:

int a[10];
...
myfunction(a, N_ELEMENTS(a));

যদি অ্যারের আকার কোডিং সময়ে পাওয়া না যায় তবে কেবল রান টাইমে পাওয়া যায়? অ্যারের আকারকে কঠোর কোডিং না করে গণনার অন্য কোনও উপায় আছে কি?
সাপ্তাহিক

দেখানো পদ্ধতিটি কেবল তখনই কাজ করে, যখন অ্যারের ঘোষণাটি "দৃষ্টিতে" থাকে। অন্যান্য সমস্ত ক্ষেত্রে, আপনাকে ম্যানুয়ালি অ্যারে-দৈর্ঘ্যটি পাস করতে হবে।
এসসি ম্যাডসেন

5

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

 // 10 is superfluous here! You can pass an array of different size!
void PrintSize(int p_someArray[10]);

5

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

void func(int *a)
void func(int a[])
void func(int a
typedef int array_plz[5];
void func(array_plz a)

চারটি ক্ষেত্রেই একটি পয়েন্টার হবে। আপনি যদি বিন্যাসকে কোনও অ্যারে পাস করেন তবে তা অবিলম্বে এর প্রথম উপাদানটির পয়েন্টারে ক্ষয় হবে। (64৪-বিট সিস্টেমে, 64৪-বিট পয়েন্টারটি 32-বিট ইন্টি থেকে দ্বিগুণ বড়, সুতরাং আপনার আকারের অনুপাতটি 2 ফিরে আসে)

এই নিয়মের একমাত্র উদ্দেশ্য historicalতিহাসিক সংকলকগুলির সাথে পিছনের সামঞ্জস্যতা বজায় রাখা যা ফাংশন আর্গুমেন্ট হিসাবে সামগ্রিক মানগুলি পাস করার পক্ষে সমর্থন করে না।

এর অর্থ এই নয় যে কোনও ফাংশনে অ্যারে পাস করা অসম্ভব। অ্যারেটিকে স্ট্রাক্টের মধ্যে এম্বেড করে আপনি এই ওয়ার্টটি ঘুরে দেখতে পারেন (এটি মূলত সি ++ 11 এর এসটিডি :: অ্যারের উদ্দেশ্য):

struct array_rly {
int a[5];
};
void func(struct array_rly a)
{
printf("%zd\n", sizeof(a.a)/sizeof(a.a[0]));  /* prints 5 */
}

বা অ্যারেতে একটি পয়েন্টার দিয়ে:

void func(const int (*a)[5])
{
printf("%zd\n", sizeof(*a)/sizeof((*a)[0]));  /* prints 5 */
}

অ্যারের আকার কোনও সংকলন-সময় ধ্রুবক না হলে আপনি C99 ভেরিয়েবল-দৈর্ঘ্যের অ্যারেগুলির সাথে পয়েন্টার-টু-অ্যারে প্রযুক্তি ব্যবহার করতে পারেন:

void func(int n, const int (*a)[n])
{
printf("%zd\n", sizeof(*a)/sizeof((*a)[0]));  /* prints n */
}

4

সি ++ এ আপনি এই উদ্দেশ্যটির জন্য রেফারেন্স দিয়ে একটি অ্যারে পাস করতে পারেন:

void foo(int (&array)[10])
{
    std::cout << sizeof(array) << "\n";
}

1
এটি কীভাবে সি প্রশ্নে সহায়তা করবে?
alk

3

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


2
সাধারণভাবে, আপনার সর্বদা অ্যারের আকার (উপাদানগুলির সংখ্যা) কোনও ফাংশনে অ্যারাসের সাথে পাস করা উচিত, যদি না আপনি তার আকার নির্ধারণের অন্য কোনও উপায় না পেয়ে থাকেন (যেমন, char[]স্ট্রিং অ্যারের শেষে একটি নাল অক্ষর টার্মিনেটর )।
ডেভিড আর ট্রাইবল

দয়া করে একটি " অজানা অ্যারে " কী?
alk

3

আপনি ফাংশনে অ্যারে পাস করতে পারবেন না।

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

#include <stdio.h>

void PrintSize(int (*p_anArray)[10]);

int main(void) {
    int myArray[10];
    printf("%d\n", sizeof(myArray)); /* as expected 40 */
    PrintSize(&myArray);/* prints 40 */
}

void PrintSize(int (*p_anArray)[10]){
    printf("%d\n", (int) sizeof(*p_anArray));
}

0

আচরণ নকশা দ্বারা হয়।

ফাংশন প্যারামিটার ঘোষণায় একই বাক্য গঠন মানে স্থানীয় ভেরিয়েবল সংজ্ঞার চেয়ে সম্পূর্ণ আলাদা জিনিস।

অন্যান্য উত্তরে কারণ বর্ণিত হয়েছে।


0

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

মজা (int a []) মজার সাথে একই রকম হয় (int * a);

সুতরাং আপনি যখন অ্যারের আকার মুদ্রণ করবেন এটি প্রথম উপাদানটির আকার মুদ্রণ করবে।


সি তে কোনও " রেফারেন্স দ্বারা কল " নেই।
alk

" আপনি যখন অ্যারের আকার মুদ্রণ করবেন এটি প্রথম উপাদানটির আকার প্রিন্ট করবে " "না, এটি একটি পয়েন্টারের আকার মুদ্রণ করে।
alk

-1

'সি' প্রোগ্রামিংয়ে ল্যাঙ্গুয়েঞ্জে 'সাইজফোফ ()' অপারেটর এবং সে বাইটে অবজেক্টের আকার দেয় '' সাইজফ '()' অপারেটরের অবশ্যই একটি বাম-মানের প্রকার (পূর্ণসংখ্যা, ফ্লোট নম্বর, কাঠামো, অ্যারে) হতে হবে )। সুতরাং আপনি যদি বাইটে কোনও অ্যারের আকার জানতে চান তবে আপনি এটি খুব সহজ করতে পারেন ust কেবলমাত্র 'মাপের ()' অপারেটরটি ব্যবহার করুন এবং তার যুক্তির জন্য অ্যারের নামটি ব্যবহার করুন For উদাহরণস্বরূপ:

#include <stdio.h>

main(){

 int n[10];
 printf("Size of n is: %d \n", sizeof(n)); 

}

৩২ বিট সিস্টেমে আউটপুট হবে: এন এর আকার: 40. কারণ 32 সিস্টেমে অ্যান্টিজার 4 বাইটস 64৪x এর মধ্যে এটি 8 বাইটস। এই ক্ষেত্রে আমাদের 10 টি পূর্ণসংখ্যা একটি অ্যারেতে ঘোষণা করা হয়েছে S সুতরাং ফলাফলটি '10 * আকারের ( int- এ) '।

কিছু টিপস:

আমাদের কাছে যদি এমন অ্যারে ঘোষণা করা হয় তবে এটি 'int n [] = {1, 2, 3, ... 155 ..};'। সুতরাং আমরা জানতে চাই যে এই অ্যারেতে কয়টি উপাদান সঞ্চিত রয়েছে। এই অ্যালগরিদম ব্যবহার করুন:

আকারের (নাম_ও_আর_আরে) / আকারের (অ্যারে_ টাইপ)

কোড: # অন্তর্ভুক্ত

প্রধান () {

int n[] = { 1, 2, 3, 44, 6, 7 };
printf("Number of elements: %d \n", sizeof(n) / sizeof(int));
return 0;

}


2
স্ট্যাকওভারফ্লোতে আপনাকে স্বাগতম এবং উত্তর লেখার জন্য ধন্যবাদ। দুর্ভাগ্যক্রমে, এই প্রশ্নের সমাধান করে না, যা বিশেষত sizeof(n)স্থানীয় ভেরিয়েবলের sizeof(arg)জন্য এবং কোনও ফাংশনের যুক্তির পক্ষে পার্থক্য সম্পর্কে , যদিও উভয়ই আপাতদৃষ্টিতে টাইপযুক্ত int[10]
মাইক্রোভাইরাস

-3

অ্যারেগুলি কেবল আলগা আকারের। বেশিরভাগ অংশের জন্য, একটি অ্যারে হ'ল মেমোরিটির পয়েন্টার। আপনার ঘোষণার আকারটি কেবলমাত্র সংকলককে অ্যারের জন্য কত মেমরি বরাদ্দ করতে হবে তা বলে - এটি প্রকারের সাথে সম্পর্কিত নয়, সুতরাং মাপের () কিছুই করার নেই।


3
দুঃখিত, এই উত্তরটি বিভ্রান্তিকর। না অ্যারেগুলি "আলগা আকারের", না তারা "মেমরির দিকে নির্দেশক"। অ্যারেগুলির একটি খুব সঠিক আকার থাকে এবং যে জায়গাগুলির মধ্যে অ্যারের নামটি তার প্রথম উপাদানটির জন্য একটি পয়েন্টারের জন্য দাঁড়িয়ে থাকে সেগুলি সি মানক দ্বারা নির্দিষ্টভাবে নির্দিষ্ট করা থাকে।
জেনস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.