"এ"! = "এ" সি তে কেন?


110
void main() {
    if("a" == "a")
      printf("Yes, equal");  
    else
      printf("No, not equal");
}

আউটপুট কেন No, not equal?


100
void main??? ইও ...
পল আর

47
এম্বেডেড সি সংকলকগুলি শূন্য মূল () এর অনুমতি দেয় কারণ কোনও রিটার্ন কোড দেওয়ার জন্য কোনও অপারেটিং সিস্টেম নাও থাকতে পারে।
জিনে পিন্ডার

26
এই জাতীয় প্রশ্ন এত ঘন ঘন কীভাবে উত্থিত হতে পারে? এটি সত্যই আকর্ষণীয় নয় ... মানে, স্ট্রিংগুলি অ্যারে এবং অ্যারেগুলি পয়েন্টারগুলি সত্যই সি-তে একটি পুরানো টুপি, তাই না?
ফেলিক্স ডমব্যাক

64
@ ফেলিক্স, এটি একটি সংক্ষিপ্ত-লিখিত প্রশ্ন যা ভাষায় নতুনদের জন্য বিভ্রান্তির একটি সাধারণ বিষয়কে সম্বোধন করে। SO কেবল বিশেষজ্ঞদের জন্য নয় - এটি প্রাথমিকভাবেও এবং এটির মতো লক্ষ্যবস্তু প্রশ্নগুলি ভবিষ্যতে প্রারম্ভিকদের উল্লেখ করার জন্য ভাল।
বিডোনলা

37
@ ফেলিক্স: আপনি ভুল বলেছেন। অ্যারেগুলি পয়েন্টার নয়
জন ডিবলিং 31'11

উত্তর:


209

আপনি যা তুলনা করছেন তা হ'ল দুটি স্ট্রিমের জন্য দুটি মেমরি ঠিকানা, যা বিভিন্ন জায়গায় সঞ্চিত থাকে। এটি করা মূলত এর মত দেখাচ্ছে:

if(0x00403064 == 0x002D316A) // Two memory locations
{
    printf("Yes, equal");
}

দুটি স্ট্রিং মানগুলির তুলনা করতে নিম্নলিখিত কোডটি ব্যবহার করুন:

#include <string.h>

...

if(strcmp("a", "a") == 0)
{
    // Equal
}

উপরন্তু, "a" == "a" আপনার সংকলকটির উপর নির্ভর করে সত্যই ফিরে আসতে পারে, যা স্থান সংরক্ষণের জন্য সংকলন সময়ে সমান স্ট্রিংগুলিকে একত্রিত করতে পারে।

আপনি যখন দুটি চরিত্রের মান তুলনা করছেন (যা পয়েন্টার নয়), এটি একটি সংখ্যার তুলনা। উদাহরণ স্বরূপ:

'a' == 'a' // always true

12
জিসিসি এছাড়াও বিকল্প রয়েছে -fmerge-constantsএবং -fno-merge-constantsযদিও কিছু GCCs তে এটি মনে হচ্ছে যে ধ্রুবক মার্জ সবসময় যে বিকল্প নির্বিশেষে সক্ষম হলে, সক্ষম করতে / অক্ষম STRING এবং ফ্লোটিং পয়েন্ট ধ্রুবক অনুবাদ ইউনিট জুড়ে মার্জ।
অ্যাডাম রোজেনফিল্ড

2
আপনি "a" এর পরিবর্তে 'a' ব্যবহার করলে এটি কাজ করবে। প্রথমটি একটি চর, যা আসলে একটি সংখ্যার মান।
গোলেজট্রোল

@ গোলেজট্রোল: সি-তে, আক্ষরিক 'এ' আসলে intটাইপ করে। :-) এছাড়াও, পয়েন্টারগুলিতে সংখ্যার মান হওয়া উচিত নয়।
বাসটিয়েন লোনার্ডার্ড

intসংখ্যাও খুব, তাই না? তবে আমি ভেবেছিলাম চরগুলি বাইট ছিল। ইন্ট 4 বাইট। পয়েন্টারগুলি নিজেরাই পূর্ণসংখ্যার হয়। এগুলিতে একগুচ্ছ ডেটার ঠিকানা থাকে (এমন ডেটা যা আসলে সংখ্যায়িক হতে হয় না)।
GolezTrol

'a' == 'A' // not true... মাইএসকিউএল পৃথক হতে অনুরোধ করে।
স্টিভেন

52

আমি পার্টিতে কিছুটা দেরি করেছি, তবে আমি যেভাবেই হোক জবাব দেব; প্রযুক্তিগতভাবে একই বিট, তবে কিছুটা ভিন্ন দৃষ্টিকোণ থেকে (নীচে সি পার্লেন্স):

