দীর্ঘ মেশিন কেন কিছু মেশিনে 12 বাইট নেয়?


26

আমার মেশিনে এই কোডটি সংকলনের পরে আমি অদ্ভুত কিছু লক্ষ্য করেছি:

#include <stdio.h>

int main()
{
    printf("Hello, World!\n");

    int a,b,c,d;

    int e,f,g;

    long int h;

    printf("The addresses are:\n %0x \n %0x \n %0x \n %0x \n %0x \n %0x \n %0x \n %0x",
        &a,&b,&c,&d,&e,&f,&g,&h);

    return 0;
}

ফলাফল নিম্নলিখিত। লক্ষ্য করুন যে প্রতিটি পূর্ববর্তী ঠিকানার মধ্যে একটি 4-বাইট পার্থক্য রয়েছে। তবে শেষ প্রান্ত এবং দীর্ঘ অন্তরের মধ্যে একটি 12-বাইট পার্থক্য রয়েছে:

 Hello, World!
 The addresses are:

 da54dcac 
 da54dca8 
 da54dca4 
 da54dca0 
 da54dc9c 
 da54dc98 
 da54dc94 
 da54dc88

3
উত্স কোড intপরে অন্য রাখুন h। সংকলকটি এর আগে ফাঁকে রেখে দিতে পারে h
ctrl-alt-delor

32
আকার নির্ধারণের জন্য মেমরি ঠিকানার মধ্যে পার্থক্যটি ব্যবহার করবেন না। তার জন্য একটি sizeofফাংশন আছে । printf("size: %d ", sizeof(long));
ক্রিস স্নাইডার

