পয়েন্টার বা ঠিকানা মুদ্রণের জন্য সঠিক বিন্যাস নির্দিষ্টকরণকারক?


192

ভেরিয়েবলের ঠিকানা মুদ্রণের জন্য আমার কোন ফর্ম্যাট নির্দিষ্টকরণকারী ব্যবহার করা উচিত? আমি নীচের লট মধ্যে বিভ্রান্ত।

% u - স্বাক্ষরবিহীন পূর্ণসংখ্যা

% x - হেক্সাডেসিমাল মান

% পি - অকার্যকর পয়েন্টার

কোন ঠিকানা মুদ্রণের জন্য সর্বোত্তম বিন্যাসটি হবে?

উত্তর:


239

সহজ উত্তর, ধরে নিলে আপনি বিভিন্ন প্ল্যাটফর্মের মধ্যে বিন্যাসে ভোজন এবং ভিন্নতাগুলিকে কিছু মনে করেন না এটি হ'ল মানক %pস্বীকৃতি।

সি 99 স্ট্যান্ডার্ড (আইএসও / আইইসি 9899: 1999) §7.19.6.1 ¶8 এ বলেছেন:

pযুক্তি একটি পয়েন্টার হতে হবে void। নির্দেশকের মান প্রয়োগকরণ-সংজ্ঞায়িত পদ্ধতিতে মুদ্রণ অক্ষরের ক্রমতে রূপান্তরিত হয়।

(সি 11 - আইএসও / আইইসি 9899: 2011 - তথ্যটি §7.21.6.1 ¶8 এ রয়েছে))

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

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

আপনি যদি বাস্তবায়ন-সংজ্ঞায়িত আচরণের সাথে সন্তুষ্ট না হন %pতবে C99 <inttypes.h>এবং এর uintptr_tপরিবর্তে ব্যবহার করুন:

printf("0x%" PRIXPTR "\n", (uintptr_t)your_pointer);

এটি আপনাকে নিজের অনুসারে উপস্থাপনাটি সূক্ষ্ম-টিউন করতে দেয় to আমি উচ্চতর ক্ষেত্রে হেক্স অঙ্কগুলি বেছে নিয়েছি যাতে সংখ্যাটি সমানভাবে একই উচ্চতা হয় এবং শুরুতে বৈশিষ্ট্যপূর্ণ 0xA1B2CDEFডিপটি এভাবে প্রকাশ পায়, তবে 0xa1b2cdefএটির মতো নয় যে সংখ্যাটি বরাবরও নীচে নেমে যায়। আপনার পছন্দ যদিও, খুব বিস্তৃত সীমাবদ্ধতা মধ্যে। (uintptr_t)ঢালাই unambiguously জিসিসি দ্বারা বাঞ্ছনীয় যখন এটা কম্পাইল সময়ে ফরম্যাট স্ট্রিং পড়তে পারেন। আমি মনে করি অভিনেতাদের অনুরোধ করা ঠিক হবে, যদিও আমি নিশ্চিত যে এমন কিছু লোক আছেন যারা সতর্কতাটিকে উপেক্ষা করবেন এবং বেশিরভাগ সময় এটি থেকে দূরে সরে যাবেন।


কেরেক মন্তব্যগুলিতে জিজ্ঞাসা করেছেন:

আমি স্ট্যান্ডার্ড প্রচার এবং বৈকল্পিক যুক্তি সম্পর্কে কিছুটা বিভ্রান্ত। সমস্ত পয়েন্টার কি শূন্য * স্ট্যান্ডার্ড-প্রচারিত হয়? অন্যথায়, যদি int*বলি, দুটি বাইট, এবং void*4 বাইট ছিল, তবে এটি স্পষ্টতই তর্ক থেকে চারটি বাইট পড়তে ভুল হবে, না?

