সি পরিবর্তনশীল ঘোষণার স্থান


129

আমি দীর্ঘদিন ধরে ভেবেছিলাম যে সি তে, ফাংশনের শুরুতে সমস্ত ভেরিয়েবলগুলি ঘোষণা করতে হয়েছিল। আমি জানি যে C99 তে নিয়মগুলি সি ++ এর মতোই তবে সি 98 / এএনএসআই সি-র জন্য পরিবর্তনশীল ঘোষণা স্থান নির্ধারণের নিয়মগুলি কী কী?

নিম্নলিখিত কোডটি সফলভাবে gcc -std=c89এবং এর সাথে সংকলন করে gcc -ansi:

#include <stdio.h>
int main() {
    int i;
    for (i = 0; i < 10; i++) {
        char c = (i % 95) + 32;
        printf("%i: %c\n", i, c);
        char *s;
        s = "some string";
        puts(s);
    }
    return 0;
}

C89 / এএনএসআই মোডে ঘোষণার কারণে cএবং sত্রুটির কারণ হওয়া উচিত নয়?


54
কেবল একটি নোট: আনসিসি সি এর ভেরিয়েবলগুলি কোনও ফাংশনের শুরুতে নয় বরং একটি ব্লকের শুরুতে ঘোষিত হতে হবে। সুতরাং, চর সি = ... আপনার লুপের শীর্ষে আনসিস সি তে সম্পূর্ণ আইনী The তবে চর * গুলি অবশ্য হবে না।
জেসন কোকো

উত্তর:


149

এটি সাফল্যের সাথে সংকলন করেছে কারণ sএটি সিসি 9 বা এএনএসআই স্ট্যান্ডার্ডের অংশ না হলেও সিসি GNU এক্সটেনশন হিসাবে ঘোষণার অনুমতি দেয় । আপনি যদি সেই মানগুলি কঠোরভাবে অনুসরণ করতে চান তবে আপনাকে অবশ্যই -pedanticপতাকাটি পাস করতে হবে ।

cএকটি { }ব্লকের শুরুতে ঘোষণাটি C89 মানের অংশ; ব্লকটি কোনও ফাংশন হতে হবে না।


41
সম্ভবত এটি লক্ষণীয় যে কেবলমাত্র ঘোষণাটি sএকটি এক্সটেনশন (সি 89 দৃষ্টিকোণ থেকে)। ঘোষণাটি cসি 98 এ পুরোপুরি আইনী, কোনও এক্সটেনশনের প্রয়োজন নেই।
এএনটি

7
@ অ্যান্ড্রেটি: হ্যাঁ, সি-তে, পরিবর্তনীয় ঘোষণাগুলি একটি ব্লকের শুরুতে হওয়া উচিত এবং প্রতি সেফ কোনও ফাংশন নয়; তবে লোকেরা ব্লকটিকে ফাংশন দিয়ে বিভ্রান্ত করে, কারণ এটি একটি ব্লকের প্রাথমিক উদাহরণ।
কিংবদন্তি 2 কে

1
আমি মন্তব্যে উত্তরে +39 ভোট দিয়ে সরিয়েছি।
মার্চ

78

C89- এর জন্য আপনাকে অবশ্যই স্কোপ ব্লকের শুরুতে আপনার ভেরিয়েবলের সমস্ত ঘোষণা করতে হবে ।

সুতরাং, আপনার char cঘোষণাটি বৈধ যেমনটি লুপ স্কোপ ব্লকের জন্য শীর্ষে রয়েছে। তবে, char *sঘোষণাটি একটি ত্রুটি হওয়া উচিত।


2
বেশ সঠিক। আপনি যে কোনও {...} এর শুরুতে ভেরিয়েবল ঘোষণা করতে পারেন}
আর্টেলিয়াস

5
@ আর্টেলিয়াস পুরোপুরি সঠিক নয়। শুধু যদি curlies একটি ব্লক অংশ (যদি না তারা একটি struct বা ইউনিয়ন ঘোষণা বা তৈরি করে রেখেছিলেন সূচনাকারী অংশ।)
জেনস

কেবলমাত্র পেডেন্টিক হওয়ার জন্য, ভ্রান্ত ঘোষণাটি কমপক্ষে সি স্ট্যান্ডার্ড অনুযায়ী অবহিত করা উচিত। সুতরাং এটিতে ত্রুটি বা সতর্কতা হওয়া উচিত gcc। এটি হ'ল বিশ্বাস করবেন না যে কোনও প্রোগ্রামটি এটির অনুবর্তী বলে সংকলন করতে পারে।
jinwee

