সংকলন-সময়ে আমি কীভাবে একটি # সংজ্ঞাটির মান দেখাব?


123

আমার কোড বুস্টের কোন সংস্করণটি এটি ব্যবহার করছে বলে মনে করে তা বের করার চেষ্টা করছি। আমি এরকম কিছু করতে চাই:

#error BOOST_VERSION

তবে প্রিপ্রসেসর BOOST_VERSION প্রসারিত করে না।

আমি জানি যে আমি প্রোগ্রাম থেকে রান-টাইমে এটি মুদ্রণ করতে পারি এবং আমি জানি আমি উত্তরটি খুঁজতে প্রিপ্রসেসরের আউটপুটটি দেখতে পারি। আমার মনে হচ্ছে সংকলনের সময় এটি করার একটি উপায় থাকা কার্যকর হতে পারে।


7
ভবিষ্যতের দর্শনার্থীদের জন্য ... ক্রিস ব্যারি শেষে সাধারণ সমাধান সরবরাহ করে (বুস্ট নির্দিষ্ট স্টাফ থেকে বঞ্চিত)।
jww

উত্তর:


117

আমি জানি যে এটি মূল ক্যোয়ারির পরে দীর্ঘ সময়, তবে এটি এখনও কার্যকর হতে পারে।

এটি স্ট্রিংফাই অপারেটর "#" ব্যবহার করে জিসিসিতে করা যেতে পারে তবে এর জন্য দুটি পর্যায়ে প্রয়োজন।

#define XSTR(x) STR(x)
#define STR(x) #x

এরপরে ম্যাক্রোর মানটি প্রদর্শিত হবে:

#pragma message "The value of ABC: " XSTR(ABC)

দেখুন: জিসিসি অনলাইন ডকুমেন্টেশনে স্ট্রিংফিকেশন।

কিভাবে এটা কাজ করে:

প্রিপ্রোসেসর উদ্ধৃত স্ট্রিংগুলি বোঝে এবং এগুলি সাধারণ পাঠ্য থেকে পৃথকভাবে পরিচালনা করে। স্ট্রিং কনটেনটেশন এই বিশেষ চিকিত্সার একটি উদাহরণ। বার্তা প্রাগমাতে একটি যুক্তি প্রয়োজন যা উদ্ধৃত স্ট্রিং। যখন আর্গুমেন্টে একের অধিক উপাদান থাকে তখন সেগুলি অবশ্যই স্ট্রিং হওয়া উচিত যাতে স্ট্রিং কনক্যাটেনশন প্রয়োগ করা যায়। প্রিপ্রোসেসর কখনই ধরে নিতে পারে না যে একটি অব্যক্ত স্ট্রিংটি যেমন উদ্ধৃত হয়েছে তেমন আচরণ করা উচিত। যদি এটি তখন করে:

#define ABC 123
int n = ABC;

সংকলন না।

এখন বিবেচনা করুন:

#define ABC abc
#pragma message "The value of ABC is: " ABC

যা সমান

#pragma message "The value of ABC is: " abc

এটি প্রিপ্রোসেসর সতর্কতা সৃষ্টি করে কারণ পূর্ববর্তী স্ট্রিং সহ আব্যাক (অব্যক্ত) সংমিশ্রণ করা যায় না।

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

#define STR(x) #x
char *s1 = "abc";
char *s2 = STR(abc);

s1 এবং s2 এ অভিন্ন মান নির্ধারণ করবে। আপনি যদি জিসিসি-ই চালান তবে আপনি এটি আউটপুটে দেখতে পাবেন। সম্ভবত এসআরটি এনকোটির মতো আরও কিছু নাম দেওয়া হবে।

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


3
কেন আমি এর জন্য দুটি পর্যায়ে প্রয়োজন তা জানতে আগ্রহী
ভিনসেন্ট ফোরমন্ড

