সি এবং সি ++ সংকলকগুলি যখন কখনও প্রয়োগ না করা হয় তখন ফাংশন স্বাক্ষরে অ্যারে দৈর্ঘ্যের অনুমতি দেয় কেন?


131

আমার শেখার সময়কালে আমি এটি খুঁজে পেয়েছি:

#include<iostream>
using namespace std;
int dis(char a[1])
{
    int length = strlen(a);
    char c = a[2];
    return length;
}
int main()
{
    char b[4] = "abc";
    int c = dis(b);
    cout << c;
    return 0;
}  

ভেরিয়েবলের মধ্যে int dis(char a[1]), [1]মনে হয় কিছুই করার মতো নয় এবং কিছুতেই কাজ করে না
, কারণ আমি ব্যবহার করতে পারি a[2]। ঠিক যেমন int a[]বা char *a। আমি জানি অ্যারের নামটি একটি পয়েন্টার এবং কীভাবে অ্যারেটি পৌঁছে দিতে হয়, তাই আমার ধাঁধাটি এই অংশটি সম্পর্কে নয়।

আমি যা জানতে চাই তা সংকলকরা কেন এই আচরণের অনুমতি দেয় ( int a[1])। বা এর অন্য অর্থ আছে যা আমি জানিনা?


6
এটি কারণ আপনি আসলে ফাংশনে অ্যারে পাস করতে পারবেন না।
এড এস

37
আমি মনে করি যে এখানে প্রশ্নটি কেন সি আপনাকে একটি প্যারামিটারকে অ্যারে টাইপ হিসাবে ঘোষণা করার অনুমতি দেয় যখন এটি ঠিক যেভাবে পয়েন্টারের মতো ঠিক আচরণ করবে।
ব্রায়ান

8
@ ব্রায়ান: আমি নিশ্চিত নই যে এটি আচরণের পক্ষে বা বিপক্ষে কোনও যুক্তি কিনা, তবে এটি যুক্তিযুক্ত প্রকারটি typedefঅ্যারে টাইপের সাথে যুক্ত হলে প্রযোজ্যও । সুতরাং আর্গুমেন্ট ধরণের "পয়েন্টার টু পয়েন্টার" কেবল সিনট্যাকটিক চিনির সাথে প্রতিস্থাপন []করা নয় *, এটি আসলে টাইপ সিস্টেমের মধ্য দিয়ে চলছে। va_listঅ্যারে বা অ-অ্যারে টাইপের সাথে সংজ্ঞায়িত করা যেতে পারে এমন কিছু স্ট্যান্ডার্ড ধরণের জন্য এটির বাস্তব-বিশ্ব পরিণতি রয়েছে ।
আর .. গীটহাব বন্ধ করুন সহায়তা আইসিসি

4
@songyuanyao আপনি কিছু সি (এবং সি ++) এ সম্পূর্ণভাবে বিসদৃশ না সাধা পারেন পয়েন্টার ব্যবহার করছে: int dis(char (*a)[1])। তারপর, আপনি একটি অ্যারের একটি পয়েন্টার পাস: dis(&b)। আপনি যদি সি বৈশিষ্ট্যগুলি ব্যবহার করতে ইচ্ছুক হন যা সি ++ তে বিদ্যমান নেই, আপনি এ জাতীয় জিনিসগুলি বলতে পারেন void foo(int data[static 256])এবং int bar(double matrix[*][*])এটি সম্পূর্ণ কৃমিতে পারে।
স্টুয়ার্ট ওলসেন

1
পছন্দ করেছেন মুল বিষয় হ'ল যে কেউ এটি সংজ্ঞায়িত করে সে এটি সেভাবে সংজ্ঞায়িত করে।
ব্যবহারকারী 253751

উত্তর:


156

এটি অ্যারেগুলিকে ফাংশনগুলিতে প্রেরণের জন্য সিনট্যাক্সের একটি স্পর্শ।

প্রকৃতপক্ষে সি-তে কোনও অ্যারে পাস করা সম্ভব নয় আপনি যদি সিনট্যাক্স লিখেন যা দেখে মনে হয় এটি অ্যারে পাস করা উচিত, তবে যা ঘটেছিল তা হ'ল অ্যারের প্রথম উপাদানটির একটি পয়েন্টার পরিবর্তে পাস করা হয়।