35

পুরানো, আদিম সি সংকলকগুলির সীমাবদ্ধতার কারণে ব্লকের শীর্ষে পরিবর্তনশীল ঘোষণাগুলি গোষ্ঠীকরণ সম্ভবত একটি উত্তরাধিকার। সমস্ত আধুনিক ভাষা সুপারিশ করে এবং কখনও কখনও সর্বশেষতম বিন্দুতে স্থানীয় ভেরিয়েবলগুলির ঘোষণাকে কার্যকর করে: যেখানে সেগুলি প্রথম শুরু করা হয়। কারণ এটি ভুল করে এলোমেলো মান ব্যবহারের ঝুঁকি থেকে মুক্তি পায়। ঘোষণা এবং আরম্ভের পৃথকীকরণ যখন আপনি পারতেন তখন "কনস্ট" (বা "চূড়ান্ত") ব্যবহার করা থেকেও বাধা দেয়।

সি ++ দুর্ভাগ্যক্রমে সি এর সাথে পশ্চাদপটে সামঞ্জস্যের জন্য পুরানো, শীর্ষ ঘোষণার উপায়টিকে গ্রহণ করে চলেছে (এক সি এর সাথে আরও অনেকের তুলনায় টেনে আনা হয় ...) তবে সি ++ এ থেকে সরে যাওয়ার চেষ্টা করে:

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

সি 99 একই দিকে সি সরানো শুরু করে।

আপনি যদি স্থানীয় ভেরিয়েবলগুলি ঘোষিত হয় না তা সন্ধান করে থাকেন তবে এর অর্থ আপনার আরও অনেক বড় সমস্যা আছে: এনক্লোজিং ব্লকটি অনেক দীর্ঘ এবং বিভক্ত হওয়া উচিত।

https://wiki.sei.cmu.edu/confluence/display/c/DCL19-C.+Minimize+the+scope+of+variables+and+functions



আরও দেখুন: কিভাবে ব্লক উপরের পরিবর্তনশীল ঘোষণা অত্যাচার নিরাপত্তা গর্ত তৈরি করতে পারেন lwn.net/Articles/443037
মার্চ

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

1
@ জোসো: আমি বিভ্রান্ত হয়েছি কেন আপনি ভাবেন যে অবিচ্ছিন্ন ভেরিয়েবলগুলি পড়ে সালিসি প্রভাবের ফলে প্রোগ্রামিংয়ের ভুলগুলি সনাক্ত করার পক্ষে এটি একটি সামঞ্জস্যপূর্ণ মান বা নির্জন ত্রুটি অর্জনের চেয়ে সহজতর করে তুলবে? নোট করুন যে আনইনটলাইজড স্টোরেজ পড়তে এমন কোনও ফ্যাশনে আচরণ করা হবে যা ভেরিয়েবলের যে কোনও বিট প্যাটার্নের সাথে সামঞ্জস্যপূর্ণ, এমনকি এমন কোনও প্রোগ্রাম সময় এবং কার্যকারণের স্বাভাবিক আইনগুলির সাথে সামঞ্জস্যপূর্ণ ফ্যাশনে আচরণ করবে এমন কোনও গ্যারান্টি নেই। এর মতো কিছু দেওয়া হয়েছে int y; ... if (x) { printf("X was true"); y=23;} return y;...
সুপারক্যাট

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

22

সিনট্যাকটিক, স্ট্যান্ডপয়েন্টের পরিবর্তে একটি রক্ষণাবেক্ষণযোগ্যতা থেকে কমপক্ষে তিনটি চিন্তার ট্রেন রয়েছে:

  1. ফাংশনের শুরুতে সমস্ত ভেরিয়েবলগুলি ঘোষণা করুন যাতে সেগুলি এক জায়গায় থাকবে এবং আপনি এক নজরে বিস্তৃত তালিকা দেখতে সক্ষম হবেন।

  2. সমস্ত ভেরিয়েবলগুলি প্রথমে যে স্থানে ব্যবহৃত হয়েছে তার কাছে যত তাড়াতাড়ি ঘনিষ্ঠভাবে ঘোষণা করুন, যাতে আপনি জানেন যে কেন প্রতিটি প্রয়োজন।

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

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

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


27
আমি বিকল্প 2 বা 3 ব্যবহার করি তাই ভেরিয়েবলগুলি সন্ধান করা আরও সহজ - কারণ ফাংশনগুলি এত বড় হওয়া উচিত নয় যে আপনি ভেরিয়েবলের ঘোষণাগুলি দেখতে পাচ্ছেন না।
জোনাথন লেফলার

