এই প্রোগ্রাম কিভাবে কাজ করে?


88
#include <stdio.h>

int main() {
    float a = 1234.5f;
    printf("%d\n", a);
    return 0;
}

এটি একটি প্রদর্শিত হয় 0!! কীভাবে সম্ভব? যুক্তি কী?


আমি ইচ্ছাকৃতভাবে একটি করা আছে %dমধ্যে printfআচরণ অধ্যয়ন করতে বিবৃতি printf

উত্তর:


239

এটি কারণ এমনটি %dপ্রত্যাশা করে intতবে আপনি একটি ফ্ল্যাট সরবরাহ করেছেন।

ফ্লোট মুদ্রণ করতে %e/ %f/ ব্যবহার করুন %g


কেন 0 মুদ্রিত হয়: ভাসমান পয়েন্ট নম্বরটি doubleপ্রেরণের আগে রূপান্তরিত হয় printf। সামান্য এরিয়ানে ডাবল প্রতিনিধিত্বের সংখ্যা 1234.5

00 00 00 00  00 4A 93 40

%d32-বিট পূর্ণসংখ্যা গ্রহণ করে, তাই শূন্যটি মুদ্রিত হয়। (পরীক্ষা হিসাবে, আপনি printf("%d, %d\n", 1234.5f);আউটপুট পেতে পারে 0, 1083394560।)


6.5.2.2/7 থেকে প্রিন্টফের প্রোটোটাইপ হিসাবে কেন floatরূপান্তরিত হয়?doubleint printf(const char*, ...)

কোনও ফাংশন প্রোটোটাইপ ঘোষকের মধ্যে উপবৃত্তাকার স্বরলিপিটি সর্বশেষ ঘোষিত প্যারামিটারের পরে যুক্তির ধরণের রূপান্তর বন্ধ করে দেয়। ডিফল্ট আর্গুমেন্ট প্রচারগুলি পেছনের আর্গুমেন্টে সঞ্চালিত হয়।

এবং 6.5.2.2/6 থেকে,

যদি কথিত ফাংশনটিকে বোঝায় এমন অভিব্যক্তিটির কোনও প্রোটোটাইপ অন্তর্ভুক্ত না থাকে তবে প্রতিটি যুক্তিতে পূর্ণসংখ্যা প্রচার হয় এবং প্রকারের যুক্তিগুলিতে floatপ্রচার হয় doubleএই বলা হয় ডিফল্ট যুক্তি প্রচার

(এটি জানতে পেরে ধন্যবাদ অলোক।)


4
+1 সেরা উত্তর। এটি "স্ট্যান্ডার্ড প্রযুক্তিগতভাবে সঠিক" কেন এবং "আপনার সম্ভাব্য প্রয়োগ" কেন উভয়ই উত্তর দেয়।
ক্রিস লুৎজ

12
আমি বিশ্বাস করি যে আপনি 12 জন ব্যক্তিদের মধ্যে কেবলমাত্র তিনিই ছিলেন যে উত্তরটি তিনি খুঁজছিলেন তার উত্তর সরবরাহ করেছিলেন।
গাবে

11
কারণ printfএকটি বৈকল্পিক ফাংশন, এবং মানটি বলে যে ভেরিয়াদিক ফাংশনগুলির জন্য, একটি পাস floatকরার doubleআগে রূপান্তরিত হয় ।
অলোক সিংহল

8
সি স্ট্যান্ডার্ড থেকে: "একটি ফাংশন প্রোটোটাইপ ডিক্লেয়ারারে এলিপসিস স্বরলিপিটি সর্বশেষ ঘোষিত প্যারামিটারের পরে আর্গুমেন্টের ধরণের রূপান্তর বন্ধ করে দেয় argument এবং "... এবং ধরণের ফ্লোট রয়েছে এমন যুক্তিগুলিকে দ্বিগুণ হিসাবে প্রচার করা হয় These এগুলিকে ডিফল্ট আর্গুমেন্ট প্রচার বলে " "
অলোক সিংহল

4
ভুল বিন্যাস সুনির্দিষ্টভাবে উল্লেখ করা ব্যবহার printf()পূজা অনির্ধারিত আচরণ
প্রসূন সৌরভ

45

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

উদাহরণস্বরূপ, আমার ম্যাকবুকে আমি 1606416304আপনার প্রোগ্রামের সাথে আউটপুট পাই ।