4
@ ভিনসেন্টফরমন্ড এক্সএসআরটি স্টেজ ছাড়া ম্যাক্রো প্রসারিত হয় না। সুতরাং আপনি যদি # এবিসি 42 STR n স্ট্রিট (এবিসি) সংজ্ঞায়িত করেন তবে আপনি "এবিসি" পেয়ে যাবেন। দেখুন gcc.gnu.org/onlinedocs/cpp/Stringification.html
rob05c

এটি এক্সকোড 8 এর সাথে দুর্দান্ত কাজ করে, যেমন এবিসি এর সাথে প্রতিস্থাপন __IPHONE_9_3
ফেনারল

জিসিসির পরিভাষা পরিবর্তিত হয়েছে বলে মনে হয় এবং এর সাথে ইউআরএল, যা এখন https://gcc.gnu.org/onlinesocs/cpp/Stringizing.html#
ক্রিস ব্যারি

119

BOOST_PP_STRINGIZE সি ++ এর জন্য দুর্দান্ত সমাধান বলে মনে হচ্ছে তবে নিয়মিত সি-তে নয়

জিএনইউ সিপিপির জন্য আমার সমাধানটি এখানে:

/* Some test definition here */
#define DEFINED_BUT_NO_VALUE
#define DEFINED_INT 3
#define DEFINED_STR "ABC"

/* definition to expand macro then apply to pragma message */
#define VALUE_TO_STRING(x) #x
#define VALUE(x) VALUE_TO_STRING(x)
#define VAR_NAME_VALUE(var) #var "="  VALUE(var)

/* Some example here */
#pragma message(VAR_NAME_VALUE(NOT_DEFINED))
#pragma message(VAR_NAME_VALUE(DEFINED_BUT_NO_VALUE))
#pragma message(VAR_NAME_VALUE(DEFINED_INT))
#pragma message(VAR_NAME_VALUE(DEFINED_STR))

উপরের সংজ্ঞাগুলির ফলাফল:

test.c:10:9: note: #pragma message: NOT_DEFINED=NOT_DEFINED
test.c:11:9: note: #pragma message: DEFINED_BUT_NO_VALUE=
test.c:12:9: note: #pragma message: DEFINED_INT=3
test.c:13:9: note: #pragma message: DEFINED_STR="ABC"

জন্য "interger হিসাবে সংজ্ঞায়িত করা" , "STRING হিসাবে সংজ্ঞায়িত করা" , এবং "সংজ্ঞায়িত কিন্তু কোন মান" ভেরিয়েবল, তারা শুধু জরিমানা কাজ করি। কেবলমাত্র "সংজ্ঞায়িত" ভেরিয়েবলের জন্য, তারা আসল ভেরিয়েবল নামের মতোই প্রদর্শিত হয়। আপনার এটি ব্যবহার করতে হবে - অথবা হতে পারে যে কেউ আরও ভাল সমাধান সরবরাহ করতে পারেন।


চমৎকার! এআরএম আরভিসিটির কোনও অভিজ্ঞতা? মনে হচ্ছে এটির কোনও "স্ট্রিংফিকেশন" বৈশিষ্ট্য নেই জিসিসি ইনফেনসিটার.আরএম.com
help

2
দুর্দান্ত সমাধান। যাইহোক, যদি আমি একটি সংকলন-সময় গণনা মান, উদাহরণস্বরূপ একটি জটিল কাঠামোর আকার প্রদর্শন করতে চান তবে এটি করা যেতে পারে? এই উত্তরে প্রস্তাবিত পদ্ধতিটি অপারেটরের মূল্যায়ন DEFINED_INT=(sizeof(MY_STRUCT))না করেই উত্পন্ন বলে মনে sizeofহচ্ছে।
কার্ল