8
বিকল্প 3 হ'ল নন-ইস্যু, যদি না আপনি 70 এর দশক থেকে কোনও সংকলক ব্যবহার করেন।
edgar.holleis

15
আপনি যদি কোনও শালীন আইডিই ব্যবহার করেন, আপনার কোড শিকারে যাওয়ার দরকার হবে না, কারণ আপনার জন্য ঘোষণার সন্ধানের জন্য আইডিই-কমান্ড থাকা উচিত। (Eclipse এফ
edgar.holleis

4
আমি বুঝতে পারি না আপনি কীভাবে বিকল্প 1 এ সূচনাটি নিশ্চিত করতে পারবেন, আপনি কেবল পরে অন্য কোনও ক্রিয়াকলাপে কল করে বা ক্যাককুলেশন সম্পাদন করে ব্লকের পরে প্রাথমিক মান পেতে পারেন।
প্লুম্যানেটর

4
@ প্লামনেটর: বিকল্প 1 সূচনাটি নিশ্চিত করে না; আমি তাদের ঘোষণার সাথে সাথে তাদের "সঠিক" মানগুলিতে বা এমন কোনও কিছুতে গ্যারান্টি দেবে যেগুলি যথাযথভাবে সেট না করা থাকলে পরবর্তী কোডটি ভঙ্গ হবে guarantee আমি বলি "বেছে নেওয়া হয়েছে" কারণ আমি এই লেখার পরে আমার পছন্দটি # 2 এ পরিবর্তিত হয়েছে, সম্ভবত আমি এখন সি-র চেয়ে জাভা ব্যবহার করছি এবং কারণ আমার কাছে আরও ভাল ডেভ সরঞ্জাম রয়েছে।
অ্যাডাম লিস

6

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

সি ৮৮ এর প্রয়োজন হয় যে প্রতিটি স্কোপের মধ্যে অন্য কোনও বিবৃতি দেওয়ার আগে ভেরিয়েবলগুলি ঘোষণা করা উচিত, পরে মানগুলি ব্যবহারের কাছাকাছি ঘোষণার অনুমতি দেয় (যা আরও স্বজ্ঞাত এবং আরও দক্ষ উভয় হতে পারে), বিশেষত 'ফর' লুপগুলিতে একযোগে ঘোষণা এবং লুপ নিয়ন্ত্রণ ভেরিয়েবলের আরম্ভকরণ initial


0

যেমনটি উল্লেখ করা হয়েছে, এটি নিয়ে দুটি চিন্তাবিদ্যালয় রয়েছে।

1) ফাংশনগুলির শীর্ষে সমস্ত কিছু ঘোষণা করুন কারণ বছর 1987।

2) প্রথম ব্যবহারের সবচেয়ে নিকটতম এবং সম্ভাব্যতম ক্ষুদ্রতম ক্ষেত্রে ঘোষণা করুন।

আমার এই উত্তর দুটি হয়! আমাকে ব্যাখ্যা করতে দাও:

দীর্ঘ ক্রিয়াকলাপের জন্য, 1) রিফ্যাক্টরিং খুব শক্ত করে। আপনি যদি এমন কোনও কোডবেসে কাজ করেন যেখানে বিকাশকারীগণ সাবরুটাইনগুলির ধারণার বিপরীতে থাকে, তবে ফাংশনটি শুরু করার সময় আপনার কাছে 50 পরিবর্তনশীল ঘোষণা থাকবে এবং এর মধ্যে কয়েকটি লুপের জন্য কেবল "i" হতে পারে ফাংশন নীচে।

অতএব আমি এ থেকে শীর্ষে-পিটিএসডি-তে ঘোষণাটি বিকাশ করেছি এবং ধর্মীয়ভাবে 2 বিকল্পটি করার চেষ্টা করেছি।

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

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

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

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

আমার রেসিপি এটি। সমস্ত স্থানীয় ভেরিয়েবলের জন্য, ভেরিয়েবলটি নিয়ে নিন এবং এর ঘোষণাটি নীচে নিয়ে যান, সংকলন করুন, তারপরে সংকলন ত্রুটির ঠিক আগে ঘোষণাটি সরান। এটিই প্রথম ব্যবহার। সমস্ত স্থানীয় ভেরিয়েবলের জন্য এটি করুন।

int foo = 0;
<code that uses foo>

int bar = 1;
<code that uses bar>

<code that uses foo>

