সি-তে কোনও প্রভাব ছাড়াই বিবৃতি কেন আইনী বিবেচিত হয়?


13

ক্ষমা যদি এই প্রশ্নটি নিষ্প্রভ হয়। নিম্নলিখিত প্রোগ্রাম বিবেচনা করুন:

#include <stdio.h>

int main() {
  int i = 1;
  i = i + 2;
  5;
  i;
  printf("i: %d\n", i);
}

উপরের উদাহরণে, বিবৃতিগুলি 5;এবং i;সম্পূর্ণরূপে অতিরিক্ত অতিরিক্ত বলে মনে হয়, তবুও কোডটি পূর্বনির্ধারিতভাবে সতর্কতা বা ত্রুটি ছাড়াই কোড সংকলন করে (তবে, জিসিসি warning: statement with no effect [-Wunused-value]যখন চালিত হয় তখন একটি সতর্কতা নিক্ষেপ করে না -Wall)। প্রোগ্রামের বাকি অংশগুলিতে তাদের কোনও প্রভাব নেই, সুতরাং কেন তারা প্রথম স্থানে বৈধ বিবৃতি হিসাবে বিবেচিত হবে? সংকলক কি কেবল এগুলি উপেক্ষা করে? এই ধরনের বিবৃতি অনুমতি দেওয়ার কোনও সুবিধা আছে কি?


5
এই জাতীয় বক্তব্য নিষিদ্ধ করার সুবিধা কী কী?
মাকিং হাঁস

2
কোনও অভিব্যক্তি ;এটি পরে রাখার মাধ্যমে একটি বিবৃতি হতে পারে। এক্সপ্রেশন যখন বক্তব্য হতে পারে না সে সম্পর্কে আরও বিধি যুক্ত করার জন্য এটি ভাষা জটিল করে তুলবে
এমএম

3
আপনি কি এর পরিবর্তে আপনার কোডটি সংকলন করতে ব্যর্থ হবেন কারণ আপনি তার ফেরতের মানটিকে উপেক্ষা করছেন printf()? বিবৃতি 5;মূলত বলেন, "যাই হোক না কেন না 5করে (কিছুই না) এবং ফলাফল উপেক্ষা করি। আপনার বিবরণ printf(...)হল" যাই হোক না কেন না printf(...)করে এবং ফলাফল উপেক্ষা করা (থেকে ফেরত মান printf()) "। সি ঐ একই আচরণ করেন। এই যেমন কোড জন্য করতে পারবেন (void) i;যেখানে iহয় একটি ফাংশন সময়ে একটি মাপদণ্ড আপনাকে নিক্ষেপ করে voidইচ্ছাকৃতভাবে অব্যবহৃত হিসাবে চিহ্নিত করতে।
অ্যান্ড্রু Henle

1
@ অ্যান্ড্রুহেনেল: এটি একেবারেই এক নয়, কারণ কলিংয়ের printf()ফলস্বরূপ কার্যকর হয়, আপনি যদি মূল্যটি অবশেষে ফিরিয়ে দেন তবে তা উপেক্ষা করেও। বিপরীতে 5;এর কোনও প্রভাব নেই।
নাট এল্ডারেজ

1
কারণ ডেনিস রিচি, এবং তিনি আমাদের বলার মতো আশেপাশে নেই।
ব্যবহারকারী 207421

উত্তর:


10

এই জাতীয় বক্তব্যকে মঞ্জুরি দেওয়ার একটি সুবিধা হ'ল কোডগুলি যা ম্যাক্রোগুলি বা অন্যান্য প্রোগ্রাম দ্বারা তৈরি হয়েছিল, তা মানুষের দ্বারা লিখিত না হয়ে।

উদাহরণস্বরূপ, এমন একটি ফাংশনটি কল্পনা int do_stuff(void)করুন যা সাফল্যে 0 বা ব্যর্থতার পরে -1 ফেরার কথা। এটি "স্টাফ" এর পক্ষে সমর্থন optionচ্ছিক হতে পারে এবং তাই আপনার একটি শিরোনাম ফাইল থাকতে পারে

#if STUFF_SUPPORTED
#define do_stuff() really_do_stuff()
#else
#define do_stuff() (-1)
#endif

এখন এমন কিছু কোড কল্পনা করুন যা সম্ভব হলে স্টাফগুলি করতে চায়, তবে এটি সফল হয় বা ব্যর্থ হয় কিনা তা সত্যই যত্নশীল হতে পারে বা নাও পারে:

