টাইপদেফ ফাংশন পয়েন্টার?


458

আমি কীভাবে গতিশীলভাবে ডিএলএল লোড করব তা শিখছি তবে যা আমি বুঝতে পারি না তা এই লাইন

typedef void (*FunctionFunc)();

আমার কিছু প্রশ্ন আছে। যদি কেউ তাদের উত্তর দিতে সক্ষম হয় তবে আমি কৃতজ্ঞ হব।

  1. কেন typedefব্যবহার করা হয়?
  2. বাক্য গঠনটি অদ্ভুত দেখাচ্ছে; পরে voidকোন ফাংশন নাম বা কিছু থাকা উচিত? এটি একটি বেনামি ফাংশনের মতো দেখাচ্ছে।
  3. কোনও ফাংশনের মেমরি ঠিকানা সঞ্চয় করার জন্য কোনও ফাংশন পয়েন্টার তৈরি করা হয়েছে?

তাই আমি এই মুহূর্তে বিভ্রান্ত; আপনি কি আমার জন্য বিষয় পরিষ্কার করতে পারেন?


5
লিঙ্কটি একবার দেখুন (সর্বশেষ বিভাগ) learnncpp.com/cpp-tutorial/78-function-pointers
উত্সাহী

9
উল্লেখ্য যে যেহেতু using FunctionFunc = void (*)();পরিবর্তে সি ++ 11 ব্যবহার করা যেতে পারে। এটি কিছুটা স্পষ্ট যে আপনি কেবল কোনও প্রকারের জন্য নাম ঘোষণা করছেন (ফাংশনটি নির্দেশক)
ব্যবহারকারী 362515

শুধু @ ব্যবহারকারী 362515 এ যুক্ত করার জন্য, আমার কাছে কিছুটা পরিষ্কার ফর্মটি হ'ল:using FunctionFunc = void(void);
টপসপিন

@ টপস্পিন আইআইআরসি এই দুটি একই নয়। একটি হ'ল ফাংশন পয়েন্টার টাইপ, অন্যটি ফাংশন টাইপ। এখানে অন্তর্নিহিত রূপান্তর রয়েছে, এজন্য এটি কাজ করে, আইএএনএ (সি ++) এল তাই, কেউ আমাকে পদক্ষেপে সংশোধন করতে পারে। যাই হোক না কেন, উদ্দেশ্য যদি কোনও পয়েন্টার টাইপকে সংজ্ঞায়িত করে তবে আমি মনে করি এর সিনট্যাক্সটি *কিছুটা আরও স্পষ্ট।
ব্যবহারকারী 36251515

উত্তর:


463

typedefএকটি ভাষা গঠন যা একটি নামকে একটি প্রকারের সাথে সংযুক্ত করে।
উদাহরণস্বরূপ, আপনি এটি একইভাবে ব্যবহার করুন আপনি আসল প্রকারটি ব্যবহার করবেন

  typedef int myinteger;
  typedef char *mystring;
  typedef void (*myfunc)();

তাদের মত ব্যবহার

  myinteger i;   // is equivalent to    int i;
  mystring s;    // is the same as      char *s;
  myfunc f;      // compile equally as  void (*f)();

আপনি দেখতে পাচ্ছেন, আপনি উপরে বর্ণিত সংজ্ঞা দিয়ে কেবল টাইপফিড নামটি প্রতিস্থাপন করতে পারেন ।

অসুবিধা সি এবং সি ++ এ ফাংশন সিনট্যাক্স এবং পঠনযোগ্যতার পয়েন্টারের মধ্যে রয়েছে এবং এই typedefজাতীয় ঘোষণার পাঠযোগ্যতা উন্নত করতে পারে। তবে বাক্য গঠনটি যথাযথ, যেহেতু ফাংশনগুলি - অন্যান্য সাধারণ ধরণের থেকে পৃথক - একটি রিটার্ন মান এবং প্যারামিটার থাকতে পারে, এভাবে ফাংশনটির জন্য পয়েন্টারটির কখনও কখনও দীর্ঘ এবং জটিল ঘোষণা হয়।

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