(মন্তব্য সংযোজন: অপ্রত্যাশিত নয়, যেহেতু এটি প্রসেসরের চেয়ে সংকলক যা মূল্যায়ন করবে sizeof, তবে এটি অর্জনের কোনও চতুর উপায় আছে কিনা তা এখনও
কার্ল

@ এক্সডান ভাল সমাধান, দুর্ভাগ্যক্রমে এর মতো জিনিসগুলি পূরণ করা যায় না#define masks {0xff, 0xaf, 0x0f}
সাইমন ব্যাগলি

59

আপনি যদি ভিজ্যুয়াল সি ++ ব্যবহার করেন তবে আপনি ব্যবহার করতে পারেন #pragma message:

#include <boost/preprocessor/stringize.hpp>
#pragma message("BOOST_VERSION=" BOOST_PP_STRINGIZE(BOOST_VERSION))

সম্পাদনা করুন: লিঙ্কের জন্য ধন্যবাদ LB

স্পষ্টতই, জিসিসির সমতুল্য (পরীক্ষিত নয়):

#pragma message "BOOST_VERSION=" BOOST_PP_STRINGIZE(BOOST_VERSION)

5
একে ডায়াগনস্টিক প্রাগমাস
এলবি 40

4
আপনি যদি সংজ্ঞাটিBOOST_PP_STRINGIZE সুন্দর এবং সংক্ষিপ্ত এবং অনুলিপি / পেস্টেবলের সাথে অন্তর্ভুক্ত করেন তবে দুর্দান্ত হবে।
টিম্ম্ম্ম


14

যতদূর আমি জানি '# এরর' কেবল স্ট্রিং মুদ্রণ করবে, বাস্তবে আপনার উদ্ধৃতি ব্যবহার করার দরকার নেই

আপনি কি "BOOST_VERSION" ব্যবহার করে উদ্দেশ্যমূলকভাবে ভুল কোড লেখার চেষ্টা করেছেন? সম্ভবত "ব্লাহ [BOOST_VERSION] = foo;" এর মতো কিছু আপনাকে "স্ট্রিং আক্ষরিক 1.2.1.1 এর অ্যারে ঠিকানা হিসাবে ব্যবহার করা যাবে না" এর মতো কিছু বলবে। এটি কোনও সুন্দর ত্রুটির বার্তা হবে না তবে কমপক্ষে এটি আপনাকে প্রাসঙ্গিক মানটি প্রদর্শন করবে। আপনি কোনও সংকলন ত্রুটি খুঁজে না পাওয়া পর্যন্ত আপনি চারপাশে খেলতে পারবেন যা আপনাকে মানটি বলে না।


এটি কার্যকর হয়নি, যেহেতু BOOST_VERSION একটি পূর্ণসংখ্যা, তবে আমি এটি এই বিবৃতি দিয়ে দেখতে পেলাম: জিসিসি std::vector<BOOST_VERSION>;৪.৪.১ এ। ধন্যবাদ!
জিম হুনজিকার

দ্রষ্টব্য যে ভিজ্যুয়াল সি ++ এর সাথে আপনাকে বোজন রজনিকের উত্তরটি ব্যবহার করতে হবে।
রাফাল সেন্ট-পিয়ের

আমি এটি কাজে লাগানোর চেষ্টা করেছি, তবে জিসিসি আমাকে যে ত্রুটি বার্তা দিয়েছে তা দুঃখজনকভাবে বর্ণনাতীত ছিল। তবে এটি উল্লেখ করার জন্য +1 করুন।
ক্রিস লুটজ

14

উত্সাহ ছাড়া:

  1. আবার একই ম্যাক্রো সংজ্ঞায়িত করুন এবং সংকলক হিমসেলফ সতর্কতা দেবে।

  2. সতর্কতা থেকে আপনি পূর্বের সংজ্ঞাটির অবস্থান দেখতে পারেন।

  3. vi পূর্ববর্তী সংজ্ঞা ফাইল।

ambarish@axiom:~/cpp$ g++ shiftOper.cpp
shiftOper.cpp:7:1: warning: "LINUX_VERSION_CODE" redefined
shiftOper.cpp:6:1: warning: this is the location of the previous definition

#define LINUX_VERSION_CODE 265216
#define LINUX_VERSION_CODE 666

int main ()
{

}

এই এক সহজ এবং সোজা।
টিএমএক্স

1
নিজেই : সংকলকদের কোনও লিঙ্গ নেই
স্কাই

এটি পূর্বনির্ধারিত ম্যাক্রোগুলির সাথে কাজ করে না __cplusplus
ম্যানুয়েলএটওয়ার্ক

10

মাইক্রোসফ্ট সি / সি ++ এ _CRT_STRINGIZE()আপনি অন্তরগুলি মুদ্রণের জন্য ব্যবহার করতে পারেন । আমার অনেকগুলি stdafx.hফাইলে এর কিছু সংমিশ্রণ রয়েছে:

#pragma message("_MSC_VER      is " _CRT_STRINGIZE(_MSC_VER))
#pragma message("_MFC_VER      is " _CRT_STRINGIZE(_MFC_VER))
#pragma message("_ATL_VER      is " _CRT_STRINGIZE(_ATL_VER))
#pragma message("WINVER        is " _CRT_STRINGIZE(WINVER))
#pragma message("_WIN32_WINNT  is " _CRT_STRINGIZE(_WIN32_WINNT))
#pragma message("_WIN32_IE     is " _CRT_STRINGIZE(_WIN32_IE))
#pragma message("NTDDI_VERSION is " _CRT_STRINGIZE(NTDDI_VERSION)) 

এবং এরকম কিছু আউটপুট দেয়:

_MSC_VER      is 1915
_MFC_VER      is 0x0E00
_ATL_VER      is 0x0E00
WINVER        is 0x0600
_WIN32_WINNT  is 0x0600
_WIN32_IE     is 0x0700
NTDDI_VERSION is 0x06000000

5
#define a <::BOOST_VERSION>
#include a
MSVC2015 : মারাত্মক ত্রুটি C1083: ফাইল অন্তর্ভুক্ত খুলতে পারে না: ':: 106200': এই জাতীয় কোনও ফাইল বা ডিরেক্টরি নেই

preprocess to fileসক্ষম থাকলেও কাজ করে , এমনকি অবৈধ টোকেন উপস্থিত থাকলেও:

#define a <::'*/`#>
#include a
MSVC2015 : মারাত্মক ত্রুটি C1083: ফাইলটি অন্তর্ভুক্ত করতে পারে না: '::' * / `# ': এ জাতীয় কোনও ফাইল বা ডিরেক্টরি
GCC4.x : সতর্কতা: অনুপস্থিত' অক্ষর [-Winuthor-pp-token]
# নির্ধারণ করুন <:: '* / `#>

আমার শুধু বলে Build error: #include expects "FILENAME" or <FILENAME>। দীর্ঘশ্বাস.
এন্ডোলিথ

@endolith কি সংকলক এবং সংস্করণ?
অ্যান্ড্রি

ডিপি 8051 কেয়েল 9.51 :)
এন্ডোলিথ