আমি এই মায়ার মধ্যে ছিলাম যে সি স্ট্যান্ডার্ড বলেছে যে সমস্ত অবজেক্ট পয়েন্টারগুলি অবশ্যই একই আকারের হবে, তাই void *এবং int *বিভিন্ন আকার হতে পারে না। যাইহোক, আমি যা মনে করি C99 স্ট্যান্ডার্ডের প্রাসঙ্গিক বিভাগটি তেমন জোরালো নয় (যদিও আমি এমন কোনও বাস্তবায়ন সম্পর্কে জানিনা যেখানে আমি প্রস্তাবিত সত্যটি সত্য মিথ্যা):

.6.2.5 প্রকার

¶26 অকার্যকর করার জন্য একটি পয়েন্টারের একটি চরিত্রের ধরণের পয়েন্টার হিসাবে একই উপস্থাপনা এবং প্রান্তিককরণের প্রয়োজনীয়তা থাকতে হবে। 39) একইভাবে, সামঞ্জস্যপূর্ণ প্রকারের যোগ্য বা অযোগ্য সংস্করণের পয়েন্টারগুলির একই উপস্থাপনা এবং প্রান্তিককরণের প্রয়োজনীয়তা থাকতে হবে। কাঠামোর ধরণের সমস্ত পয়েন্টারের একে অপরের মতো প্রতিনিধিত্ব এবং প্রান্তিককরণের প্রয়োজনীয়তা থাকতে হবে। ইউনিয়নের ধরণের সমস্ত পয়েন্টারগুলির একে অপরের মতো প্রতিনিধিত্ব এবং প্রান্তিককরণের প্রয়োজনীয়তা থাকতে হবে। অন্যান্য ধরণের পয়েন্টারগুলির একই প্রতিনিধিত্ব বা প্রান্তিককরণের প্রয়োজনীয়তা থাকা দরকার না।

39) একই প্রতিনিধিত্ব এবং প্রান্তিককরণের প্রয়োজনীয়তাগুলি হ'ল ফাংশনগুলিতে আর্গুমেন্ট, ফাংশন থেকে মানগুলি ফেরত দেওয়া এবং ইউনিয়নের সদস্য হিসাবে আদান প্রদানের বোঝা।

(সি 11 §6.2.5, ¶28 বিভাগ এবং পাদটীকা 48 এ ঠিক একই কথা বলেছে।)

সুতরাং, কাঠামোগুলির সমস্ত পয়েন্টার অবশ্যই একে অপরের মতো সমান আকারের হওয়া উচিত এবং একই প্রান্তিককরণের প্রয়োজনীয়তাগুলি অবশ্যই ভাগ করতে হবে, যদিও বিন্দুগুলির বিন্দুগুলির কাঠামোগুলির বিভিন্ন প্রান্তিককরণের প্রয়োজনীয়তা থাকতে পারে। একইভাবে ইউনিয়নগুলির জন্য। ক্যারেক্টার পয়েন্টার এবং অকার্যকর পয়েন্টারগুলির অবশ্যই একই আকার এবং প্রান্তিককরণের প্রয়োজনীয়তা থাকতে হবে। পরিবর্তনের জন্য পয়েন্টারগুলির int(অর্থ unsigned intএবং signed int) একে অপরের মতো একই আকার এবং প্রান্তিককরণের প্রয়োজনীয়তা থাকতে হবে; একইভাবে অন্যান্য ধরণের জন্য। তবে সি স্ট্যান্ডার্ড আনুষ্ঠানিকভাবে এটি বলে না sizeof(int *) == sizeof(void *)। ওহ ভাল, আপনাকে আপনার অনুমানগুলি পরিদর্শন করার জন্য তাই ভাল।

সি স্ট্যান্ডার্ডের অবশ্যই অবজেক্ট পয়েন্টারগুলির মতো একই আকারের ফাংশন পয়েন্টারগুলির প্রয়োজন হয় না। ডস-এর মতো সিস্টেমে বিভিন্ন মেমরির মডেলগুলি না ভাঙার জন্য এটি প্রয়োজনীয় ছিল। সেখানে আপনার কাছে 16-বিট ডেটা পয়েন্টার থাকতে পারে তবে 32-বিট ফাংশন পয়েন্টার বা বিপরীতে। এই কারণেই সি স্ট্যান্ডার্ড আদেশ দেয় না যে ফাংশন পয়েন্টারগুলি বস্তু পয়েন্টারগুলিতে রূপান্তর করতে পারে এবং বিপরীতে।

