সিটিতে সমতার জন্য স্ট্রাক্টকে আপনি কীভাবে তুলনা করবেন?


উত্তর:


196

সি এটি করার জন্য কোনও ভাষার সুবিধা সরবরাহ করে না - আপনাকে নিজেরাই এটি করতে হবে এবং প্রতিটি কাঠামোর সদস্যকে সদস্য দ্বারা তুলনা করতে হবে।


19
যদি 2 স্ট্রাকচার ভেরিয়েবল কলোকের সাথে আরম্ভ করা হয় বা সেগুলি মেমসেটের মাধ্যমে 0 দিয়ে সেট করা থাকে যাতে আপনি আপনার 2 টি কাঠামোকে মেমক্যাম্পের সাথে তুলনা করতে পারেন এবং কাঠামোর আবর্জনা সম্পর্কে কোনও উদ্বেগ নেই এবং এটি আপনাকে সময় উপার্জনের সুযোগ দেবে
মোহামেড

21
@ মোহেমড ফ্লোটিং পয়েন্ট ক্ষেত্রের সাথে তুলনা 0.0, -0.0 NaNকরা একটি সমস্যা memcmp()। বাইনারি উপস্থাপনায় পৃথক পয়েন্টারগুলি একই অবস্থানের দিকে নির্দেশ করতে পারে (যেমন ডস: সেগ: অফসেট) এবং তাই সমান। কিছু সিস্টেমে একাধিক নাল পয়েন্টার রয়েছে যা সমানভাবে তুলনা করে। intঅপ্রয়োজনীয় এনকোডিং সহ -0 এবং ভাসমান পয়েন্ট ধরণের অস্পষ্টতার জন্য একই । (ইন্টেল দীর্ঘ ডাবল, দশমিক ,৪, ইত্যাদি) এই সমস্যাগুলির কোনও পার্থক্য নেই যে calloc()ব্যবহৃত হয় না বা প্যাডিং হয়।
chux -

2
@ chux আমি যে কোনও আধুনিক 32- বা 64- বিট সিস্টেমটি সম্পর্কে জানি, কেবলমাত্র ভাসমান পয়েন্ট নিয়েই সমস্যা।
ডেমি

2
যদি আপনি ভাবছি কেন ==স্ট্রাকচার (আমার মত), দয়া করে দেখুন সঙ্গে কাজ করছে না stackoverflow.com/questions/46995631/...
stefanct

4
@ ডেমি: আজ। সি প্রোগ্রামারদের জন্য দশম আদেশটি হ'ল 'আপনি পুরোপুরি পোশাক পরেন, ত্যাগ করুন এবং নিন্দিত বদনামকে ঘৃণা করুন যা "বিশ্বের সমস্ত ভ্যাক্স" ... দাবি করে। এটি "সমস্ত বিশ্বের একটি পিসি" দিয়ে প্রতিস্থাপন করা কোনও উন্নতি নয়।
মার্টিন বোনার

110

আপনি ব্যবহার করতে প্রলুব্ধ হতে পারে memcmp(&a, &b, sizeof(struct foo)) , তবে এটি সমস্ত পরিস্থিতিতে কার্যকর নাও হতে পারে। সংকলকটি কোনও কাঠামোতে প্রান্তিককরণ বাফার স্থান যুক্ত করতে পারে এবং বাফার স্পেসে থাকা মেমরির অবস্থানগুলিতে পাওয়া মানগুলি কোনও নির্দিষ্ট মান হওয়ার নিশ্চয়তা দেয় না।

কিন্তু, যদি আপনি ব্যবহার callocবা memsetতাদের ব্যবহার করার আগে স্ট্রাকচার পূর্ণ আকার, আপনি করতে পারেন একটি অগভীর সঙ্গে তুলনা memcmpকরে (যদি আপনার গঠন পয়েন্টার রয়েছে, এটি শুধুমাত্র ম্যাচ হবে ঠিকানা পয়েন্টার প্রতি নির্দেশ করা হয় একই থাকেন)।