এটি বলার পরে, আপনি যখন floatকোনও বৈকল্পিক ফাংশনে floatএকটি পাস করেন , এটি একটি হিসাবে পাস হয় double। সুতরাং, আপনার প্রোগ্রামটি aএকটি হিসাবে ঘোষণার সমতুল্য double

এটির বাইটগুলি পরীক্ষা doubleকরতে, আপনি এখানে একটি সাম্প্রতিক প্রশ্নের উত্তরটি দেখতে পারেন O

আসুন এটি করা যাক:

#include <stdio.h>

int main(void)
{
    double a = 1234.5f;
    unsigned char *p = (unsigned char *)&a;
    size_t i;

    printf("size of double: %zu, int: %zu\n", sizeof(double), sizeof(int));
    for (i=0; i < sizeof a; ++i)
        printf("%02x ", p[i]);
    putchar('\n');
    return 0;
}

আমি যখন উপরের প্রোগ্রামটি চালাই, তখন আমি পাই:

size of double: 8, int: 4
00 00 00 00 00 4a 93 40 

সুতরাং, প্রথম চারটি বাইটগুলি double0 এ পরিণত হয়েছে , এটিই সম্ভবত আপনি 0আপনার printfকলটির আউটপুট হিসাবে পেয়েছেন ।

আরও আকর্ষণীয় ফলাফলের জন্য, আমরা প্রোগ্রামটি কিছুটা পরিবর্তন করতে পারি:

#include <stdio.h>

int main(void)
{
    double a = 1234.5f;
    int b = 42;

    printf("%d %d\n", a, b);
    return 0;
}

আমি যখন আমার ম্যাকবুকে উপরের প্রোগ্রামটি চালাই, তখন আমি পাই:

42 1606416384

একটি লিনাক্স মেশিনে একই প্রোগ্রাম সহ, আমি পাই:

0 1083394560

আপনি কেন পিছনের দিকে প্রিন্ট করলেন? আমি কিছু অনুপস্থিত করছি? বি যদি কোনও আন্তঃ = 42 হয় এবং '% d' হয় পূর্ণসংখ্যা বিন্যাস, কেন এটি দ্বিতীয় মুদ্রিত মান নয়, কেননা এটি প্রিন্টএফ আর্গুমেন্টে দ্বিতীয় পরিবর্তনশীল? এটি কি টাইপো?
ক্যাটাস্টিক ভয়েজ

সম্ভবত কারণ intআর্গুমেন্টগুলি বিভিন্ন রেজিস্টারে doubleআর্গুমেন্টের চেয়ে পাস হয় । printfসাথে যুক্তিটি %dগ্রহণ করে intযেটি 42 এবং দ্বিতীয়টি %dসম্ভবত আবর্জনা মুদ্রণ করে যেহেতু দ্বিতীয় intযুক্তি ছিল না ।
অলোক সিংহল

20

%dসুনির্দিষ্টভাবে উল্লেখ করা বলেprintf একটি পূর্ণসংখ্যা প্রত্যাশিত। সুতরাং ভাসমানের প্রথম চার (বা দুটি, প্ল্যাটফর্মের উপর নির্ভর করে) বাইটগুলি একটি পূর্ণসংখ্যা হিসাবে ব্যাখ্যা করা হয়। সেগুলি যদি শূন্য হয় তবে একটি শূন্য মুদ্রিত হয়

1234.5 এর বাইনারি উপস্থাপনাটি এরকম

1.00110100101 * 2^10 (exponent is decimal ...)

সি সংকলক সহ যা floatআইইইই 7575৫ ডাবল মান হিসাবে বাস্তবে প্রতিনিধিত্ব করে , বাইটগুলি হবে (যদি আমি কোনও ভুল না করি)

01000000 10010011 01001010 00000000 00000000 00000000 00000000 00000000

সামান্য সমাপ্তি (যেমন সর্বনিম্ন তাৎপর্যপূর্ণ বাইট প্রথম আসবে) সহ একটি ইন্টেল (x86) সিস্টেমে এই বাইট ক্রমটি বিপরীত হয় যাতে প্রথম চারটি বাইট শূন্য হয়। printfঅর্থাত , কী ছাপে ...

আইইইই 7575৫ অনুযায়ী ভাসমান পয়েন্ট উপস্থাপনার জন্য এই উইকিপিডিয়া নিবন্ধটি দেখুন ।


7

এটি বাইনারি মধ্যে একটি ভাসমান প্রতিনিধিত্ব কারণ। একটি পূর্ণসংখ্যার রূপান্তর এটি 0 দিয়ে ছেড়ে যায়।