যেহেতু পয়েন্টারে কোনও দৈর্ঘ্যের তথ্য অন্তর্ভুক্ত করা হয়নি, []তাই ফাংশনটির আনুষ্ঠানিক প্যারামিটার তালিকায় থাকা সামগ্রীগুলি আসলে উপেক্ষা করা হবে।

এই সিনট্যাক্সটিকে অনুমতি দেওয়ার সিদ্ধান্তটি ১৯ 1970০ এর দশকে হয়েছিল এবং তখন থেকেই অনেক বিভ্রান্তি সৃষ্টি করেছে ...


21
নন-সি প্রোগ্রামার হিসাবে আমি এই উত্তরটি খুব অ্যাক্সেসযোগ্য মনে করি। +1
asteri

21
"এই বাক্য
গঠনের

8
এটি সত্য তবে এটি সিনট্যাক্স ব্যবহার করে কেবলমাত্র আকারের একটি অ্যারে পাস করাও সম্ভব void foo(int (*somearray)[20])। এই ক্ষেত্রে 20 টি কলার সাইটগুলিতে প্রয়োগ করা হয়।
v.oddou

14
-1 একজন সি প্রোগ্রামার হিসাবে আমি এই উত্তরটি ভুল বলে মনে করি। []প্যাটের উত্তরে দেখানো হিসাবে বহুমাত্রিক অ্যারেগুলিকে উপেক্ষা করা হবে না। সুতরাং অ্যারে সিনট্যাক্স সহ প্রয়োজনীয় ছিল। তদুপরি, একক মাত্রিক অ্যারেতে কোনও কিছুই সংকেত সংকেত প্রদান বন্ধ করে না।
ব্যবহারকারী 694733

7
"আপনার []" এর বিষয়বস্তু দ্বারা, আমি প্রশ্নের কোড সম্পর্কে বিশেষভাবে কথা বলছি। এই সিনট্যাক্স তর্কটি মোটেই প্রয়োজন ছিল না, পয়েন্টার সিনট্যাক্স ব্যবহার করে একই জিনিস অর্জন করা যায়, অর্থাত্ যদি কোনও পয়েন্টারটি পাস হয়ে যায় তবে প্যারামিটারটি পয়েন্টার ডিক্লেটার হিসাবে প্রয়োজন। উদাহরণস্বরূপ প্যাট উদাহরণস্বরূপ,void foo(int (*args)[20]); কঠোরভাবে বলা সি এর বহু-মাত্রিক অ্যারে নেই; তবে এতে অ্যারে রয়েছে যার উপাদানগুলি অন্যান্য অ্যারে হতে পারে। এটি কিছুই পরিবর্তন করে না।
এমএম

143

প্রথম মাত্রার দৈর্ঘ্য অগ্রাহ্য করা হয়, তবে সংকলককে অফসেটগুলি সঠিকভাবে গণনা করার জন্য অতিরিক্ত মাত্রার দৈর্ঘ্য প্রয়োজনীয় necessary নিম্নলিখিত উদাহরণে, fooফাংশনটি একটি দ্বি-মাত্রিক অ্যারেতে একটি পয়েন্টারটি পাস করা হয়।

#include <stdio.h>

void foo(int args[10][20])
{
    printf("%zd\n", sizeof(args[0]));
}

int main(int argc, char **argv)
{
    int a[2][20];
    foo(a);
    return 0;
}

প্রথম মাত্রার আকার [10]উপেক্ষা করা হয়; সংকলকটি আপনাকে শেষের সূচিকরণ থেকে বিরত রাখবে না (লক্ষ্য করুন যে আনুষ্ঠানিকভাবে 10 টি উপাদান চায় তবে প্রকৃত মাত্র 2 সরবরাহ করে)। যাইহোক, দ্বিতীয় মাত্রার আকার [20]প্রতিটি সারিটির প্রান্ত নির্ধারণ করতে ব্যবহৃত হয় এবং এখানে, আনুষ্ঠানিকটি অবশ্যই বাস্তবের সাথে মেলে। আবার, সংকলকটি আপনাকে দ্বিতীয় মাত্রার শেষেও সূচীকরণ থেকে বিরত রাখবে না।