সিতে, অভিব্যক্তিটি "a"একটি স্ট্রিং আক্ষরিককে চিহ্নিত করে , যা একটি স্থির নামবিহীন অ্যারে const char, দুটি দৈর্ঘ্য সহ - অ্যারে বর্ণগুলি 'a'এবং'\0' - সমাপ্ত নাল অক্ষরটি স্ট্রিংয়ের শেষের ইঙ্গিত দেয়।

তবে সি-তে একইভাবে আপনি মান অনুসারে ফাংশনগুলিতে অ্যারেগুলি পাস করতে পারবেন না - বা তাদের মান ( সূচনাকরণের পরে ) নির্ধারণ করতে পারবেন - ==অ্যারেগুলির জন্য কোনও ওভারলোডেড অপারেটর নেই , সুতরাং তাদের সরাসরি তুলনা করা সম্ভব নয়। বিবেচনা

int a1[] = {1, 2, 3};
int a2[] = {3, 4, 5};
a1 == a2 // is this meaningful? Yes and no; it *does* compare the arrays for
         // "identity", but not for their values. In this case the result
         // is always false, because the arrays (a1 and a2) are distinct objects

যদি ==অ্যারেগুলির সাথে তুলনা না করা হয় তবে এটি আসলে কী করে? সিতে, প্রায় সমস্ত প্রসঙ্গে - এই এক সহ - অ্যারে পয়েন্টারগুলিতে ক্ষয় হয় (অ্যারের প্রথম উপাদানটি সেই বিন্দু) - এবং সমতার জন্য পয়েন্টারগুলির সাথে তুলনা করা আপনি যা প্রত্যাশা করতেন তা করে। তাই কার্যকরভাবে, যখন এই করছেন

"a" == "a"

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

অন্যরা যেমন উল্লেখ করেছে, "সি স্ট্রিং" তুলনা করতে (যেমন নাল অক্ষর দিয়ে স্ট্রিংগুলি সমাপ্ত করা হয়েছে) আপনি strcmpস্ট্যান্ডার্ড শিরোনাম ফাইলে পাওয়া সুবিধা ফাংশনটি ব্যবহার করেন string.h0সমান স্ট্রিংগুলির জন্য ফাংশনটির একটি রিটার্ন মান রয়েছে ; 0অপারেটর of! ´ ব্যবহারের পরিবর্তে সুস্পষ্টভাবে রিটার্নের মানটির তুলনা করা ভাল অনুশীলন হিসাবে বিবেচিত হয়

strcmp(str1, str2) == 0 // instead of !strcmp(str1, str2)

47

সি 99 অনুসারে (বিভাগ 6.4.5 / 6)

স্ট্রিং লিটারালস

এই অ্যারেগুলি পৃথক পৃথক কিনা তাদের উপাদানগুলির উপযুক্ত মান রয়েছে কিনা তা অনির্দিষ্ট

সুতরাং এই ক্ষেত্রে এটি উভয়ই "a"স্বতন্ত্র কিনা তা অনির্দিষ্ট । একটি অনুকূলিত সংকলকটি "a"কেবল পঠনযোগ্য স্থানে একক রাখতে পারে এবং উভয় উল্লেখই এটি উল্লেখ করতে পারে।

এখানে জিসিসিতে আউটপুট পরীক্ষা করে দেখুন


19

কারণ এগুলি 2 পৃথক const char*, পয়েন্টার, প্রকৃত মান নয়। আপনি এমন কিছু বলছেন 0x019181217 == 0x0089178216যা অবশ্যই কোনটি ফেরত দেয় না

strcmp()পরিবর্তে ব্যবহার করুন==


7
স্ট্রিং লিটারেলগুলি পয়েন্টার নয়, তারা অ্যারে। তারা তুলনায় পয়েন্টার ক্ষয়, যদিও।
GManNickG

@ জেমন সত্য, সত্য যে স্পষ্ট না হওয়ার জন্য দুঃখিত, এটি ভুলে যাবেন :)
আন্তওয়ান ভ্যান হড

9

সহজ কথায় বলতে গেলে সি এর কোনও অন্তর্নির্মিত স্ট্রিং তুলনা অপারেটর নেই। এটি স্ট্রিংকে এইভাবে তুলনা করতে পারে না।

পরিবর্তে, স্ট্রিংগুলি স্ট্যান্ডার্ড লাইব্রেরি রুটিন যেমন স্ট্রিম্প () ব্যবহার করে বা স্ট্রিংয়ের প্রতিটি অক্ষরের মধ্য দিয়ে লুপ করতে কোড লেখার সাথে তুলনা করা হয়।

সি-তে, ডাবল উদ্ধৃতিতে পাঠ্যের একটি স্ট্রিং একটি পয়েন্টারকে স্ট্রিংয়ে ফিরে আসে। আপনার উদাহরণটি পয়েন্টারগুলির সাথে তুলনা করছে এবং স্পষ্টতই আপনার স্ট্রিংয়ের দুটি সংস্করণ বিভিন্ন ঠিকানায় বিদ্যমান।