@endolith মনে এই কম্পাইলার খুব উপর preprocessing সীমাবদ্ধ: keil.com/support/man/docs/c51/c51_pp_directives.htm , কিন্তু খনি উপর পাশ এটা প্রায় কাজ আশানুরূপ, আমি শুধু মত অবৈধ অক্ষর কিছু সরিয়েছি ':*** WARNING C318 IN LINE 2 OF test.c: can't open file '::*/`'
Andry

আপনাকে ধন্যবাদ, এটি আমাকে বাঁচিয়েছিল কারণ আমি যে সংকলকটি ব্যবহার করছিলাম তার মধ্যে প্রাগমা বার্তা স্টাফ প্রয়োগ করা হয়নি।
কোডমনেকি

3

আপনি উত্স ফাইলটি প্রিপ্রসেসও করতে পারেন এবং প্রিপ্রোসেসর মানটি কী মূল্যায়ন করে তা দেখতে পারেন।


2

আপনি খুঁজছেন

#if BOOST_VERSION != "1.2"
#error "Bad version"
#endif

BOOST_VERSION যদি স্ট্রিং হয় তবে এটি দুর্দান্ত নয়, যেমন আমি ধরে নিয়েছি তবে বড়, নাবালক এবং সংশোধন সংখ্যার জন্য পৃথক সংখ্যার সংজ্ঞাও থাকতে পারে।