অ্যারের গোড়া থেকে কোনও উপাদানে অফসেট args[row][col]বাই নির্ধারণ করা হয়:

sizeof(int)*(col + 20*row)

মনে রাখবেন যে যদি col >= 20, তবে আপনি প্রকৃতপক্ষে পরবর্তী সারিতে ইনডেক্স করবেন (বা পুরো অ্যারের শেষের দিকে)।

sizeof(args[0])80আমার মেশিনে যেখানে ফিরে আসে sizeof(int) == 4। তবে, যদি আমি গ্রহণের চেষ্টা করি তবে আমি sizeof(args)নিম্নলিখিত সংকলকটির সতর্কতা পেয়েছি:

foo.c:5:27: warning: sizeof on array function parameter will return size of 'int (*)[20]' instead of 'int [10][20]' [-Wsizeof-array-argument]
    printf("%zd\n", sizeof(args));
                          ^
foo.c:3:14: note: declared here
void foo(int args[10][20])
             ^
1 warning generated.

এখানে, সংকলকটি সতর্ক করছে যে এটি কেবলমাত্র পয়েন্টারের আকার দিতে চলেছে যার মধ্যে অ্যারের নিজেই আকারের পরিবর্তে অ্যারে ক্ষয় হয়ে গেছে।


খুব দরকারী - এটির সাথে সামঞ্জস্যতা 1-ডি ক্ষেত্রে চটকদার কারণ হিসাবে প্রশংসনীয়।
jwg

1
এটি 1-ডি কেসের মতো একই ধারণা। C এবং C ++ এ 2-D অ্যারের মতো দেখতে আসলে 1-D অ্যারে, যার প্রতিটি উপাদানই অন্য 1-D অ্যারে। এক্ষেত্রে আমাদের 10 টি উপাদান সহ একটি অ্যারে রয়েছে, যার প্রতিটি উপাদান "20 ইন্টের অ্যারে"। আমার পোস্টে বর্ণিত হিসাবে, যা আসলে ফাংশনে পাস হয় তা হ'ল প্রথম উপাদানটির পয়েন্টার args। এই ক্ষেত্রে, আরোগুলির প্রথম উপাদানটি হ'ল "20 ইন্টের অ্যারে"। পয়েন্টারগুলিতে প্রকারের তথ্য অন্তর্ভুক্ত থাকে; যা পাস হয় তা হ'ল "20 ইন্টের অ্যারে পয়েন্টার"।
এমএম

9
হ্যাঁ, এটাই কি int (*)[20]ধরণের; "20 ints এর অ্যারে পয়েন্টার"।
প্যাট করুন

33

সমস্যা এবং কীভাবে এটি সি ++ এ কাটিয়ে উঠবেন

প্যাট এবং ম্যাট দ্বারা সমস্যাটি ব্যাপকভাবে ব্যাখ্যা করা হয়েছে । সংকলকটি মূলত অ্যারের আকারের প্রথম মাত্রাকে কার্যকরভাবে কার্যকর আর্গুমেন্টের আকারটিকে উপেক্ষা করছে is

অন্যদিকে, সি ++ এ আপনি সহজেই এই সীমাবদ্ধতাটি দুটি উপায়ে কাটিয়ে উঠতে পারেন:

  • রেফারেন্স ব্যবহার করে
  • ব্যবহার std::array(সি ++ 11 সাল থেকে)

তথ্যসূত্র

যদি আপনার ফাংশনটি কেবল বিদ্যমান অ্যারেটি পড়ার বা সংশোধন করার চেষ্টা করছে (এটি অনুলিপি করছে না) আপনি সহজেই উল্লেখগুলি ব্যবহার করতে পারেন।

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

void reset(int (&array)[10]) { ... }

এটি কেবলমাত্র সূক্ষ্মভাবে কাজ করবে না , তবে এটি অ্যারের মাত্রাও প্রয়োগ করবে

উপরের কোডটি জেনেরিক করতে আপনি টেমপ্লেটগুলি ব্যবহার করতে পারেন :

template<class Type, std::size_t N>
void reset(Type (&array)[N]) { ... }