তবে এটি নিজের মতো করে স্ট্রিংগুলি তুলনা করছে না বলে মনে হচ্ছে।


3

পয়েন্টার।

প্রথম "a" নাল-টার্মিনেটেড এএসসিআইআই স্ট্রিংয়ের পয়েন্টার।

দ্বিতীয় "a" হল নাল-টার্মিনেটেড এএসসিআইআই স্ট্রিংয়ের পয়েন্টার।

আপনি যদি 32-বিট সংকলক ব্যবহার করেন তবে আমি আশা করব "a"=="a"-4। আমি সবেমাত্র এটি টিসিসি / উইন 32 দিয়ে চেষ্টা করেছি এবং পেয়েছি "a"=="a"-2। আচ্ছা ভালো...


6
আপনি কেন স্ট্রিংগুলি 4-বাইট সীমানায় সংযুক্ত হওয়ার প্রত্যাশা করবেন? তারা ints না। 2 যা আমি প্রত্যাশা করি (যদি সংকলক সেগুলিকে একীভূত না করে), যেহেতু প্রতিটি স্ট্রিং নাল টার্মিনেটর সহ দুটি বাইট দীর্ঘ।
সের্গেই টেচেনভ

প্রান্তিককরণের কিছু ডিগ্রী উদাহরণস্বরূপ, strcmpএকবারে কয়েকটি বাইট চালানোর অনুমতি দিতে পারে। কিছু সংকলক এটি করেন, কেউ করেন না, কেউ এটি কেবল কিছু
ন্যূনতমের

@ জ্যাক: তারা আসলে স্ট্রিংয়ের তুলনা করার আগে তাদের দৈর্ঘ্যটি কীভাবে জানবে?
জোচিম সউর

আমার অর্থ, কিছু সংকলক কিছু ন্যূনতমের চেয়ে দীর্ঘতর স্ট্রিংগুলি সারিবদ্ধ করে।
zwol

1

আপনি দুটি মেমরি ঠিকানার তুলনা করছেন, ফলে ফলাফলটি সর্বদা সত্য হয় না। আপনি চেষ্টা করেছেন if('a' == 'a'){...}?


1

এই প্রশ্নটি সমস্ত প্রারম্ভিকদের জন্য ব্যাখ্যার খুব ভাল ট্রেইল সেট করে ....
আমাকেও এতে অবদান রাখুন .....

উপরের সবাই যেমন ব্যাখ্যা করেছে, কেন আপনি এমন আউটপুট পাচ্ছেন।

এখন আপনি যদি আপনার অগ্রগতি চান। "হ্যাঁ সমান" মুদ্রণ করতে

হয় ব্যবহার

if(strcmp("a", "a") == 0)
{

}

অথবা
স্ট্রিং হিসাবে "ক" ব্যবহার করবেন না, তাদের অক্ষর হিসাবে ব্যবহার করুন ....

if('a'=='a')  
{  
printf ("yes Equal");  
}  

সি অক্ষরে 1 বাইট সংক্ষিপ্ত পূর্ণসংখ্যার .......


অক্ষরগুলি কেবল 1 বাইট দখল করে তবে চরিত্রের আক্ষরিক যেমন 'a'বাস্তবে পূর্ণসংখ্যা হয়।
স্পাইডি

0

কিছু সংকলকগুলির 'মার্জ স্ট্রিং' বিকল্প রয়েছে যা আপনি সমস্ত ধ্রুবক স্ট্রিংকে একই ঠিকানা করতে বাধ্য করতে ব্যবহার করতে পারেন। আপনি যদি এটি ব্যবহার করেন, "a" == "a"হবে true


0

অক্ষরের মধ্যে তুলনা যদি সর্বদা একক উদ্ধৃতিতে থাকে, যেমন

if('a' == 'a')

এবং সি স্ট্রিং তুলনার মতো সমর্থন করতে পারে না "abc" == "abc"

এটা দিয়ে শেষ strcmp("abc","abc")


-5

এই লোকটি ভেরিয়েবল ব্যবহার করে না। পরিবর্তে, তিনি অস্থায়ীভাবে পাঠ্য অ্যারেগুলি ব্যবহার করেন: aএবং a। কারণ কেন

void main() 
{
    if("a" == "a")
      printf("Yes, equal");  
    else
      printf("No, not equal");
}

অবশ্যই কাজ করে না, আপনি ভেরিয়েবলের তুলনা করেন না।
আপনি যদি ভেরিয়েবলগুলি তৈরি করতে চান তবে:

চর * পাঠ্য = "ক";
চর * পাঠ্য 2 = "এ";

তারপর আপনি তুলনা পারে textসঙ্গে text2, এবং এটি হওয়া উচিত সত্য

সম্ভবত আপনি ব্যবহার করতে ভুলবেন না {এবং }=)

void main() {
    if("a" == "a")
    {
      printf("Yes, equal");
    }
    else
    {
      printf("No, not equal");
    }
}

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