আমি মনে করি সাবমিটার একটি নির্দিষ্ট মান প্রয়োগ করতে চান না (কেবল) তারা বর্তমান মানটি কী তা দেখতে চায় want
কীসারসোজ

এটিই আমার পক্ষে কাজ করে। আমি পরিবর্তন করতে পারেন#if VARIABLE == 123 ফ্লাইতে বিবৃতিটি এবং সিনট্যাক্স হাইলাইট করে আমাকে বলে যে এটি আমার মনে হয় এটির মান কি না ...
এন্ডোলিথ

2

প্রিপ্রসেসরের আউটপুটটি দেখানো আপনার কাছে যে উত্তরটি চেয়েছে তার নিকটতম জিনিস।

আমি জানি আপনি এটি (এবং অন্যান্য উপায়ে) বাদ দিয়েছেন তবে কেন তা নিশ্চিত নই। সমাধানের জন্য আপনার একটি নির্দিষ্ট যথেষ্ট সমস্যা রয়েছে তবে কোনও "স্বাভাবিক" পদ্ধতি আপনার পক্ষে কেন ভাল কাজ করে না তা আপনি ব্যাখ্যা করেননি।


এটি সম্ভবত সাধারণ সমস্যার সঠিক উত্তর।
jww

1

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


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

আপনার আসল প্রোগ্রাম থেকে এটি মুদ্রণ করুন। যদি গ্রাফিকাল হয় তবে এটি "সম্পর্কে" ডায়ালগটিতে রাখুন। যদি কমান্ড-লাইন থাকে তবে এটিকে একটি বিকল্প করুন (--version এর অংশ, সম্ভবত)। যদি ডেমন হয় তবে এটি একটি লগ ফাইলে লিখুন। যদি এম্বেড থাকে তবে অন্য কোনও উপায় সন্ধান করুন।
দিভেগেক

@ সুইডেন - ওপি এটি সংকলন সময়ে চেয়েছিল, রানটাইমের সময় নয়।
ক্রিস লুটজ

এটি ক্রস-সংকলক ভিত্তিক বিল্ডগুলিও ভেঙে যেতে পারে
ক্রেগ রিঞ্জার


1

আপনি ম্যাক্রো কীভাবে ব্যবহার করছেন সে সম্পর্কে বুস্ট ডকুমেন্টেশনটিও একবার দেখুন:

Http://www.boost.org/doc/libs/1_37_0/libs/config/doc/html/boost_config/oost_macro_references.html#boost_config.boost_macro_references.boost_helper_macrosBOOST_VERSION থেকে রেফারেন্স হিসাবে :

বর্ণনা যেমন যে XXYYZZ বিন্যাসে বুস্ট সংস্করণ সংখ্যা: (BOOST_VERSION % 100)উপ-ছোটখাট সংস্করণ, গৌণ সংস্করণে, এবং প্রধান সংস্করণ।((BOOST_VERSION / 100) % 1000)(BOOST_VERSION / 100000)


0

# অররের পরিবর্তে, ম্যাক্রোটি ব্যবহৃত হওয়ার ঠিক আগে পুনরায় সংজ্ঞায়িত করার চেষ্টা করুন। সংকলন ব্যর্থ হবে এবং সংকলক ম্যাক্রোর জন্য প্রযোজ্য এমনটি বর্তমান মান প্রদান করবে thinks

# ডিফাইন BOOST_VERSION বেলা

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