এবং অবশেষে আপনি constসঠিকতার সুবিধা নিতে পারেন । আসুন একটি ফাংশন বিবেচনা করুন যা 10 টি উপাদানের অ্যারে প্রিন্ট করে:

void show(const int (&array)[10]) { ... }

constকোয়ালিফায়ার প্রয়োগ করে আমরা সম্ভাব্য পরিবর্তনগুলি রোধ করছি ।


অ্যারেগুলির জন্য স্ট্যান্ডার্ড লাইব্রেরি ক্লাস

যদি আপনি আমার মতো করে উপরের সিনট্যাক্সটিকে কুরুচিপূর্ণ এবং অপ্রয়োজনীয় উভয়ই বিবেচনা করেন তবে আমরা এটি ক্যানের মধ্যে ফেলে দিতে পারি এবং ব্যবহার করতে পারি std::array পরিবর্তে (সি ++ 11) ।

রিফ্যাক্টর কোডটি এখানে:

void reset(std::array<int, 10>& array) { ... }
void show(std::array<int, 10> const& array) { ... }

আশ্চর্য কি না? আমি আপনাকে জেনেরিক কোড ট্রিক আগে শিখিয়েছি তা এখনও উল্লেখযোগ্য নয় :

template<class Type, std::size_t N>
void reset(std::array<Type, N>& array) { ... }

template<class Type, std::size_t N>
void show(const std::array<Type, N>& array) { ... }

কেবল এটিই নয়, আপনি অনুলিপি এবং সিমেন্টিকটি বিনামূল্যে সরাতে পারেন। :)

void copy(std::array<Type, N> array) {
    // a copy of the original passed array 
    // is made and can be dealt with indipendently
    // from the original
}

তাহলে তুমি কিসের জন্য অপেক্ষা করছ? ব্যবহার করুন std::array


2
@ কিয়েটস, আমি দুঃখিত যে আপনার প্রস্তাবিত সম্পাদনাটি বাতিল হয়ে গেছে, তবে আমরা স্বয়ংক্রিয়ভাবে ধরে নিই যে সি ++ 11 ব্যবহার করা হচ্ছে , অন্যথায় নির্দিষ্ট না করা পর্যন্ত।
জুতো

এটি সত্য, তবে আমাদের দেওয়া লিঙ্কের ভিত্তিতে কোনও সমাধান কেবল সি ++ 11 কিনা তাও আমরা নির্দিষ্ট করে নেব।
ট্র্যাকলি

@trlkly, আমি সম্মত আমি সেই অনুযায়ী উত্তরটি সম্পাদনা করেছি। এটা ইশারা জন্য ধন্যবাদ।
জুতো

9

এটি সি এর একটি মজাদার বৈশিষ্ট্য যা আপনি খুব ঝোঁক থাকলে আপনাকে কার্যকরভাবে নিজেকে পাদদেশে গুলি করতে দেয়।

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

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


3
হ্যাঁ. সি কম্পাইলারের উপর প্রোগ্রামারকে বিশ্বাস করার জন্য ডিজাইন করা হয়েছে। আপনি যদি এত সহজেই কোনও অ্যারের শেষের সূচকে সূচনা করেন তবে আপনাকে অবশ্যই বিশেষ এবং ইচ্ছাকৃত কিছু করা উচিত।
জন

7
আমি 14 বছর আগে সি তে প্রোগ্রামিংয়ে দাঁত কেটেছি। আমার সমস্ত প্রফেসর বলেছেন, যে বাক্যটি আমার সাথে অন্য সকলের চেয়ে বেশি আটকে আছে, "সি প্রোগ্রামাররা লিখেছিলেন, প্রোগ্রামারদের জন্য।" ভাষা অত্যন্ত শক্তিশালী। (ক্লিচের জন্য প্রস্তুত) চাচা বেন যেমন আমাদের শিখিয়েছিলেন, "দুর্দান্ত শক্তি দিয়ে, আসে মহান দায়িত্ব comes"
অ্যান্ড্রু ফালঙ্গা

6

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

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

typedef struct {
  int a[10];
} myarray_t;

myarray_t my_function(myarray_t foo) {

  myarray_t bar;

  ...

  return bar;

}