19
বন্ধ করুন, কারণ এটি "প্রায় সমস্ত" সংকলকগুলিতে কাজ করে তবে বেশ নয়। সি 90 এ 6.2.1.6.4 দেখুন: "একই বস্তুর উপস্থাপনের সাথে দুটি মান (এনএএনএস ব্যতীত) সমান তুলনা করে, তবে সমান তুলনা করা মানগুলির মধ্যে পৃথক বস্তুর উপস্থাপনা থাকতে পারে।"
স্টিভ জেসোপ

22
একটি "BOOL" ক্ষেত্র বিবেচনা করুন। সমতার ক্ষেত্রে, যে কোনও শূন্য-বিওওএল প্রতিটি শূন্য-বিওএল মানের সমান। সুতরাং 1 এবং 2 উভয়ই সত্য এবং তাই সমান হতে পারে, মেমক্যাম্প ব্যর্থ হবে।
ajs410

4
@ জাসালাজার আপনার জন্য সম্ভবত সহজতর তবে সংকলক এবং সিপিইউর পক্ষে আরও শক্ত এবং এইভাবে আরও ধীর। আপনি কেন প্রথম স্থানে সংকলক প্যাডিং যুক্ত মনে করেন? অবশ্যই কোনও কিছুর জন্য স্মৃতি নষ্ট না করা;)
কিছুর

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

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

22

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

এটি কীভাবে করবেন .... আপনার প্রতিটি উপাদান পৃথকভাবে তুলনা করতে হবে


1
আমি এটি একবার ব্যবহার করতে চাইলেও আমি একটি পৃথক ফাংশন লিখব।
স্যাম

18

স্ট্রাক্টের ক্ষেত্রে ক্ষেত্রের মধ্যে সম্ভাব্য র্যান্ডম প্যাডিং অক্ষরের কারণে সাম্যের জন্য স্ট্রাকগুলি তুলনা করতে আপনি মেমক্যাম্প ব্যবহার করতে পারবেন না।

  // bad
  memcmp(&struct1, &struct2, sizeof(struct1));

উপরেরগুলি এই জাতীয় কাঠামোর জন্য ব্যর্থ হবে:

typedef struct Foo {
  char a;
  /* padding */
  double d;
  /* padding */
  char e;
  /* padding */
  int f;
} Foo ;

নিরাপদ থাকতে আপনাকে সদস্যবিহীন তুলনা ব্যবহার করতে হবে।


25
দ্বিগুণ পরে প্যাডিং করা অসম্ভব; চরটি পুরোপুরি পর্যাপ্তরূপে ডাবলের পরের দিকে সংযুক্ত হবে।
জোনাথন লেফলার

7

@ গ্রেগ সঠিক যে সাধারণ ক্ষেত্রে একটি সুস্পষ্ট তুলনা ফাংশন লিখতে হবে।

এটি ব্যবহার করা সম্ভব memcmpযদি:

  • স্ট্রাক্টগুলিতে সম্ভবত কোনও ভাসমান-পয়েন্ট ক্ষেত্র নেই NaN
  • স্ট্রাক্টগুলিতে কোনও প্যাডিং থাকে না ( -Wpaddedএটি পরীক্ষা করার জন্য ঝাঁকুনির সাথে ব্যবহার করুন ) অথবা স্ট্রাক্টগুলি স্পষ্টভাবে দিয়ে শুরু করা হয়memset করা হয়।
  • কোনও সদস্যের ধরণের (যেমন উইন্ডোজ BOOL) আলাদা নয় তবে সমমানের মান রয়েছে।

