যদি কোনও শূন্য পয়েন্টার (শূন্য *) দুটি ডেটা ধরণের একটি হয় তবে যাচাই করবেন কীভাবে?


10

আমি একটি ফাংশন লিখছি যেখানে আমি 2 typeটি পরামিতি গ্রহণ করতে চাই ।

  • string(চর *)
  • একটি structureযেখানে এন সংখ্যক উপাদান থাকবে।

এবং এটি অর্জন করার জন্য আমি void *প্যারামিটার ধরণের হিসাবে একটি সহজ ব্যবহার করার কথা ভাবছি । তবে আমি জানিনা কীভাবে প্যারামিটারটি এক প্রকারের বা অন্য, নিরাপদে কিনা তা যাচাই করতে হবে।


10
আপনি পারবেন না! খুব কমপক্ষে, আপনাকে ফাংশনে একটি দ্বিতীয় প্যারামিটার যুক্ত করতে হবে যা void*পয়েন্টগুলি নির্দেশ করে।
অ্যাড্রিয়ান মোল

4
... এবং আপনি কি একটি দ্বিতীয় প্যারামিটার যোগ আছে, তাহলে আপনি ঠিক যেমন ভাল দুটি পৃথক ফাংশন লিখতে পারে func_strএবং func_structএবং কম্পাইল সময়ে টাইপ চেক করুন।
এম Oehm

হ্যাঁ এ কারণেই আমি ভাবছিলাম যদি এটি শুধুমাত্র একটি ফাংশনে সম্ভব হয়
লোকালহোস্ট

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

আপনি যদি কেবল স্ট্রিং এবং স্ট্রাক্ট ফাংশনগুলির জন্য একটি সাধারণ নাম চান তবে আপনি _Genericম্যাক্রো ব্যবহার করতে পারেন । আপনি স্ব-শনাক্তকরণের ধরনগুলি তৈরি করতে পারেন, উদাহরণস্বরূপ ট্যাগযুক্ত ইউনিয়নগুলির সাথে , যার অর্থ হল আপনি কোনও কাঁচা char *স্ট্রিং পাস করতে পারবেন না । এগুলি সম্ভবত এটির চেয়ে বেশি সমস্যা is
এম Oehm

উত্তর:


12

অনুবাদটি void*হ'ল
"প্রিয় সংকলক, এটি একটি পয়েন্টার, এটিতে আপনার জন্য কোনও অতিরিক্ত তথ্য নেই।

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

সুতরাং শেষ পর্যন্ত void*তথ্য টাইপ থাকে না।
অনেক প্রোগ্রামার এটিকে "আমার কাছে টাইপ তথ্যটি জানার দরকার নেই" বলে ভুল বুঝে।
তবে বিপরীতটি সত্য, প্রকারের তথ্যের উপর নজর রাখার জন্য এবং প্রোগ্রাম / সংকলককে এটির জন্য যথাযথভাবে সরবরাহ করার জন্য প্রোগ্রামারটির দায়িত্ব void* বৃদ্ধি করে।


তদতিরিক্ত, সংকলকটি আসলে জানে যে কীভাবে ডেটার পয়েন্ট-এ হয়। সুতরাং আপনি যদি কোনও void*ফাংশনে ঝাঁপিয়ে পড়ে , ভুল প্রকারে ফেলে দেন, তবে ডেটাটিকে রেফারেন্স করুন ... তারপরে সমস্ত ধরণের অপরিজ্ঞাত আচরণের জন্য অনুরোধ করা হয়েছে।
লন্ডিন

5

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

পরিবর্তে আপনার সি 11 ব্যবহার করা উচিত _Genericযা সংকলন সময়ে প্রকারগুলি পরীক্ষা করতে এবং প্রকারের সুরক্ষা যুক্ত করতে পারে। উদাহরণ:

#include <stdio.h>

typedef struct
{
  int n;
} s_t; // some struct

void func_str (const char* str)
{
  printf("Doing string stuff: %s\n", str);
}

void func_s (const s_t* s)
{
  printf("Doing struct stuff: %d\n", s->n);
}

#define func(x) _Generic((x),              \
  char*: func_str, const char*: func_str,  \
  s_t*:  func_s,   const s_t*:  func_s)(x) \


int main()
{
  char str[] = "I'm a string";
  s_t s = { .n = 123 };

  func(str);
  func(&s); 
}

constআপনি সমর্থন করতে চান এমন সমস্ত ধরণের যোগ্য ( ) সংস্করণ সরবরাহ করতে ভুলবেন না ।


যদি কলারটি ভুল প্রকারটি পাস করে আপনি আরও ভাল সংকলক ত্রুটিগুলি চান, আপনি একটি স্ট্যাটিক দাবী যুক্ত করতে পারেন:

#define type_check(x) _Static_assert(_Generic((x), \
  char*:   1,  const char*: 1,  \
  s_t*:    1,  const s_t*:  1,  \
  default: 0), #x": incorrect type.")

#define func(x) do{ type_check(x); _Generic((x),     \
  char*: func_str, const char*: func_str,            \
  s_t*:  func_s,   const s_t*:  func_s)(x); }while(0) 

আপনি যদি এমন কিছু চেষ্টা করেন তবে আপনি int x; func(x);সংকলক বার্তাটি পাবেন "x: incorrect type"

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