আপনাকে এই জাতীয় উপাদানগুলি অ্যাক্সেস করতে হবে: foo.a [1]। অতিরিক্ত ".a" অদ্ভুত লাগতে পারে তবে এই কৌশলটি সি ভাষায় দুর্দান্ত কার্যকারিতা যুক্ত করে।


7
আপনি কম্পাইল-টাইম চেকিংয়ের সাথে রানটাইম বাউন্ড চেকিংকে বিভ্রান্ত করছেন।
বেন ভয়েগট

@ বেন ভয়েগ্ট: আমি আসল প্রশ্ন হিসাবে কেবল সীমানা যাচাইয়ের কথা বলছি।
ব্যবহারকারী 34814

2
@ ব্যবহারকারী 34814 সংকলন-সময় সীমা পরীক্ষা করা টাইপ চেকিংয়ের সুযোগের মধ্যে। বেশ কয়েকটি উচ্চ-স্তরের ভাষা এই বৈশিষ্ট্যটি সরবরাহ করে।
লুশেনকো

5

সংকলকটি বলতে যে MyAray কমপক্ষে 10 টি ints এর অ্যারে নির্দেশ করে:

void bar(int myArray[static 10])

আপনি আমারআরে [10] এ অ্যাক্সেস করলে একটি ভাল সংকলক আপনাকে একটি সতর্কতা দিতে হবে। "স্ট্যাটিক" কীওয়ার্ড ব্যতীত 10 এর অর্থ মোটেও কিছু নয়।


1
আপনি যদি 11 তম এবং অ্যারিতে কমপক্ষে 10 টি উপাদান থাকে তবে কোনও সংকলককে কেন সতর্ক করা উচিত ?
নওহ্নহোফ

সম্ভবত এটি এর কারণ কম্পাইলার কেবলমাত্র আপনার কমপক্ষে 10 টি উপাদান রয়েছে তা প্রয়োগ করতে পারে । আপনি যদি 11 তম উপাদানটি অ্যাক্সেস করার চেষ্টা করেন তবে এটি নিশ্চিত হওয়া যায় না যে এটি বিদ্যমান (যদিও তা রয়েছে)।
ডিলান ওয়াটসন 14

2
আমি মনে করি না যে এটি স্ট্যান্ডার্ডটির সঠিক পড়া। [static]কম্পাইলার সতর্ক করতে আপনি পারবেন কল bar একটি সঙ্গে int[5]। আপনি কীসের মধ্যে প্রবেশ করতে পারবেন তা নির্ধারণ করে না bar। পুরোপুরি কলার দিকে on
ট্যাব

3
error: expected primary-expression before 'static'এই সিনট্যাক্সটি কখনও দেখেনি। এটি স্ট্যান্ডার্ড সি বা সি ++ হওয়ার সম্ভাবনা কম।
v.oddou

3
@ ভি.ওডডউ, এটি সি 99.৯, 6..7.৫.২ এবং 7.7.৫.৩ এ নির্দিষ্ট করা হয়েছে।
স্যামুয়েল এডউইন ওয়ার্ড

5

এটি সি এর একটি সুপরিচিত "বৈশিষ্ট্য", যা সি ++ এ চলে গেছে কারণ সি ++ সি কোডটি সঠিকভাবে সংকলন করার কথা বলেছে।

বিভিন্ন দিক থেকে সমস্যা দেখা দেয়:

  1. একটি অ্যারের নাম একটি পয়েন্টারের সাথে সম্পূর্ণ সমতুল্য বলে মনে করা হয়।
  2. সিটিকে দ্রুত বলে মনে করা হয়, মূলত বিকাশকারী এক ধরণের "উচ্চ-স্তরের এসেমব্লার" (বিশেষত প্রথম "পোর্টেবল অপারেটিং সিস্টেম": ইউনিক্স লেখার জন্য ডিজাইন করা হয়েছে), তাই এটি "লুকানো" কোড সন্নিবেশ করানোর কথা নয় ; রানটাইম পরিসীমা পরীক্ষা করা এইভাবে "নিষিদ্ধ"।
  3. একটি স্ট্যাটিক অ্যারে বা গতিশীল এক অ্যাক্সেস করতে জেনারেটেড মেশিন কোড (হয় স্ট্যাকের মধ্যে বা বরাদ্দ) আসলে আলাদা।
  4. যেহেতু ডাকা ফাংশনটি অ্যারের "ধরণের" টি আর্গুমেন্ট হিসাবে পাস করতে পারে তা সবই জানতে পারে না যে সমস্ত কিছু পয়েন্টার হিসাবে বিবেচিত হবে এবং এরূপ হিসাবে বিবেচিত হবে।

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