10
আপনি কেবলমাত্র আপনার ঠিকানাগুলির সাথে কম 4 বাইট মুদ্রণ করছেন %x। আপনার জন্য ভাগ্যবান, এটি আপনার প্ল্যাটফর্মে সঠিকভাবে কাজ করার জন্য প্রত্যাশিত ফর্ম্যাট স্ট্রিং সহ unsigned intপয়েন্টার আরোগুলি পেরিয়ে যায় তবে পয়েন্টার এবং ইনটগুলি অনেক এবিআইতে বিভিন্ন আকারের হয়। %pপোর্টেবল কোডে পয়েন্টারগুলি মুদ্রণ করতে ব্যবহার করুন । (এমন কোনও সিস্টেমের কল্পনা করা সহজ যেখানে আপনার কোডটি 8
পিটার


2
@ লু ভুল তথ্য ছড়াবেন না কোনও শালীন সংকলক সিটিতে ভেরিয়েবলগুলি ঘোষিত হয় সেটির বিষয়ে চিন্তা করে না যদি এটি যত্নশীল হয় তবে এটি আপনার বর্ণনার উপায়ে এটি করার কারণ নেই।
gnasher729

উত্তর:


81

এটি 12 বাইট নেয় নি, এটি কেবল 8 নিয়েছে However তবে, এই প্ল্যাটফর্মে 8 বাইট লং ইন্টের জন্য ডিফল্ট প্রান্তিককরণটি 8 বাইট। যেমনটি, সংকলকটি 8 টি দ্বারা বিভাজ্য এমন ঠিকানায় লম্বা ইনট্রে স্থানান্তরিত করার দরকার ছিল "স্পষ্টত" ঠিকানা, da54dc8c, 8 দ্বারা বিভাজ্য নয় তাই 12 বাইট ফাঁক।

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

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


3
পার্থক্য, ফাঁক নয়।
উত্সাহক

10
"পুনঃ-অর্ডারিং ভেরিয়েবলগুলি সহ"। সংকলক যদি সিদ্ধান্ত নেয় যে আপনি একই সাথে দুটি ভেরিয়েবল ব্যবহার করবেন না, তবে আংশিকভাবে ওভারল্যাপ করা বা সেগুলি সম্পূর্ণরূপে ওভারলে ফ্রি করা বিনামূল্যে ...
রজার লিপসক্বে

8
বা প্রকৃতপক্ষে, তাদের স্ট্যাকের পরিবর্তে নিবন্ধগুলিতে রাখুন।
মনিকা মনিকা বন্ধ করুন

11
@ ওরেঞ্জডগ আমি ঠিক মনে করি না যে যদি ঠিকানার ক্ষেত্রে এই ঠিকানাটি নেওয়া হয় তবে সাধারণভাবে আপনি অবশ্যই সঠিক।
অ্যালেক্স

5
@ অ্যালেক্স: ঠিকানা নেওয়ার সময় আপনি মেমরির সাথে নিবন্ধগুলি এবং নিবন্ধগুলি পেতে পারেন। ঠিকানাটি গ্রহণের অর্থ এটি এটিকে একটি মেমরি অবস্থান দিতে হবে, তবে এর অর্থ এটি আসলে ব্যবহার করতে হবে না। যদি আপনি ঠিকানাটি নেন, এটিতে 3 নির্ধারণ করুন এবং এটি অন্য ফাংশনে পাস করুন, এটি কেবল আরডিআইতে 3 লিখতে এবং কল করতে পারে, মেমোরিতে কখনই এটি লিখবেন না। কখনও কখনও কখনও কোনও ডিবাগারে অবাক করা।
ঝ্যান

9

এর কারণ আপনার সংকলকটি ভেরিয়েবলের মধ্যে অতিরিক্ত প্যাড তৈরি করছে যাতে তারা মেমরিতে সঠিকভাবে প্রান্তিক হয় তা নিশ্চিত করে।

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


ব্যাখ্যা করার জন্য ধন্যবাদ. যে আকারগুলির একাধিক আকারের ভেরিয়েবলগুলি অ্যাক্সেস করা আরও কার্যকরী সেগুলি সম্পর্কে আপনি কি আমাকে কিছু উপকরণ নির্দেশ করতে পারেন? আমি জানতে চাই কেন এমন হচ্ছে?
yoyo_fun

4
@ ইয়য়ো_ফুন এবং আপনি যদি সত্যিই স্মৃতি বুঝতে চান তবে ভবিষ্যতেটেক.ব্লিংকেনলাইটস.এনএল
অ্যালেক্স

1
@Yoyo_fun এটি বেশ সহজ। কিছু মেমরি কন্ট্রোলার কেবল প্রসেসরের বিট প্রস্থের বহুগুণ অ্যাক্সেস করতে পারে (উদাহরণস্বরূপ 32-বিট প্রসেসর কেবল 0-3, 4-7, 8-11, ইত্যাদি ঠিকানার জন্য অনুরোধ করতে পারে)। আপনি যদি একটি অ-প্রান্তিক ঠিকানা চেয়েছিলেন, প্রসেসরের দুটি মেমরি অনুরোধ করতে হবে তারপরে রেজিস্টারে ডেটা আনতে হবে। সুতরাং, 32-বিট-এ ফিরে যদি আপনি ঠিকানা 1 তে একটি মান সঞ্চিত রাখতে চান, প্রসেসরকে 0-3, 4-7 ঠিকানা জিজ্ঞাসা করতে হবে, তারপরে 1, 2, 3 এবং 4 থেকে বাইট পেতে হবে মেমরি পড়া নষ্ট।
ফায়ারফক্স

2
মাইনর পয়েন্ট, তবে মিস্যালাইনযুক্ত মেমরি অ্যাক্সেস কোনও পারফরম্যান্স হিটের পরিবর্তে অপরিশোধনযোগ্য ত্রুটি হতে পারে। আর্কিটেকচার নির্ভর।
জন চেস্টারফিল্ড

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

2

আপনার পরীক্ষা অগত্যা আপনি এটি কী মনে করেন তা যাচাই করে না, কারণ এই স্থানীয় ভেরিয়েবলগুলির একে অপরের সাথে সম্পর্কিত করার জন্য ভাষার কোনও প্রয়োজন নেই।

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

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

বিপরীতে, এটি কোনও স্ট্রাক্টে অস্থায়ী পরিবর্তনশীল সন্নিবেশ করার অনুমতি দেওয়া হবে না, সুতরাং আপনি যদি এর পরিবর্তে স্ট্রাক্ট ক্ষেত্রগুলির ঠিকানাগুলি মুদ্রণ করেন তবে আপনি একই লজিকাল মেমরির (স্ট্রাক্ট) বরাদ্দকৃত আইটেমগুলির সাথে তুলনা করবেন।

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