আপনার তিনটি প্রশ্নের উত্তর দিতে

  • টাইপেইফ কেন ব্যবহার করা হয়? কোডটি পড়া সহজ করার জন্য - বিশেষত ফাংশনগুলির নির্দেশক বা কাঠামোর নামগুলির জন্য।

  • সিনট্যাক্সটি অদ্ভুত দেখায় (ঘোষণার জন্য নির্দেশকের মধ্যে) সেই বাক্য গঠনটি কমপক্ষে শুরু করার সময় পড়তে পারা যায় না। typedefপরিবর্তে একটি ঘোষণা ব্যবহার করে পড়া সহজ হয় reading

  • কোনও ফাংশনের মেমরি ঠিকানা সঞ্চয় করার জন্য কোনও ফাংশন পয়েন্টার তৈরি করা হয়েছে? হ্যাঁ, একটি ফাংশন পয়েন্টার একটি ফাংশনের ঠিকানা সঞ্চয় করে। এটির typedefনির্মাণের সাথে কোনও সম্পর্ক নেই যা কেবল কোনও প্রোগ্রামের লেখা / পড়া সহজ করে দেয়; সংকলক প্রকৃত কোড সংকলনের আগে টাইপডেফ সংজ্ঞাটি কেবল প্রসারিত করে।

উদাহরণ:

typedef int (*t_somefunc)(int,int);

int product(int u, int v) {
  return u*v;
}

t_somefunc afunc = &product;
...
int x2 = (*afunc)(123, 456); // call product() to calculate 123*456

6
শেষ উদাহরণে, কেবল 'বর্গক্ষেত্র' একই জিনিসকে বোঝায় না কারণ & বর্গ ব্যবহারের পরিবর্তে ফাংশনটির পয়েন্টার।
প্রণবক

2
প্রশ্ন, আপনার প্রথম টাইপিডের উদাহরণে আপনার ফর্মটি রয়েছে typedef type aliasতবে ফাংশন পয়েন্টার সহ কেবলমাত্র 2 টি আর্গুমেন্ট বলে মনে হয় typedef type,। টাইপ আর্গুমেন্টে উল্লিখিত নামটির সাথে কি ওরফে ডিফল্ট করা আছে?
hetচেত্রি

2
@ প্রণভক: হ্যাঁ, squareএবং &square(এবং, প্রকৃতপক্ষে *squareএবং **square) সমস্ত একই ফাংশন পয়েন্টারকে বোঝায়।
জোনাথন লেফলার

6
@ ব্যবহারকারী 814628: আপনি কী জিজ্ঞাসা করছেন তা পুরোপুরি পরিষ্কার নয়। সাথে typedef int newname, আপনি newnameএকটি উপাধি তৈরি করছেন int। এর সাথে typedef int (*func)(int), আপনি এর funcজন্য একটি উপাধি তৈরি করছেন int (*)(int)- একটি intযুক্তি গ্রহণ এবং একটি intমূল্য ফেরত দেওয়ার জন্য একটি পয়েন্টার ।
জোনাথন লেফলার

10
আমি অনুমান করি আমি অর্ডারটি সম্পর্কে কেবল বিভ্রান্ত। টাইপিডেফের সাথে int (*func)(int), আমি বুঝতে পারি যে ফানক একটি উপনাম, কেবলমাত্র কিছুটা বিভ্রান্ত কারণ উপনামটি টাইপের সাথে জটলা। দ্বারা Going typedef int INTএকটি উদাহরণ আমি আরাম আরো হবে যদি হয় typedef ফাংশন পয়েন্টার ফর্মের ছিল typedef int(*function)(int) FUNC_1। সেভাবে আমি একের মধ্যে মিশ্রিত না হয়ে টাইপ এবং ওরফে দুটি পৃথক টোকেনে দেখতে পারি।
hetেচেত্রি