যাইহোক, সর্বোপরি সমস্ত সত্য আর সত্য নয়: পি

বেশিরভাগ আধুনিক সি / সি ++ কম্পাইলার কি সমর্থন সীমা চেক, কিন্তু মান প্রয়োজন (অনুন্নত সহাবস্থানযোগ্যতা জন্য) এটা ডিফল্টরূপে বন্ধ করতে হবে। জিসিসির সাম্প্রতিকতম সংস্করণগুলি উদাহরণস্বরূপ, "-O3 -Wall -Wextra" এবং "-ফাউন্ডস-চেকিং" সহ সম্পূর্ণ রান-টাইম সীমা পরীক্ষা করে কম্পাইল-টাইম রেঞ্জ চেক করুন।


হয়তো সি ++ 20 বছর আগে সি কোডটি সংকলন করার কথা ছিল , তবে এটি অবশ্যই নেই এবং দীর্ঘ সময় ধরে নেই (সি ++ 98? সি 99 কমপক্ষে, যা কোনও নতুন সি ++ মানক দ্বারা "স্থির" হয়নি)।
হাইড

@ হাইড এটি আমার কাছে কিছুটা কঠোর মনে হচ্ছে। স্ট্রস্ট্রস্ট্রকে উদ্ধৃত করতে "ছোট ব্যতিক্রম ছাড়া, সি হ'ল সি ++ এর একটি উপসেট" " (সি ++ পিএল 4 র্থ সংস্করণ, সেকেন্ড। 1.2.1)। যদিও সি ++ এবং সি উভয়ই আরও বিবর্তিত হয়েছে এবং সর্বশেষ সি সংস্করণ থেকে এমন বৈশিষ্ট্য বিদ্যমান রয়েছে যা সর্বশেষ সি ++ সংস্করণে নেই, সামগ্রিকভাবে আমি মনে করি যে স্ট্রাস্ট্রাপের উদ্ধৃতিটি এখনও বৈধ।
এমভিডাব্লু

এই মিলেনিয়ামে লিখিত @ এমভিডাব্লু মোস্ট সি কোড, যা অসতর্কতাযুক্ত বৈশিষ্ট্যগুলি এড়িয়ে ইচ্ছাকৃতভাবে সি ++ সামঞ্জস্যপূর্ণ নয়, তারা C99 ব্যবহার করবে struct MyStruct s = { .field1 = 1, .field2 = 2 }; স্ট্রাক্ট শুরু করার জন্য মনোনীত ইনিশিয়ালাইজারস সিনট্যাক্স ( ) ব্যবহার করবে, কারণ এটি স্ট্রাক্টের সূচনা করার জন্য এতটা পরিষ্কার উপায় way ফলস্বরূপ, বেশিরভাগ বর্তমান সি কোডটি স্ট্যান্ডার্ড সি ++ কম্পাইলার দ্বারা প্রত্যাখ্যান করা হবে, কারণ বেশিরভাগ সি কোড স্ট্রাক্ট শুরু করবে।
হাইড

@ এমভিডাব্লু সম্ভবত এটি বলা যেতে পারে যে, সি ++ সি এর সাথে সামঞ্জস্যপূর্ণ বলে মনে করা হচ্ছে, যাতে কোনও কোড আপলোড করা হয় তবে কোড লেখা সম্ভব যা সি এবং সি ++ উভয় সংকলককেই সংহত করবে। তবে এর একটি উপসেট ব্যবহার করা দরকার কেবল সি ++ এর উপসেট নয়, সি এবং সি ++ উভয়ের
হাইড

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

3