4
আপনি কেবল তিনিই চেয়েছিলেন যা তিনি বুঝতে চেয়েছিলেন be অবশ্যই আমি নিজের ভুল না করি।
মিজিপজোর

আমি সম্মত হই যে উত্তরটি ভুল এবং অসম্পূর্ণ, তবে ভুল নয়।
শাইহি

7

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


5

কারণটি হ'ল printf()একটি দুর্দান্ত বোবা ফাংশন। এটি মোটেই প্রকার পরীক্ষা করে না। যদি আপনি বলেন প্রথম যুক্তিটি একটি int(এবং এটিই আপনি যা বলছেন %d) তবে এটি আপনাকে বিশ্বাস করে এবং এটির জন্য প্রয়োজনীয় বাইটগুলি লাগে int। এই ক্ষেত্রে, আপনার মেশিনটি চার-বাইট intএবং আট-বাইট ব্যবহার করে double(এটি floatএকটি doubleঅভ্যন্তরে রূপান্তরিত হয় printf()), প্রথম চারটি বাইট aকেবল শূন্য হবে এবং এটি মুদ্রিত হবে।


3

এটি স্বয়ংক্রিয়ভাবে ভাসমানটিকে পূর্ণসংখ্যায় রূপান্তর করবে না। কারণ উভয়ের স্টোরেজের বিভিন্ন ফর্ম্যাট রয়েছে। সুতরাং আপনি যদি রূপান্তর করতে চান, (int) টাইপকাস্টিং ব্যবহার করুন।

#include <stdio.h>

int main() {
    float a = 1234.5f;
    printf("%d\n", (int)a);
    return 0;
}

2

আপনি যেহেতু এটি সি ++ এর সাথেও ট্যাগ করেছেন তাই এই কোডটি আপনার প্রত্যাশা অনুযায়ী রূপান্তরটি করে:

#include <iostream.h>

int main() {
    float a = 1234.5f;
    std::cout << a << " " << (int)a << "\n";
    return 0;
}

আউটপুট:

1234.5 1234

1

%d দশমিক হয়

%f ভাসা হয়

এখানে আরও দেখুন ।

আপনি 0 পেয়ে যাচ্ছেন কারণ ভাসমান এবং পূর্ণসংখ্যা পৃথকভাবে উপস্থাপিত হয়।


1

আপনার কেবল প্রাসঙ্গিক ডেটা প্রকারের (যথাযথ, ভাসা, স্ট্রিং ইত্যাদি) সাথে উপযুক্ত ফর্ম্যাট স্পেসিফায়ার (% d,% f,% s, ইত্যাদি) ব্যবহার করতে হবে।


প্রশ্নটি কীভাবে এটি ঠিক করা যায় তা নয় তবে এটি কেন এটি কাজ করে।
ya23


0

আরে এটি কিছু মুদ্রণ করতে হয়েছিল তাই এটি একটি 0 মুদ্রিত। সি 0 এ মনে রাখবেন সব কিছু!


4
এটা কিভাবে? সি তে সব কিছুর মতো জিনিস নেই।
ভ্লাদ

যদি এক্স কিছু হয়, তবে! x == 0 :)
চুঙ্কিগুয়ে

যদি (iGot == "সবকিছু") "সবকিছু" মুদ্রণ করে ; অন্যথায় "কিছুই না" মুদ্রণ করুন;
নিক

0

এটি কোনও পূর্ণসংখ্যা নয়। ব্যবহার করার চেষ্টা করুন %f


আমি অনুমান করি যে প্রশ্নটি হ'ল কেন এটি কেবল ভাসমানটিকে ইনট এবং "1234" প্রদর্শন করে না?
Björn Pollex

গ এর আশা করবেন না যে আপনাকে এমন কিছু করতে দেওয়া হবে যা কোনও যৌক্তিক ধারণা দেয় না। হ্যাঁ অনেকগুলি ভাষা আপনার প্রত্যাশা করতে পারে 1234 দেবে এবং সম্ভবত সি এর কিছু বাস্তবায়নও আমি এই আচরণটি সংজ্ঞায়িত বলে মনে করব না। সি আপনাকে এটিকে পিতামাতার মতো ঝুলতে দেয় যা আপনাকে এর নরকের জন্য ক্র্যাক চেষ্টা করতে দেয়।
পুনরায় চালু করুন

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