নিম্নলিখিত কোডগুলি সমস্যা ছাড়াই সংকলন করে:
int main() {
printf("Hi" "Bye");
}
তবে এটি সংকলন করে না:
int main() {
int test = 0;
printf("Hi" (test ? "Bye" : "Goodbye"));
}
এর কারণ কী?
নিম্নলিখিত কোডগুলি সমস্যা ছাড়াই সংকলন করে:
int main() {
printf("Hi" "Bye");
}
তবে এটি সংকলন করে না:
int main() {
int test = 0;
printf("Hi" (test ? "Bye" : "Goodbye"));
}
এর কারণ কী?
"Hi"
এবং "Bye"
হয় স্ট্রিং লিটারেল না স্ট্রিং যেমন সি মান লাইব্রেরিতে ব্যবহৃত। সঙ্গে স্ট্রিং লিটারেল , কম্পাইলার কনক্যাটেনেট হবে "H\0i" "B\0ye"
। sprintf(buf,"%s%s", "H\0i" "B\0ye");
a (some_condition ? + : - ) b
printf("Hi" ("Bye"));
কাজ করবে না - এর জন্য টের্নারি অপারেটরের প্রয়োজন নেই; প্রথম বন্ধনী যথেষ্ট (যদিও printf("Hi" test ? "Bye" : "Goodbye")
এটি সংকলন করবে না)। কেবলমাত্র সীমিত সংখ্যক টোকেন রয়েছে যা স্ট্রিং আক্ষরিক অনুসরণ করতে পারে। কমা ,
, ওপেন স্কোয়ার ব্র্যাকেট [
, বন্ধ স্কোয়ার ব্র্যাকেট ]
(যেমন 1["abc"]
- এবং হ্যাঁ, এটি মারাত্মক), নিকট বৃত্তাকার বন্ধনী )
, ঘনিষ্ঠ কোঁকড়ানো বন্ধনী }
(একটি আরম্ভকারী বা অনুরূপ প্রসঙ্গে), এবং সেমিকোলন ;
বৈধ (এবং অন্য স্ট্রিং আক্ষরিক); আমি নিশ্চিত যে অন্য কোনও আছে।
উত্তর:
সি স্ট্যান্ডার্ড অনুযায়ী (5.1.1.2 অনুবাদ পর্যায়ক্রমে)
1 অনুবাদের বাক্য গঠন নিয়মের মধ্যে প্রাধান্য নিম্নলিখিত ধাপগুলি দ্বারা নির্দিষ্ট করা হয়েছে))
- সংলগ্ন স্ট্রিং আক্ষরিক টোকেন সংক্ষিপ্ত হয়।
এবং কেবল তারপরেই
- টোকেনগুলি পৃথক করে সাদা-স্থানের অক্ষরগুলি আর তাত্পর্যপূর্ণ নয়। প্রতিটি প্রাক-প্রসেসিং টোকেন টোকেনে রূপান্তরিত হয়। ফলস্বরূপ টোকেনগুলি সিনট্যাক্টিকাল এবং শব্দার্থবিজ্ঞানের সাথে বিশ্লেষণ করা হয় এবং অনুবাদ ইউনিট হিসাবে অনুবাদ করা হয় ।
এই নির্মাণে
"Hi" (test ? "Bye" : "Goodbye")
এখানে কোনও সংলগ্ন স্ট্রিং আক্ষরিক টোকেন নেই। সুতরাং এই নির্মাণটি অবৈধ।
(test ? "Bye" : "Goodbye")
মূলত স্ট্রিং লিটারেল হয় evaulate উপার্জন "Hi" "Bye"
বা "Hi Goodbye"
? (আমার প্রশ্নের উত্তর অন্য উত্তর দেওয়া হয়)
সি 11 স্ট্যান্ডার্ড অনুসারে অধ্যায় §5.1.1.2, সংলগ্ন স্ট্রিং লিটারেলগুলির সংক্ষিপ্তকরণ:
সংলগ্ন স্ট্রিং আক্ষরিক টোকেন সংক্ষিপ্ত হয়।
অনুবাদ পর্বে ঘটে । অন্য দিকে:
printf("Hi" (test ? "Bye" : "Goodbye"));
শর্তসাপেক্ষ অপারেটর জড়িত, যা রান সময় সময়ে মূল্যায়ন করা হয় । সুতরাং, সংকলনের সময়, অনুবাদ পর্বের সময়, কোনও সংলগ্ন স্ট্রিং লিটারাল উপস্থিত নেই, সুতরাং সমাহারটি সম্ভব নয়। বাক্য গঠনটি অবৈধ এবং এইভাবে আপনার সংকলক দ্বারা প্রতিবেদন করা হয়েছে।
প্রিপ্রোসেসিং পর্ব চলাকালীন কেন অংশটি সম্পর্কে কিছুটা বিস্তৃত করার জন্য , সংলগ্ন স্ট্রিং লিটারালগুলি একক স্ট্রিং আক্ষরিক (টোকেন) হিসাবে উপস্থাপিত হয় এবং উপস্থাপন করা হয় । স্টোরেজটি সেই অনুযায়ী বরাদ্দ করা হয় এবং সংক্ষিপ্ত স্ট্রিং আক্ষরিককে একটি একক সত্তা (একটি স্ট্রিং আক্ষরিক) হিসাবে বিবেচনা করা হয় ।
অন্যদিকে, রান-টাইম কনটেনটেশনের ক্ষেত্রে, গন্তব্যটিতে সংক্ষিপ্ত স্ট্রিংকে আক্ষরিক ধরে রাখতে পর্যাপ্ত মেমরি থাকতে হবে, অন্যথায় প্রত্যাশিত সংক্ষিপ্ত আউটপুট অ্যাক্সেস করার কোনও উপায় থাকবে না । এখন, স্ট্রিং লিটারেলের ক্ষেত্রে , তারা ইতিমধ্যে সংকলন সময়ে মেমরি বরাদ্দ করা হয়েছে এবং আসল সামগ্রীটিতে আর কোনও ইনকামিং ফিট করার জন্য বা বাড়ানো যাবে না । অন্য কথায়, একক স্ট্রিং আক্ষরিক হিসাবে একযোগে ফল অ্যাক্সেস (উপস্থাপিত) হওয়ার কোনও উপায় থাকবে না । সুতরাং, এই নির্মাণ অন্তর্নিহিত ভুল।
কেবলমাত্র এফওয়াইআই, রান-টাইম স্ট্রিংয়ের জন্য ( আক্ষরিক নয় ) কনটেক্সটেশনের জন্য আমাদের কাছে লাইব্রেরির ফাংশন রয়েছে strcat()
যা দুটি স্ট্রিংকে সংহত করে । লক্ষ্য করুন, বর্ণনায় উল্লেখ রয়েছে:
char *strcat(char * restrict s1,const char * restrict s2);
strcat()
ফাংশন একটি স্ট্রিং এর কপি প্রতি ইঙ্গিত দ্বারা appendss2
(সসীম নাল চরিত্র সহ) শেষ করা স্ট্রিং দ্বারা প্রতি ইঙ্গিতs1
। প্রাথমিক অক্ষরs2
শেষে নাল অক্ষর ওভাররাইট করেs1
। [...]
সুতরাং, আমরা দেখতে পাচ্ছি, এটি s1
একটি স্ট্রিং , স্ট্রিং আক্ষরিক নয় । যাইহোক, বিষয়বস্তু s2
কোনওভাবেই পরিবর্তন করা হয়নি, এটি খুব ভালভাবে স্ট্রিং আক্ষরিক হতে পারে ।
strcat
: গন্তব্য অ্যারেটি s2
ইতিমধ্যে উপস্থিত অক্ষরের পরে প্লাস নাল টার্মিনেটর থেকে অক্ষরগুলি গ্রহণ করার জন্য যথেষ্ট দীর্ঘ হতে হবে ।
স্ট্রিং আক্ষরিক সম্মিলন সংকলন সময়ে প্রিপ্রোসেসর দ্বারা সঞ্চালিত হয়। এই কনটেন্টেশনটির মান সম্পর্কে সচেতন হওয়ার কোনও উপায় নেই test
যা প্রোগ্রামটি বাস্তবায়িত না হওয়া অবধি জানা যায় না। সুতরাং, এই স্ট্রিং আক্ষরিক সংক্ষিপ্ত করা যাবে না।
কারণ সাধারণ ক্ষেত্রে এটি হ'ল সংকলন-সময়ে জ্ঞাত মানগুলির জন্য আপনার মতো এই জাতীয় নির্মাণের দরকার নেই, সি স্ট্যান্ডার্ডটি স্বয়ংক্রিয়-কনটেন্টেশন বৈশিষ্ট্যটিকে সর্বাধিক বেসিক ক্ষেত্রে সীমাবদ্ধ করার জন্য তৈরি করা হয়েছিল: যখন আক্ষরিক একে অপরের পাশে অক্ষরে অক্ষরে থাকে ।
তবে এমনকি যদি এটি এই বিধিনিষেধটিকে সেভাবে না বলে থাকে বা সীমাবদ্ধতাটি অন্যরকমভাবে নির্মিত হয়, তবুও আপনার উদাহরণটি কনটেন্টেশনকে রানটাইম প্রক্রিয়া না করেই উপলব্ধি করা অসম্ভব। এবং, তার জন্য, আমাদের যেমন লাইব্রেরির ফাংশন রয়েছে strcat
।
কারণ সি এর কোনও string
প্রকার নেই। স্ট্রিং লিটারালগুলি char
অ্যারেতে সংকলিত হয় , একটি char*
পয়েন্টার দ্বারা রেফারেন্স করা হয় ।
সি আপনার প্রথম উদাহরণের মতো সংলগ্ন সময়ে সংলগ্ন লিটারেলগুলিকে একত্রিত করার অনুমতি দেয় । সি সংকলক নিজেই স্ট্রিং সম্পর্কে কিছু জ্ঞান আছে। তবে রানটাইমের সময় এই তথ্য উপস্থিত নেই, এবং এভাবে কনকনেটেশন ঘটতে পারে না।
সংকলন প্রক্রিয়া চলাকালীন আপনার প্রথম উদাহরণটি "অনুবাদিত" এতে:
int main() {
static const char char_ptr_1[] = {'H', 'i', 'B', 'y', 'e', '\0'};
printf(char_ptr_1);
}
প্রোগ্রামটি কার্যকর করার আগে সংকলক দ্বারা দুটি স্ট্রিং কীভাবে একক স্ট্যাটিক অ্যারেতে একত্রিত হয় তা নোট করুন।
তবে আপনার দ্বিতীয় উদাহরণটি "অনুবাদিত" এর মতো কিছুতে:
int main() {
static const char char_ptr_1[] = {'H', 'i', '\0'};
static const char char_ptr_2[] = {'B', 'y', 'e', '\0'};
static const char char_ptr_3[] = {'G', 'o', 'o', 'd', 'b', 'y', 'e', '\0'};
int test = 0;
printf(char_ptr_1 (test ? char_ptr_2 : char_ptr_3));
}
এটি সংকলন করে না কেন এটি পরিষ্কার হওয়া উচিত। তিনটি অপারেটরটি ?
রানটাইম সময়ে মূল্যায়ন করা হয়, সংকলন-সময় নয়, যখন "স্ট্রিংস" আর উপস্থিত থাকে না, কেবল পয়েন্টার char
দ্বারা রেফারেন্সযুক্ত সরল অ্যারে হিসাবে char*
। সংলগ্ন স্ট্রিং লিটারেলের বিপরীতে , সংলগ্ন চর পয়েন্টার কেবল একটি বাক্য গঠন ত্রুটি।
static const char *char_ptr_1 = {'H', 'i', 'B', 'y', 'e', '\0'};
হওয়া উচিত নয় static const char *char_ptr_1 = "HiBye";
?
static const char *char_ptr_1 = "HiBye";
কম্পাইলার লিখেন তখন লাইনটি অনুবাদ করে static const char *char_ptr_1 = {'H', 'i', 'B', 'y', 'e', '\0'};
, তাই না, এটি "স্ট্রিংয়ের মতো" লেখা উচিত নয়। উত্তরটি যেমন বলেছে, স্ট্রিংগুলি চরগুলির একটি অ্যারেতে সংকলিত হয় এবং আপনি যদি এটির বেশিরভাগ "কাঁচা" আকারে অক্ষরের একটি অ্যারে নির্ধারণ করে থাকেন তবে আপনি অক্ষরের সাথে কমা দ্বারা পৃথক করা তালিকা ব্যবহার করবেন, ঠিক যেমনstatic const char *char_ptr_1 = {'H', 'i', 'B', 'y', 'e', '\0'};
static const char str[] = {'t', 'e', 's', 't', '\0'};
হিসাবে একই static const char str[] = "test";
, static const char* ptr = "test";
হয় না হিসাবে একই static const char* ptr = {'t', 'e', 's', 't', '\0'};
। পূর্ববর্তীটি বৈধ এবং সংকলন করবে তবে পরবর্তীটি অবৈধ এবং আপনি যা প্রত্যাশা করেছেন তা করে।
আপনি যদি সত্যিই উভয় শাখার রানটাইমের সময় চয়ন করার জন্য সংকলন-সময়ের স্ট্রিং ধ্রুবক উত্পাদন করতে চান তবে আপনার একটি ম্যাক্রোর প্রয়োজন।
#include <stdio.h>
#define ccat(s, t, a, b) ((t)?(s a):(s b))
int
main ( int argc, char **argv){
printf("%s\n", ccat("hello ", argc > 2 , "y'all", "you"));
return 0;
}
এর কারণ কী?
আপনার কোডটি টার্নারি অপারেটর ব্যবহার করে শর্তাধীনভাবে দুটি স্ট্রিং ল্যাটারেলের মধ্যে নির্বাচন করে। পরিচিত বা অজানা বিষয় শর্ত নয়, এটি সংকলন সময়ে মূল্যায়ন করা যায় না, সুতরাং এটি সংকলন করতে পারে না। এমনকি এই বিবৃতিটি printf("Hi" (1 ? "Bye" : "Goodbye"));
সংকলন করবে না। উপরের উত্তরগুলিতে কারণটি গভীরভাবে ব্যাখ্যা করা হয়েছে। সংকলনের জন্য বৈধতাযুক্ত অপারেটর ব্যবহার করে এই জাতীয় বিবৃতি দেওয়ার আরও একটি সম্ভাবনা , এতে একটি ফর্ম্যাট ট্যাগ এবং টর্নেরি অপারেটর স্টেটমেন্টের ফলাফলকে অতিরিক্ত যুক্তি হিসাবে ফর্ম্যাট করা অন্তর্ভুক্ত করবে printf
। তারপরেও, printf()
প্রিন্টআউট কেবলমাত্র স্ট্রিংগুলিতে এবং রানটাইম হিসাবে "স্ট্র্যাটেটেটেড" একটি ধারণা দেয় ।
#include <stdio.h>
int main() {
int test = 0;
printf("Hi %s\n", (test ? "Bye" : "Goodbye")); //specify format and print as result
}
printf
বিন্যাস নির্দিষ্টকরণের প্রয়োজন হয় না ; সংকলনের সময় যদি কেবল কনটেন্টেশন করা হত (যা এটি নয়), অপ্টের প্রিন্টফের ব্যবহার বৈধ হবে।
printf()
হবে যেন স্ট্যাটিংয়ের জন্য কোনও ফর্ম্যাট ট্যাগের প্রয়োজন হবে যা একেবারেই সত্য নয়। সংশোধিত!
ইন printf("Hi" "Bye");
আপনি গৃহস্থালির কাজ দুটি পর পর অ্যারে যা কম্পাইলার একটি একক অ্যারের পরিণত করতে পারেন।
ইন printf("Hi" (test ? "Bye" : "Goodbye"));
আপনি এক অ্যারে (অ্যারে তার প্রথম উপাদান একটি পয়েন্টার রূপান্তরিত) গৃহস্থালি একটি পয়েন্টার অনুসরণ। সংকলক একটি অ্যারে এবং একটি পয়েন্টারটিকে মার্জ করতে পারে না ।
প্রশ্নের উত্তর দিতে - আমি প্রিন্টফের সংজ্ঞাতে যাব। ফাংশন প্রিন্টফ কনস্ট চরকে * যুক্তি হিসাবে প্রত্যাশা করে । যে কোনও স্ট্রিং আক্ষরিক যেমন "হাই" একটি কনস্ট চর; তবে একটি অভিব্যক্তি যেমন (test)? "str1" : "str2"
কোনও কনস্ট চর নয় * কারণ এ জাতীয় অভিব্যক্তির ফলাফল কেবল রান-টাইমে পাওয়া যায় এবং তাই সংকলন সময়ে এটি অনির্দিষ্ট হয়, এটি একটি সত্য যা সংকলককে যথাযথভাবে অভিযোগ করে। অন্যদিকে - এটি পুরোপুরি ভাল কাজ করেprintf("hi %s", test? "yes":"no")
(test)? "str1" : "str2"
নয় const char*
... অবশ্যই এটি! এটি একটি ধ্রুবক অভিব্যক্তি নয়, কিন্তু তার ধরণ হয় const char *
। এটি লিখতে পুরোপুরি ঠিক হবে printf(test ? "hi " "yes" : "hi " "no")
। ওপি এর সমস্যা সঙ্গে কিছুই করার আছে printf
, "Hi" (test ? "Bye" : "Goodbye")
কোন ব্যাপার কি অভিব্যক্তি হল প্রসঙ্গ একটি বাক্য গঠন ত্রুটি।
এটি সংকলন করে না কারণ প্রিন্টফ ফাংশনটির জন্য প্যারামিটার তালিকা
(const char *format, ...)
এবং
("Hi" (test ? "Bye" : "Goodbye"))
পরামিতি তালিকায় ফিট করে না।
জিসিসি এটি কল্পনা করে এটি বোঝার চেষ্টা করে
(test ? "Bye" : "Goodbye")
একটি প্যারামিটার তালিকা, এবং অভিযোগ করে যে "হাই" কোনও ফাংশন নয়।
printf()
আর্গুমেন্ট তালিকার সাথে মেলে না তবে এটি কারণ কারণটি কোথাও বৈধ নয় - কেবল printf()
যুক্তি তালিকায় নয়। অন্য কথায়, আপনি সমস্যার অনেক বেশি বিশেষ কারণ বেছে নিয়েছেন; সাধারণ সমস্যাটি হ'ল "Hi" (
সিটিতে বৈধ নয়, একটি কল করার সময় ছেড়ে দিন printf()
। আমি আপনাকে এই উত্তরটি নিচে ভোট দেওয়ার আগে মুছে ফেলার পরামর্শ দিচ্ছি।