188
  1. typedefউপন্যাসের ধরণে ব্যবহৃত হয়; এই ক্ষেত্রে আপনি aliasing করছি FunctionFuncকরার void(*)()

  2. প্রকৃতপক্ষে সিনট্যাক্সটি দেখতে অদ্ভুত লাগে না, এটি দেখুন:

    typedef   void      (*FunctionFunc)  ( );
    //         ^                ^         ^
    //     return type      type name  arguments
  3. না, এটি সহজভাবে সংকলককে বলে যে FunctionFuncটাইপটি একটি ফাংশন পয়েন্টার হবে, এটি এর মতো এটির সংজ্ঞা দেয় না :

    FunctionFunc x;
    void doSomething() { printf("Hello there\n"); }
    x = &doSomething;
    
    x(); //prints "Hello there"

27
typedefনতুন ধরণের ঘোষণা দেয় না । আপনার typedefএকই ধরণের অনেকগুলি সংজ্ঞায়িত নাম থাকতে পারে এবং সেগুলি আলাদা নয় (উদাহরণস্বরূপ, ক্রিয়াকলাপগুলি ওভারলোডিং)। কিছু পরিস্থিতি রয়েছে যেখানে আপনি নামটি কীভাবে ব্যবহার করতে পারেন সে সম্পর্কে একটি typedefনির্দিষ্ট-সংজ্ঞায়িত নামটি এর সংজ্ঞা অনুসারে ঠিক সমান নয়, তবে একাধিক সংজ্ঞায়িত typedefনামগুলি সমান equivalent
চিয়ার্স এবং এইচটিএইচ - আল্ফ

আহ আমি এখন এটি পেতে। ধন্যবাদ।
জ্যাক হারভিন

4
প্রশ্নের উত্তর 2 +1 - খুব পরিষ্কার। বাকী উত্তরগুলিও পরিষ্কার ছিল, তবে
সেটাই

33

ছাড়া typedefশব্দ, C ++ ঘোষণা একটি পরিবর্তনশীল ঘোষণা করা হবে FunctionFuncটাইপ পয়েন্টার কোন আর্গুমেন্ট ফাংশন, ফিরে void

সঙ্গে typedefএটি পরিবর্তে সংজ্ঞায়িত FunctionFuncযে ধরনের জন্য একটি নামের।


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

9

আপনি যদি সি ++ 11 ব্যবহার করতে পারেন তবে আপনি কীওয়ার্ড std::functionএবং ব্যবহার করতে চাইতে পারেন using

using FunctionFunc = std::function<void(int arg1, std::string arg2)>;

1
সি ++ ছাড়া usingকীওয়ার্ডটি এর মতো হবে typedef std::function<void(int, std::string)> FunctionFunc;, যদি কেউ সি ++ 11 ছাড়াই ফাংশনগুলির চারপাশে অন্য একটি মোড়ক চায়
টপ-মাস্টার

2
#include <stdio.h>
#include <math.h>

/*
To define a new type name with typedef, follow these steps:
1. Write the statement as if a variable of the desired type were being declared.
2. Where the name of the declared variable would normally appear, substitute the new type name.
3. In front of everything, place the keyword typedef.
*/

// typedef a primitive data type
typedef double distance;

// typedef struct 
typedef struct{
    int x;
    int y;
} point;

//typedef an array 
typedef point points[100]; 

points ps = {0}; // ps is an array of 100 point 

// typedef a function
typedef distance (*distanceFun_p)(point,point) ; // TYPE_DEF distanceFun_p TO BE int (*distanceFun_p)(point,point)

// prototype a function     
distance findDistance(point, point);

int main(int argc, char const *argv[])
{
    // delcare a function pointer 
    distanceFun_p func_p;

    // initialize the function pointer with a function address
    func_p = findDistance;

    // initialize two point variables 
    point p1 = {0,0} , p2 = {1,1};

    // call the function through the pointer
    distance d = func_p(p1,p2);

    printf("the distance is %f\n", d );

    return 0;
}