আপনি এম্বেড থাকা সিস্টেমগুলির জন্য প্রোগ্রামিং না করা (বা তাদের উপর ব্যবহৃত হতে পারে এমন একটি গ্রন্থাগার লেখার জন্য), আমি সি স্ট্যান্ডার্ডের কয়েকটি কোণার বিষয়ে চিন্তা করব না। নিকটতম বনাম দূরের পয়েন্টার পার্থক্যটি কোনও 32- বা 64- বিট ডিভাইসে বিদ্যমান নেই। আমি জানি না এমন কোনও অ-এমবেডেড সিস্টেমের একাধিক নেইNULL পয়েন্টার নেই।

আরেকটি বিকল্প হ'ল সাম্যতা ফাংশনগুলি স্বয়ংক্রিয়ভাবে উত্পন্ন করা। আপনি যদি আপনার স্ট্রাক্ট সংজ্ঞাগুলি একটি সহজ উপায়ে রেখে দেন তবে সাধারণ কাঠামো সংজ্ঞাগুলি পরিচালনা করতে সাধারণ পাঠ্য প্রক্রিয়াকরণ ব্যবহার করা সম্ভব। আপনি সাধারণ কেসের জন্য লাইব্লাক্ল্যাং ব্যবহার করতে পারেন - যেহেতু এটি ক্ল্যাংয়ের মতো একই সীমানা ব্যবহার করে, এটি কোণার সমস্ত ক্ষেত্রে সঠিকভাবে পরিচালনা করে (বাগগুলি ব্যতীত)।

এরকম কোড জেনারেশন লাইব্রেরি আমি দেখিনি। তবে এটি তুলনামূলক সহজ appears

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


2
স্পষ্টভাবে সঙ্গে structs মধ্যে আরম্ভের memset, ইত্যাদি একটি struct উপাদানে আরও লেখা পরে প্যাডিং বিট মান নিশ্চয়তা দেয় না, দেখুন: stackoverflow.com/q/52684192/689161
gengkev

4

দ্রষ্টব্য আপনি প্যাডিংয়ের বিষয়ে চিন্তা না করেই স্ট্যাটাসহীন স্টাচচারে মেমক্যাম্প () ব্যবহার করতে পারেন, যতক্ষণ না আপনি সমস্ত সদস্যকে (একবারে) আরম্ভ করবেন। এটি সি 90 দ্বারা সংজ্ঞায়িত করা হয়েছে:

http://www.pixelbeat.org/programming/gcc/auto_init.html


1
এটি কি নির্দিষ্ট করে দেওয়া হয়েছে যা {0, }কোনও প্যাডিং বাইটও শূন্য করবে?
Alnitak

উপরের লিঙ্কটিতে প্রদর্শিত হিসাবে আংশিকভাবে প্রাথমিক স্ট্রাক্টগুলির জন্য কমপক্ষে জিরো প্যাডিং বাইটস এবং সি -11 সেই আচরণটি সুনির্দিষ্টভাবে বিশদ বিবরণ করে যে স্ট্যাকওভারফ্লো / প্রশ্নগুলি / ১১৩০16364//২
পিক্সেলবিট

1
সাধারণভাবে খুব কার্যকর নয়, কারণ যে কোনও সদস্যকে অর্পণ করার পরে সমস্ত প্যাডিং অনির্দিষ্ট হয়ে যায়
এমএম

2

আপনি যে প্রশ্নটি জিজ্ঞাসা করছেন তা এটি নির্ভর করে:

  1. এই দুটি স্ট্রাক্ট কি একই জিনিস?
  2. তাদের কি একই মূল্য আছে?

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

বিশেষ ক্ষেত্রে যেখানে স্ট্রাইকগুলিতে পয়েন্টার থাকে না আপনি তথ্যের অর্থ কী তা জেনেও প্রতিটিতে থাকা তথ্যের সাথে কিছুটা তুলনা করার জন্য একটি মেমক্যাম্প করতে পারেন।