সি শুধুমাত্র ধরনের একটি প্যারামিটার রুপান্তর করা হবে না int[5]মধ্যে *int; ঘোষণা দেওয়া typedef int intArray5[5];, এটা ধরনের একটি প্যারামিটার রূপান্তরিত হবে intArray5থেকে *intহিসাবে ভাল। কিছু পরিস্থিতি রয়েছে যেখানে এই আচরণটি বিজোড় হলেও কার্যকর হয় (বিশেষত va_listসংজ্ঞায়িত মতো জিনিসগুলির সাথে stdargs.h, যা কিছু বাস্তবায়ন অ্যারে হিসাবে সংজ্ঞায়িত করে)। প্যারামিটার হিসাবে কোনও ধরণের int[5](মাত্রা উপেক্ষা করে) হিসাবে সংজ্ঞায়িত করার অনুমতি দেওয়া অযৌক্তিক হবে তবে int[5]সরাসরি নির্দিষ্ট করার অনুমতি দেবে না ।

আমি অ্যারের ধরণের প্যারামিটারগুলি সি এর পরিচালনা পরিচালনাকে অযৌক্তিক বলে মনে করি, তবে এটি একটি অ্যাড-হক ভাষা নেওয়ার প্রচেষ্টার ফলাফল, যার বেশিরভাগ অংশ বিশেষভাবে সংজ্ঞায়িত বা চিন্তাভাবনাযুক্ত ছিল না এবং আচরণগতভাবে সামনে আসতে চেষ্টা করেছিল স্পেসিফিকেশন যা বিদ্যমান প্রোগ্রামগুলির জন্য বিদ্যমান বাস্তবায়নগুলির সাথে সামঞ্জস্যপূর্ণ। সেই আলোতে দেখা গেলে সি এর অনেকগুলি স্ফুটিত বিষয়গুলি বোঝা যায়, বিশেষত যদি কেউ বিবেচনা করে যে তাদের মধ্যে যখন অনেকগুলি আবিষ্কার করা হয়েছিল, তখন আমরা যে ভাষার আজকাল জানি সেই ভাষার বৃহত অংশগুলি এখনও বিদ্যমান ছিল না। পূর্বসূরীর সি, বিসিপিএল বলে আমি যা বুঝি, কম্পাইলাররা সত্যই পরিবর্তনশীল ধরণের ট্র্যাক রাখেনি। একটি ঘোষণা int arr[5];সমান ছিল int anonymousAllocation[5],*arr = anonymousAllocation;; বরাদ্দ একবার রাখা হয়েছিল। সংকলক না জানত না যত্নও করল নাarrএকটি পয়েন্টার বা একটি অ্যারে ছিল। উভয় হিসাবে অ্যাক্সেস করা হলে , এটি কীভাবে ঘোষিত হয়েছিল তা নির্বিশেষে এটি পয়েন্টার হিসাবে বিবেচিত হবে।arr[x] বা*arr


1

একটি জিনিস যা এখনও উত্তর দেওয়া হয়নি তা হ'ল আসল প্রশ্ন।

ইতিমধ্যে প্রদত্ত উত্তরগুলি ব্যাখ্যা করে যে অ্যারেগুলি সি বা সি ++ এর মধ্যে কোনও ফাংশনে মান দ্বারা পাস করা যাবে না। তারা আরও ব্যাখ্যা করে যে কোনও প্যারামিটার হিসাবে ঘোষিত হয় int[]এটির মতো আচরণ করা হয় int *এবং টাইপের একটি পরিবর্তনশীলint[] যেমন ফাংশনে যেতে পারে।

তবে তারা ব্যাখ্যা করে না কেন স্পষ্টভাবে অ্যারের দৈর্ঘ্য সরবরাহ করতে কখনই ত্রুটি করা হয়নি।

void f(int *); // makes perfect sense
void f(int []); // sort of makes sense
void f(int [10]); // makes no sense

এইগুলির শেষটি কেন ত্রুটি নয়?

এর কারণ হ'ল এটি টাইপিডেফগুলির সাথে সমস্যা সৃষ্টি করে।

typedef int myarray[10];
void f(myarray array);

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


0

এটি সংকলকরা অ্যারে পাসের আকার প্রত্যাশার সাথে একই কিনা তা পরীক্ষা করতে সক্ষম হওয়ার অনুমতি দেওয়া হয়েছে। কম্পাইলাররা যদি কোনও সমস্যা না ঘটে তবে সতর্ক করতে পারে।

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