ভাগ্যক্রমে (প্রোগ্রামারদের জন্য পসিক্স লক্ষ্য করে), পসিক্স লঙ্ঘনের পদক্ষেপ নেয় এবং ফাংশন পয়েন্টার এবং ডেটা পয়েন্টারগুলি একই আকারের নির্দেশ দেয়:

.2.12.3 পয়েন্টার প্রকার

সমস্ত ফাংশন পয়েন্টার প্রকারের শূন্যস্থান বিন্দু টাইপের অনুরূপ প্রতিনিধিত্ব করতে হবে। কোনও ক্রিয়াকলাপের পয়েন্টারের রূপান্তর void *উপস্থাপনাটিকে পরিবর্তন করে না। এ void *জাতীয় রূপান্তরকরণের ফলে প্রাপ্ত মানটি কোনও তথ্য ক্ষতি ছাড়াই একটি সুস্পষ্ট castালাই ব্যবহার করে মূল ফাংশন পয়েন্টার টাইপে ফিরে রূপান্তরিত হতে পারে।

দ্রষ্টব্য: আইএসও সি স্ট্যান্ডার্ডটির এটির প্রয়োজন নেই, তবে এটি পসিক্স কনফারেন্সের জন্য প্রয়োজন।

সুতরাং, দেখে মনে হচ্ছে যে স্পষ্ট void *ক্যাসেটগুলি কোডটিতে সর্বাধিক নির্ভরযোগ্যতার জন্য দৃ strongly়ভাবে পরামর্শ দেওয়া হয় যেমন কোনও বৈকল্পিক ফাংশনে একটি পয়েন্টার পাস করার সময় printf()। পসিক্স সিস্টেমে মুদ্রণের জন্য একটি ফাংশন পয়েন্টারটি একটি শূন্য পয়েন্টারটিতে কাস্ট করা নিরাপদ। অন্যান্য সিস্টেমে এটি করা অপরিহার্যভাবে নিরাপদ নয় এবং void *a ালাই ব্যতীত অন্য পয়েন্টারগুলি পাস করাও প্রয়োজনীয় নয় ।


3
আমি স্ট্যান্ডার্ড প্রচার এবং বৈকল্পিক যুক্তি সম্পর্কে কিছুটা বিভ্রান্ত। সমস্ত পয়েন্টার কি স্ট্যান্ডার্ড-প্রচারিত হয় void*? অন্যথায়, যদি int*বলি, দুটি বাইট, এবং void*4 বাইট ছিল, তবে এটি স্পষ্টতই তর্ক থেকে চারটি বাইট পড়তে ভুল হবে, না?
কেরেক এসবি

নোট করুন যে POSIX এ আপডেট হয়েছে (POSIX 2013) বিভাগটি 2.12.3 সরিয়েছে, বেশিরভাগ প্রয়োজনীয়তার dlsym()পরিবর্তে ফাংশনে সরিয়ে নিয়েছে। একদিন আমি পরিবর্তনটি লিখব ... তবে 'একদিন' 'আজ' নয়।
জোনাথন লেফলার

এই উত্তরটিও কার্য সম্পাদনের পয়েন্টারগুলিতে প্রযোজ্য? তাদের কি রূপান্তর করা যায় void *? হুঁ আমি এখানে আপনার মন্তব্য দেখুন । যেহেতু শুধুমাত্র এক-ওয়াটের রূপান্তর প্রয়োজন (ফাংশন পয়েন্টার টু টু void *), তা কি কাজ করে?
chux -

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

"এবং তথ্য ক্ষতি ছাড়াই ফিরে" মুদ্রণের সাথে প্রাসঙ্গিক নয়। এটা কি সাহায্য করে?
chux - মনিকা পুনরায় ইনস্টল করুন

50