void func1(void) {
    if (do_stuff() == -1) {
        printf("stuff did not work\n");
    }
}

void func2(void) {
    do_stuff(); // don't care if it works or not
    more_stuff();
}

যখন STUFF_SUPPORTED0 হয়, প্রিপ্রোসেসর কেবল func2পাঠানো একটি বিবৃতিতে কলটি প্রসারিত করবে

    (-1);

এবং সুতরাং সংকলক পাসটি আপনাকে কেবল বিরক্তিকর বলে মনে হচ্ছে এমন "অতিমাত্রায়" বিবৃতি বাছাই করবে। তবুও আর কী করা যায়? আপনি যদি #define do_stuff() // nothing, তারপর কোড func1ব্রেক হবে। (এবং আপনি এখনও একটি খালি বিবৃতিতে হবে func2যে শুধু সার্চ ;অন্যদিকে যা সম্ভবত আরও বেশি প্রযোজন নেই,।), আপনি আসলে একটি সংজ্ঞায়িত করতে আছে যদি do_stuff()ফাংশন যা রিটার্ন -1, আপনি একটি ফাংশন কল খরচ বহন করতে হতে পারে কোন সঙ্গত কারণেই


নো-অপের আরও ক্লাসিক সংস্করণ (বা আমি কী সাধারণ সংস্করণ বলতে চাইছি) তা ((void)0)
জোনাথন লেফলার

এর একটি ভাল উদাহরণ assert
নিল

3

সি-তে সরল বিবৃতিগুলি সেমিকোলন দ্বারা সমাপ্ত হয়।

সি-তে সরল বিবৃতিগুলি হ'ল অভিব্যক্তি। একটি এক্সপ্রেশন হল ভেরিয়েবল, কনস্ট্যান্ট এবং অপারেটরগুলির সংমিশ্রণ। প্রতিটি অভিব্যক্তি একটি নির্দিষ্ট ধরণের কিছু মানের ফল দেয় যা একটি ভেরিয়েবলকে বরাদ্দ করা যেতে পারে।

কিছু "স্মার্ট সংকলক" 5 টি ফেলে দিতে পারে বলেছে; এবং আমি; বিবৃতি।


আমি এমন কোনও সংকলক কল্পনা করতে পারি না যা সেগুলি বাতিল করে দেওয়া ছাড়া এই বিবৃতিগুলির সাথে কিছু করতে পারে। এটি তাদের সাথে আর কী করতে পারে?
জেরেমি ফ্রাইজনার

@ জেরেমিফ্রিজার: একটি খুব সাধারণ, অপ্রচলিত সংকলক খুব ভাল মান গণনা করতে কোড উত্পন্ন করতে পারে এবং ফলাফল একটি রেজিস্টারে রাখতে পারে (যে বিন্দু থেকে এটি উপেক্ষা করা হবে)।
নাট এল্ডারেজ

সি স্ট্যান্ডার্ডটি "সাধারণ বিবৃতি" শব্দটি ব্যবহার করে না। একটি এক্সপ্রেশন বিবৃতিতে একটি (alচ্ছিক) প্রকাশ থাকে যার পরে সেমিকোলন থাকে। প্রতিটি অভিব্যক্তি একটি মান হিসাবে ফলাফল না; ধরণের অভিব্যক্তির voidকোনও মূল্য নেই।
কিথ থম্পসন

2

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

একটি অভিব্যক্তি বিবৃতি একটি সেমিকোলন পরে একটি এক্সপ্রেশন গঠিত। এর আচরণটি হ'ল ভাবটি মূল্যায়ন করা এবং ফলাফল (যদি থাকে তবে) বাতিল করা discard সাধারণত উদ্দেশ্যটি হ'ল অভিব্যক্তিটির মূল্যায়নের পার্শ্ব প্রতিক্রিয়া রয়েছে তবে প্রদত্ত এক্সপ্রেশনটির পার্শ্ব প্রতিক্রিয়া রয়েছে কিনা তা নির্ধারণ করা সর্বদা সহজ বা এমনকি সম্ভব নয়।

উদাহরণস্বরূপ, একটি ফাংশন কল একটি অভিব্যক্তি, সুতরাং একটি সেমিকোলনের পরে ফাংশন কল একটি বিবৃতি। এই বিবৃতিতে কি কোনও পার্শ্ব প্রতিক্রিয়া রয়েছে?

some_function();

বাস্তবায়ন না দেখে বলা অসম্ভব some_function

এ কেমন?

obj;

সম্ভবত না - তবে যদি objসংজ্ঞায়িত করা হয় volatileতবে তা হয়।

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