distance findDistance(point p1, point p2)
{
distance xdiff =  p1.x - p2.x;
distance ydiff =  p1.y - p2.y;

return sqrt( (xdiff * xdiff) + (ydiff * ydiff) );
}

1
কোন পরিস্থিতিতে 'ও' প্রয়োজন? উদাহরণস্বরূপ, 'func_p = & FindDistance' এবং 'func_p = FindDistance' কি সমানভাবে কাজ করে?
ডোনা

1
একটি ফাংশনের নাম একটি পয়েন্টার, সুতরাং আপনার এটির সাথে '&' ব্যবহার করার দরকার নেই। অন্য কথায়, ফাংশন পয়েন্টার বিবেচনা করা হলে '&' isচ্ছিক। তবে, প্রাথমিক তথ্য ধরণের জন্য আপনাকে তার ঠিকানা পেতে '&' ব্যবহার করতে হবে।
আমজাদ

1
এটি সর্বদা অদ্ভুতরূপে আঘাত করেছে যে '&' কখনও optionচ্ছিক হতে পারে। একটি typedef (ক আদিম একটি পয়েন্টার তৈরি করতে ব্যবহার করা হয়, তাহলে অর্থাত typedef (*double) p? '&' ঐচ্ছিক
দনা

আমি মনে করি আপনি typedef double* pএকটি ডাবল পয়েন্টার সংজ্ঞায়িত করতে টাইপ করতে চেয়েছিলেন । আপনি যদি pকোনও প্রাথমিক ভেরিয়েবল থেকে পয়েন্টারটি পপুলেট করতে চান তবে আপনাকে '&' ব্যবহার করতে হবে। একটি পার্শ্ব নোট, আমরা আপনাকে * <পয়েন্টার নাম> একটি পয়েন্টার অবলম্বন করতে। *ফাংশন পয়েন্টার পয়েন্টার (ফাংশন নাম) ডি-রেফারেন্স এবং মেমরি ব্লক যেখানে ফাংশন নির্দেশাবলী অবস্থিত হয় যেতে ব্যবহার করা হয়।
আমজাদ

2

সিনট্যাক্সের সাধারণ ক্ষেত্রে আপনি এএনএসআই সি স্ট্যান্ডার্ড সংযুক্তি এ দেখতে পারেন ।

সেখান থেকে ব্যাকাস-নুর ফর্মে আপনি দেখতে পাচ্ছেন যে typedefটাইপটি রয়েছে storage-class-specifier

প্রকারভেদে declaration-specifiersআপনি দেখতে পাচ্ছেন যে আপনি অনেকগুলি স্পেসিফায়ার প্রকারের মিশ্রণ করতে পারেন, যার ক্রমটি বিবেচনা করে না।

উদাহরণস্বরূপ, এটি বলা ঠিক হয়,

long typedef long a;

প্রকারের aজন্য একটি নাম হিসাবে সংজ্ঞা দেওয়া long long। সুতরাং, সম্পূর্ণরূপে ব্যবহারের টাইপডেফ বুঝতে আপনার কিছু ব্যাকাস-নুর ফর্মের পরামর্শ নেওয়া উচিত যা সিনট্যাক্সটি সংজ্ঞায়িত করে (এএনএসআই সি-র জন্য অনেকগুলি সঠিক ব্যাকরণ রয়েছে, কেবল আইএসও নয়)।

আপনি যখন কোনও ফাংশন টাইপের জন্য কোনও উলেফ সংজ্ঞায়িত করতে টাইপফের ব্যবহার করেন তখন আপনাকে যেখানে উক্ত ফাংশনটির পরিচয়কারী রেখেছেন সেখানে উপন্যাসটি একই স্থানে রাখতে হবে। আপনার ক্ষেত্রে আপনি FunctionFuncকোনও পয়েন্টারটির কাজ করতে ডাক্তারের জন্য একটি উপকরণ হিসাবে প্রকারটি সংজ্ঞায়িত করেছেন যার প্রকারের চেকিং কল এবং অক্ষম কিছুই প্রত্যাশিত is

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