প্রতিটি সদস্যের জন্য 'সমান' এর অর্থ কী তা আপনি জানেন তা নিশ্চিত করুন - এটি ভাসমান-পয়েন্টের মান বা ব্যবহারকারী-সংজ্ঞায়িত ধরণের ক্ষেত্রে ইন্টের পক্ষে সুস্পষ্ট তবে আরও সূক্ষ্ম।


2

memcmp কাঠামো তুলনা করে না, memcmp বাইনারি তুলনা করে, এবং সর্বদা আবর্জনা থাকে, সুতরাং এটি সর্বদা তুলনায় মিথ্যা বেরিয়ে আসে।

উপাদানটিকে নিরাপদ হিসাবে উপাদানটির সাথে তুলনা করুন এবং ব্যর্থ হন না।


1
যদি 2 স্ট্রাকচার ভেরিয়েবল কলোকের সাথে আরম্ভ করা হয় বা সেগুলি মেমসেটের সাহায্যে 0 দিয়ে সেট করা থাকে যাতে আপনি আপনার 2 টি কাঠামো মেমক্যাম্পের সাথে তুলনা করতে পারেন এবং কাঠামোর আবর্জনা সম্পর্কে কোনও উদ্বেগ নেই এবং এটি আপনাকে সময় উপার্জনের সুযোগ দেবে
মোহামেড

1

যদি স্ট্রাক্টগুলিতে কেবল আদিম থাকে বা আপনি যদি কঠোর সাম্যের দিকে আগ্রহী হন তবে আপনি এর মতো কিছু করতে পারেন:

ইন্ট মাই_স্ট্রিক্ট_সিএমপি (কনস্ট্রাক্ট মাই_স্ট্রাক্ট * এলএইচএস, কনস্ট্রাক্ট মাই_স্ট্রিক্ট * আরএইচএস)
{
    রিটার্ন মেমক্যাম্প (এলএইচএস, আরশ, মাপ (স্ট্রাক্ট মাই_স্ট্রিক্ট));
}

তবে, যদি আপনার স্ট্রাক্টগুলিতে অন্যান্য স্ট্রাক্ট বা ইউনিয়নগুলিতে পয়েন্টার থাকে তবে আপনাকে এমন একটি ফাংশন লিখতে হবে যা আদিমদের সঠিকভাবে তুলনা করবে এবং অন্যান্য কাঠামোর তুলনায় যথাযথ তুলনা কল করবে make

তবে সচেতন থাকুন যে আপনার এডিটি আরম্ভের অংশ হিসাবে কাঠামোগুলির মেমরির পরিসীমা শূন্য করতে আপনার মেমসেট (& a, মাপের (স্ট্রাক্ট মাই_স্ট্রাক্ট), 1) ব্যবহার করা উচিত ছিল।


-1

যদি 2 স্ট্রাকচার ভেরিয়েবল কলোকের সাথে আরম্ভ করা হয় বা সেগুলি মেমসেটের মাধ্যমে 0 দিয়ে সেট করা থাকে যাতে আপনি আপনার 2 টি কাঠামোকে মেমক্যাম্পের সাথে তুলনা করতে পারেন এবং কাঠামোর আবর্জনা নিয়ে কোনও উদ্বেগ নেই এবং এটি আপনাকে সময় উপার্জনের অনুমতি দেবে


-2

এই অনুবর্তী উদাহরণটি কাঠামোর সদস্যদের যথাসম্ভব শক্তভাবে প্যাক করা হয়েছে তা নিশ্চিত করার জন্য মাইক্রোসফ্ট ভিজ্যুয়াল স্টুডিও থেকে # প্রগমা প্যাক সংকলক এক্সটেনশন ব্যবহার করে:

#include <string.h>

#pragma pack(push, 1)
struct s {
  char c;
  int i;
  char buffer[13];
};
#pragma pack(pop)

void compare(const struct s *left, const struct s *right) { 
  if (0 == memcmp(left, right, sizeof(struct s))) {
    /* ... */
  }
}

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