pপয়েন্টার মুদ্রণের জন্য রূপান্তর নির্দিষ্টকরণকারী। এটা ব্যবহার কর.

int a = 42;

printf("%p\n", (void *) &a);

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


2
ক্ষমা, অভিনেতাকে বাদ দেওয়া কেন "অপরিজ্ঞাত আচরণ"? আপনার প্রয়োজনীয় সকলের যদি ঠিকানাটির দরকার হয় তবে এটির মূল্য কী নয় এটি কোন চলকটির ঠিকানা হিসাবে বিবেচনা করে?
ভালডো

9
@ ভ্যালডো কারণ সি এটি বলেছে (সি 99, 7.19.6.1p8) "পি যুক্তিটি শূন্য করার পক্ষে একটি পয়েন্টার হবে।"
ওহাহ

12
@ ভ্যাল্ডো: এটি অবশ্যই অগত্যা নয় যে সমস্ত পয়েন্টার একই আকার / প্রতিনিধিত্বশীল।
ক্যাফে

32

%p"পয়েন্টার" এর জন্য ব্যবহার করুন এবং অন্য কিছু ব্যবহার করবেন না *। আপনাকে কোনও নির্দিষ্ট ধরণের পূর্ণসংখ্যার মতো পয়েন্টারের সাথে আচরণ করার অনুমতি দেওয়া হয়েছে এমন মানদণ্ডের দ্বারা আপনাকে গ্যারান্টিযুক্ত করা যায় না, সুতরাং আপনি অবিচ্ছেদ্য ফর্ম্যাটগুলির সাথে প্রকৃতপক্ষে অপরিবর্তিত আচরণ পাবেন। (উদাহরণস্বরূপ, %uএকটি প্রত্যাশা করে unsigned intতবে তার void*চেয়ে আলাদা আকার বা প্রান্তিককরণের প্রয়োজন থাকলে কী হবে unsigned int?)

*) [জোনাথনের সূক্ষ্ম উত্তর দেখুন!] বিকল্প হিসাবে %p, আপনি সি 99-এ যুক্ত পয়েন্টার-নির্দিষ্ট ম্যাক্রোগুলি ব্যবহার করতে পারেন <inttypes.h>

সমস্ত অবজেক্ট পয়েন্টারগুলি void*স্পষ্টত সি তে রূপান্তরিত হয় , তবে পয়েন্টারটিকে বৈকল্পিক আর্গুমেন্ট হিসাবে পাস করার জন্য আপনাকে এটিকে স্পষ্টতই কাস্ট করতে হয় (যেহেতু স্বেচ্ছাচারিতা অবজেক্ট পয়েন্টারগুলি কেবল রূপান্তরযোগ্য তবে অকার্যকর পয়েন্টারগুলির অনুরূপ নয় ):

printf("x lives at %p.\n", (void*)&x);

2
সমস্ত অবজেক্ট পয়েন্টার এ রূপান্তরযোগ্য void *(যদিও আপনার জন্য printf()প্রযুক্তিগতভাবে স্পষ্ট কাস্টের প্রয়োজন, যেহেতু এটি একটি বৈকল্পিক ফাংশন)। ফাংশন পয়েন্টারগুলি অগত্যা রূপান্তরিত হয় না void *
ক্যাফে

@ ক্যাফ: ওহ, আমি বিচিত্র যুক্তি সম্পর্কে জানতাম না - স্থির! ধন্যবাদ!
কেরেক এসবি

2
স্ট্যান্ডার্ড সি এর প্রয়োজন নেই যে void *ফাংশন পয়েন্টারগুলি বিনা পরিবর্তে ফাংশন পয়েন্টারে রূপান্তরিত হয় এবং ফিরে যেতে পারে; সৌভাগ্যক্রমে, যদিও, পসিক্সের স্পষ্টরূপে এটির প্রয়োজন হয় (এটি লক্ষ্য করা যায় যে এটি স্ট্যান্ডার্ড সি এর অংশ নয়)। সুতরাং, অনুশীলনে, আপনি এটি থেকে পালাতে void (*function)(void)পারেন (রূপান্তর করতে void *এবং ফিরে যেতে void (*function)(void)), তবে কঠোরভাবে এটি সি স্ট্যান্ডার্ড দ্বারা বাধ্যতামূলক নয়।
জোনাথন লেফলার