এখন, স্কোপ ব্লকটি সংজ্ঞায়িত করুন যা ঘোষণার আগে শুরু হয় এবং প্রোগ্রামটি সংকলন না হওয়া পর্যন্ত শেষ সরিয়ে নিন

{
    int foo = 0;
    <code that uses foo>
}

int bar = 1;
<code that uses bar>

>>> First compilation error here
<code that uses foo>

এটি সংকলন করে না কারণ এখানে আরও কিছু কোড রয়েছে যা ফু ব্যবহার করে। আমরা লক্ষ্য করতে পারি যে সংকলকটি বার ব্যবহার করে এমন কোডের মধ্য দিয়ে যেতে সক্ষম হয়েছিল কারণ এটি ফু ব্যবহার করে না। এই মুহূর্তে, দুটি পছন্দ আছে। যান্ত্রিক একটিটি কেবল "} "টিকে নীচের দিকে সরানো হয় যতক্ষণ না এটি সংকলিত হয়, এবং অন্যটি পছন্দটি কোডটি পরীক্ষা করে পর্যায়ক্রমে নির্ধারণ করা হয় যে অর্ডারটি এতে পরিবর্তন করা যেতে পারে:

{
    int foo = 0;
    <code that uses foo>
}

<code that uses foo>

int bar = 1;
<code that uses bar>

যদি অর্ডারটি স্যুইচ করা যায় তবে আপনি সম্ভবত এটিই চান কারণ এটি অস্থায়ী মানগুলির জীবনকালকে ছোট করে তোলে।

আরেকটি বিষয় লক্ষণীয়, foo এর মান ব্যবহার করা কোডের ব্লকগুলির মধ্যে সংরক্ষণ করা দরকার, বা এটি উভয়ই আলাদা foo হতে পারে। উদাহরণ স্বরূপ

int i;

for(i = 0; i < 8; ++i){
    ...
}

<some stuff>

for(i = 3; i < 32; ++i){
    ...
}

এই পরিস্থিতিতে আমার পদ্ধতির চেয়ে বেশি প্রয়োজন। কী করা উচিত তা নির্ধারণ করতে বিকাশকারীকে কোডটি বিশ্লেষণ করতে হবে।

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

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


0

আপনার সমস্ত ভেরিয়েবল শীর্ষে বা ফাংশনে "স্থানীয়ভাবে" ঘোষণা করা উচিত। উত্তরটা হচ্ছে:

এটি আপনি কী ধরণের সিস্টেম ব্যবহার করছেন তার উপর নির্ভর করে:

1 / এম্বেড সিস্টেম (বিশেষত বিমান বা গাড়ির মতো জীবনের সাথে সম্পর্কিত): এটি আপনাকে গতিশীল মেমোরি ব্যবহার করার অনুমতি দেয় না (যেমন: কলোক, ম্যালোক, নতুন ...) ... কল্পনা করুন আপনি 1000 প্রকৌশলী নিয়ে একটি খুব বড় প্রকল্পে কাজ করছেন। যদি তারা নতুন গতিশীল মেমরি বরাদ্দ করে এবং এটি সরিয়ে দিতে ভুলে যায় (যখন এটি আর ব্যবহার করে না)? যদি এম্বেড থাকা সিস্টেমটি দীর্ঘ সময়ের জন্য চালিত হয় তবে এটি স্ট্যাকের ওভারফ্লোতে বাড়ে এবং সফ্টওয়্যারটি দূষিত হবে। গুণটি নিশ্চিত করা সহজ নয় (সর্বোত্তম উপায় হ'ল ডায়নামিক মেমরি নিষিদ্ধ)।

যদি কোনও বিমান 30 দিনের মধ্যে চালিত হয় এবং টার্নঅফ অফ হয় না, তবে সফ্টওয়্যারটি দূষিত হলে (যখন বিমানটি এখনও বাতাসে রয়েছে) কী হবে?

2 / ওয়েব, পিসির মতো অন্য সিস্টেম (বড় মেমরির স্থান রয়েছে):

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


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

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

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

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

1
যদিও আমি সম্মত হই যে এটি পরিচালনা করার পক্ষে যুক্তিসঙ্গত উপায় হবে, বাস্তবে এটি ঘটে না। আপনার উদাহরণের মতো খুব একটা কিছুর জন্য এখানে আসল সমাবেশ রয়েছে: Godbolt.org/z/mLhE9a । আপনি দেখতে পাচ্ছেন 11 লাইনে, স্টেটমেন্টের বাইরেsub rsp, 1008 পুরো অ্যারের জন্য স্থান বরাদ্দ করা হচ্ছে । আমি চেষ্টা করেছি প্রতিটি সংস্করণ এবং অপ্টিমাইজেশন স্তরের জন্য এবং এটি সত্য । clanggcc
কুইনফ্রিডম্যান

-1

আমি স্পষ্ট ব্যাখ্যার জন্য জিসিসি সংস্করণ 4.7.0 এর জন্য ম্যানুয়াল থেকে কিছু বিবৃতি উদ্ধৃত করব।

"সংকলকটি বেশ কয়েকটি বেস স্ট্যান্ডার্ড গ্রহণ করতে পারে যেমন 'সি 90' বা 'সি ++ 98', এবং সেই মানগুলির জিএনইউ উপভাষা, যেমন 'gnu90' বা 'gnu ++ 98'। বেস স্ট্যান্ডার্ড নির্দিষ্ট করে, সংকলক সেই মান অনুসরণ করে এবং GNU এক্সটেনশানগুলি ব্যবহার করে এমন সমস্ত প্রোগ্রাম গ্রহণ করবে যা এটির বিরোধিতা করে না example উদাহরণস্বরূপ, '-std = c90' জিএসসির কিছু বৈশিষ্ট্যগুলি বন্ধ করে দেয় যা আইএসও সি 90 এর সাথে অসম্পূর্ণ, যেমন এসএম এবং টাইপফুল কীওয়ার্ড, তবে নয় অন্যান্য জিএনইউ এক্সটেনশনের যেগুলির আইএসও সি 90-তে কোনও অর্থ নেই, যেমন?: প্রকাশের মধ্যবর্তী শব্দটি বাদ দেওয়া? "

আমি মনে করি আপনার প্রশ্নের মূল বক্তব্য হ'ল "-std = c89" বিকল্পটি ব্যবহার করা সত্ত্বেও কেন gcc সিসি 89 তে মেনে চলে না। আমি আপনার জিসিসির সংস্করণ জানি না, তবে আমি মনে করি যে এতে বড় পার্থক্য থাকবে না। গিসিটির বিকাশকারী আমাদের জানিয়ে দিয়েছেন যে "-std = c89" বিকল্পটি কেবলমাত্র সেই এক্সটেনশানগুলি বোঝায় যা C89 এর বিপরীতে রয়েছে off সুতরাং, এটির কিছু এক্সটেনশনের সাথে কোনও সম্পর্ক নেই যার C89 তে কোনও অর্থ নেই। এবং যে এক্সটেনশানটি ভেরিয়েবল ঘোষণার স্থান নির্ধারণকে সীমাবদ্ধ করে না সেগুলি সেই এক্সটেনশনের অন্তর্ভুক্ত যা C89 এর বিরোধিতা করে না।

সত্যি কথা বলতে, প্রত্যেকেই ভাববে যে এটি "-std = c89" বিকল্পটির প্রথম দর্শনে সম্পূর্ণ C89 এর সাথে সামঞ্জস্য করা উচিত। তবে তা হয় না। শুরুতে সমস্ত ভেরিয়েবল ঘোষিত সমস্যাটি আরও ভাল বা খারাপ কেবল অভ্যাসের বিষয়।


মেনে চলার অর্থ এক্সটেনশনগুলি গ্রহণ না করার অর্থ নয়: যতক্ষণ সংকলক বৈধ প্রোগ্রামগুলি সংকলন করে এবং অন্যদের জন্য প্রয়োজনীয় ডায়াগনস্টিক তৈরি করে ততক্ষণ তা মেনে চলে।
মনিকা

@ মার্ক লেহম্যান, হ্যাঁ, আপনি যখন ঠিক বলেছেন তখনই "সংগত" শব্দটি কম্পাইলারগুলিকে আলাদা করতে ব্যবহৃত হয়। তবে যখন কিছু ব্যবহারের বর্ণনা দিতে "কনফর্ম" শব্দটি ব্যবহার করা হয়, আপনি বলতে পারেন "একটি ব্যবহারের মানটি মানায় না।" এবং সমস্ত নতুনদের একটি মতামত রয়েছে যে ব্যবহারগুলি যা মানের সাথে খাপ খায় না এমন একটি ত্রুটি ঘটায়।
জুনওয়ানহে

@ মার্ক লেহম্যান, যাইহোক, যখন জিসিসি ব্যবহারটি দেখে যা C89 মানের সাথে খাপ খায় না এমন কোনও ডায়াগনস্টিক নেই।
জুনওয়ানহে

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