2

আপনি কোনও প্রভাব ছাড়াই তালিকাভুক্ত বিবৃতিগুলি হ'ল একটি অভিব্যক্তি বিবরণের উদাহরণ , যার বাক্য গঠনটি সি স্ট্যান্ডার্ডের 6.8.3p1 বিভাগে দেওয়া হয়েছে:

 এক্সপ্রেশন-বিবৃতি :
    এক্সপ্রেশন অপ্ট  ;

Section.৫ ধারা সমস্তই একটি অভিব্যক্তির সংজ্ঞায় উত্সর্গীকৃত, তবে আলগাভাবে বলতে গেলে কোনও অভিব্যক্তি অপারেটরগুলির সাথে যুক্ত এবং ধ্রুবক এবং শনাক্তকারীকে নিয়ে থাকে। উল্লেখযোগ্যভাবে, একটি এক্সপ্রেশন একটি এসাইনমেন্ট অপারেটর থাকতে পারে এবং নাও থাকতে পারে এবং এতে ফাংশন কল থাকতে পারে এবং নাও থাকতে পারে।

সুতরাং কোনো অভিব্যক্তি একটি অভিব্যক্তি বিবৃতি হিসাবে একটি সেমিকোলন যোগ্যতা করে। আসলে, আপনার কোড থেকে এই লাইনগুলির প্রতিটিই একটি অভিব্যক্তি বিবৃতিটির উদাহরণ:

i = i + 2;
5;
i;
printf("i: %d\n", i);

কিছু অপারেটরগুলির পার্শ্ব প্রতিক্রিয়া যেমন অ্যাসাইনমেন্ট অপারেটরগুলির সেট এবং প্রাক / পোস্ট ইনক্রিমেন্ট / হ্রাস অপারেটরগুলির সমন্বয় রয়েছে এবং ফাংশন কল অপারেটরের প্রশ্নের ক্রিয়াটি কী করে তার উপর নির্ভর করে একটি পার্শ্ব প্রতিক্রিয়া () থাকতে পারে। অপারেটরগুলির মধ্যে একটির অবশ্যই পার্শ্ব প্রতিক্রিয়া থাকতে হবে এমন কোনও প্রয়োজন নেই।

এখানে অন্য একটি উদাহরণ:

atoi("1");

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


1

কখনও কখনও এই জাতীয় বিবৃতি খুব সহজ:

int foo(int x, int y, int z)
{
    (void)y;   //prevents warning
    (void)z;

    return x*x;
}

বা যখন রেফারেন্স ম্যানুয়াল আমাদের কিছু সংরক্ষণাগারভুক্ত করার জন্য নিবন্ধগুলি পড়তে বলে - উদাহরণস্বরূপ কিছু পতাকা সাফ করা বা সেট করা (ইউসি বিশ্বের খুব সাধারণ পরিস্থিতি)

#define SREG   ((volatile uint32_t *)0x4000000)
#define DREG   ((volatile uint32_t *)0x4004000)

void readSREG(void)
{
    *SREG;   //we read it here
    *DREG;   // and here
}

https://godbolt.org/z/6wjh_5


কখন *SREGঅস্থির হয়, *SREG;সি স্ট্যান্ডার্ড দ্বারা নির্দিষ্ট মডেলটিতে কোনও প্রভাব ফেলবে না। সি স্ট্যান্ডার্ড নির্দিষ্ট করে এটি পর্যবেক্ষণযোগ্য পার্শ্ব প্রতিক্রিয়া আছে।
এরিক পোস্টপিসিল

@ এরিকপোস্টপিসিল - না এটি পর্যবেক্ষণযোগ্য প্রভাব দেয় না , তবে যদি এর প্রভাব থাকে has কোনও সি দৃশ্যমান বস্তুর কোনও পরিবর্তন হয়নি।
পি__জে__

সি 2018 5.1.2.3 6 প্রোগ্রামটির পর্যবেক্ষণযোগ্য আচরণকে অন্তর্ভুক্ত করে এটি অন্তর্ভুক্ত করে যে "অ্যাবস্ট্রাক্ট মেশিনের নিয়ম অনুসারে উদ্বায়ী বস্তুগুলির অ্যাক্সেসগুলি কঠোরভাবে মূল্যায়ন করা হয়।" ব্যাখ্যা বা ছাড়ের প্রশ্নই আসে না; এটি পর্যবেক্ষণযোগ্য আচরণের সংজ্ঞা
এরিক পোস্টপিসিল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.