2
জোনাথন এবং আর .: এটি খুব আকর্ষণীয়, তবে আমি নিশ্চিত যে আমরা এখানে ফাংশন পয়েন্টারগুলি মুদ্রণের চেষ্টা করছি না, তাই সম্ভবত এটি আলোচনা করার পক্ষে এটি ঠিক সঠিক জায়গা নয়। আমি বরং ব্যবহার না করার জন্য আমার দৃistence়তার জন্য এখানে কিছু সমর্থন দেখতে চাই %u!
কেরেক এসবি

2
%uএবং সমস্ত মেশিনে%lu ভুল , কিছু মেশিন নয়। এর স্পেসিফিকেশনটি খুব স্পষ্ট যে প্রকারটি যখন পাস করা হয়েছে তখন ফর্ম্যাট স্পেসিফায়ারের দ্বারা প্রয়োজনীয় ধরণের সাথে মেলে না, আচরণটি অপরিজ্ঞাত। প্রকারের মিলগুলির আকার (যা মেশিনের উপর নির্ভর করে সত্য বা মিথ্যা হতে পারে) অপ্রাসঙ্গিক কিনা; এটি এমন ধরণের যেগুলি অবশ্যই মিলবে এবং তারা কখনই তা মিলবে না। printf
আর .. গীটহাব বন্ধ করুন ICE

9

অন্যান্য (খুব ভাল) উত্তরের বিকল্প হিসাবে আপনি কাস্টিং uintptr_tবা intptr_t(থেকে stdint.h/ inttypes.h) এবং সম্পর্কিত সংখ্যার রূপান্তর স্পেসিফায়ার ব্যবহার করতে পারেন। এটি পয়েন্টারটি কীভাবে ফর্ম্যাট করা যায় তাতে আরও নমনীয়তার সুযোগ দেয়, তবে কঠোরভাবে কোনও প্রয়োগকরণের জন্য এই টাইপিডগুলি সরবরাহ করার প্রয়োজন হয় না।


ফর্ম্যাট স্পেসিফায়ার #include <stdio.h> int main(void) { int p=9; int* m=&s; printf("%u",m); } ব্যবহার %uকরে ভেরিয়েবলের ঠিকানা মুদ্রণ করা কি এই অপরিবর্তিত আচরণ বিবেচনা করবেন ? বেশিরভাগ ক্ষেত্রে ভেরিয়েবলের ঠিকানা ইতিবাচক হয় তাই আমি কি এর %uপরিবর্তে ব্যবহার করতে পারি %p?
ধ্বংসকারী

1
@ পরিচালক: না, %uএটি unsigned intটাইপের জন্য একটি ফর্ম্যাট এবং এতে পয়েন্টার যুক্তির সাহায্যে ব্যবহার করা যায় না printf
আর .. গিটিহাব

-1

আপনি ব্যবহার করতে পারেন %xবা %Xবা %p; তাদের সব ঠিক আছে।

  • আপনি যদি ব্যবহার করেন %xতবে ঠিকানাটি ছোট হাতের হিসাবে দেওয়া হবে, উদাহরণস্বরূপ:a3bfbc4
  • আপনি যদি ব্যবহার করেন %Xতবে ঠিকানাটি বড় হাতের হিসাবে দেওয়া হবে, উদাহরণস্বরূপ:A3BFBC4

এই দুটিই সঠিক।

আপনি যদি ব্যবহার করেন %xবা %Xএটি ঠিকানার জন্য ছয়টি অবস্থান বিবেচনা করছেন এবং আপনি যদি %pএটি ব্যবহার করেন তবে ঠিকানার জন্য আটটি অবস্থান বিবেচনা করা হবে। উদাহরণ স্বরূপ:


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