2 বাইটকে স্বাক্ষরিত 16-বিট পূর্ণসংখ্যায় রূপান্তর করার সঠিক উপায় কী?


31

ইন এই উত্তর , zwol এই দাবিটি করেছেন:

বাহ্যিক উত্স থেকে দুটি বাইট ডেটা 16-বিট স্বাক্ষরিত পূর্ণসংখ্যায় রূপান্তর করার সঠিক উপায় হ'ল সহায়ক ফাংশনগুলির সাথে:

#include <stdint.h>

int16_t be16_to_cpu_signed(const uint8_t data[static 2]) {
    uint32_t val = (((uint32_t)data[0]) << 8) | 
                   (((uint32_t)data[1]) << 0);
    return ((int32_t) val) - 0x10000u;
}

int16_t le16_to_cpu_signed(const uint8_t data[static 2]) {
    uint32_t val = (((uint32_t)data[0]) << 0) | 
                   (((uint32_t)data[1]) << 8);
    return ((int32_t) val) - 0x10000u;
}

উপরের ফাংশনগুলির মধ্যে কোনটি উপযুক্ত তা অ্যারেতে একটু এন্ডিয়ান বা বড় এন্ডিয়ান উপস্থাপনা রয়েছে কিনা তার উপর নির্ভর করে। এডিয়েননেস এখানে প্রশ্নটি নয়, আমি ভাবছি কেন zwol রূপান্তরিত মান 0x10000uথেকে বিয়োগ uint32_tকরে int32_t

কেন এটি সঠিক উপায় ?

রিটার্নের ধরণে রূপান্তর করার সময় এটি কীভাবে বাস্তবায়ন সংজ্ঞায়িত আচরণ এড়িয়ে যায়?

যেহেতু আপনি 2 এর পরিপূরক প্রতিনিধিত্ব ধরে নিতে পারেন, তাই এই সহজ কাস্ট কিভাবে ব্যর্থ হবে: return (uint16_t)val;

এই নিষ্পাপ সমাধানে ভুল কী:

int16_t le16_to_cpu_signed(const uint8_t data[static 2]) {
    return (uint16_t)data[0] | ((uint16_t)data[1] << 8);
}

Castালাইয়ের সময় সঠিক আচরণটি int16_tবাস্তবায়ন-সংজ্ঞায়িত হয়, তাই নিখুঁত দৃষ্টিভঙ্গি পোর্টেবল হয় না।
nwellnhof

@ ননহ্নহফের কোনও কাস্ট নেইint16_t
এমএম

কোন ম্যাপিংটি ব্যবহার করবেন তা নির্দিষ্ট করে না দিয়ে শিরোনামের প্রশ্নের উত্তর দেওয়া যাবে না
এমএম ২

4
উভয় পন্থা বাস্তবায়ন সংজ্ঞায়িত আচরণের উপর নির্ভর করে (একটি স্বাক্ষরিত মানকে একটি স্বাক্ষরিত ধরণের রূপান্তর করে যা মানটির প্রতিনিধিত্ব করতে পারে না)। যেমন। প্রথম পদ্ধতির মধ্যে, 0xFFFF0001uহিসাবে প্রতিনিধিত্ব করা যাবে না int16_t, এবং দ্বিতীয় পদ্ধতির 0xFFFFuহিসাবে প্রতিনিধিত্ব করা যাবে না int16_t
Sander De Dycker

1
"যেহেতু আপনি 2 এর পরিপূরক প্রতিনিধিত্ব ধরে নিতে পারেন" [উদ্ধৃতি আবশ্যক] C89 এবং C99 অবশ্যই 1 এস পরিপূরক এবং সাইন-প্রস্থের উপস্থাপনা অস্বীকার করেনি। QV, stackoverflow.com/questions/12276957/...
এরিক টাওয়ার

উত্তর:


20

যদি int16-বিট হয় তবে আপনার সংস্করণটি প্রয়োগের সংজ্ঞায়িত আচরণের উপর নির্ভর করে যদি returnবিবৃতিতে প্রকাশের মানটি সীমার বাইরে থাকে int16_t

তবে প্রথম সংস্করণেও একই রকম সমস্যা রয়েছে; উদাহরণস্বরূপ যদি int32_tকোনও টাইপডেফ হয় intএবং ইনপুট বাইট উভয়ই হয় 0xFF, তারপরে রিটার্নের বিবৃতিতে বিয়োগের ফলাফলটি UINT_MAXরূপান্তরিত হওয়ার সময় বাস্তবায়ন-সংজ্ঞায়িত আচরণের কারণ হয় int16_t

আপনি যে উত্তরটির সাথে লিঙ্ক করেছেন তার আইএমএইচও করুন কয়েকটি বড় সমস্যা রয়েছে।


2
তবে সঠিক উপায় কী?
ইডমিয়ান

@ আইডমেয়ান প্রশ্নের উত্তর দেওয়ার আগে প্রশ্নের স্পষ্টতা দরকার, আমি প্রশ্নের অধীনে একটি মন্তব্যে অনুরোধ করেছি কিন্তু ওপি সাড়া দেয়নি
এমএম ২

1
@ এমএম: আমি প্রশ্নটি সম্পাদনা করে নির্দিষ্ট করে দিয়েছি যে পরিণামটি সমস্যা নয়। IMHO ইস্যুটি zwol সমাধানের চেষ্টা করছে গন্তব্যের ধরণে রূপান্তর করার সময় এটি বাস্তবায়িত সংজ্ঞায়িত আচরণ, তবে আমি আপনার সাথে একমত হই: আমার বিশ্বাস যে তার পদ্ধতিতে অন্যান্য সমস্যা আছে বলে তিনি ভুল করেছেন। কীভাবে আপনি কার্যকরভাবে সংজ্ঞায়িত আচরণটি দক্ষতার সাথে সমাধান করবেন?
chqrlie

@ chqrlieforyellow blockquotes আমি বিশেষত শেষের দিকে উল্লেখ করছি না আপনি কি কেবলমাত্র দুটি ইনপুট অকটেটের সঠিক বিটগুলিকে লিখতে চান int16_t?
এমএম

@ এমএম: হ্যাঁ, এটি ঠিক প্রশ্ন। আমি লিখেছি বাইট কিন্তু সঠিক শব্দটি প্রকৃতপক্ষে হওয়া উচিত অক্টেট যেমন প্রকার uchar8_t
chqrlie

7

এটি প্যাডেন্টিকভাবে সঠিক হওয়া উচিত এবং প্ল্যাটফর্মগুলিতেও কাজ করা উচিত যা সাধারণ 2 এর পরিপূরকের পরিবর্তে সাইন বিট বা 1 এর পরিপূরক উপস্থাপনা ব্যবহার করে । ইনপুট বাইট 2 এর পরিপূরক হিসাবে ধরে নেওয়া হয়।

int le16_to_cpu_signed(const uint8_t data[static 2]) {
    unsigned value = data[0] | ((unsigned)data[1] << 8);
    if (value & 0x8000)
        return -(int)(~value) - 1;
    else
        return value;
}

শাখার কারণে এটি অন্যান্য বিকল্পগুলির চেয়ে বেশি ব্যয়বহুল হবে।

এটি যা অর্জন করে তা হ'ল এটি প্ল্যাটফর্মে intউপস্থাপনের সাথে কীভাবে উপস্থাপনের সাথে সম্পর্কিত তার কোনও ধারণাই এড়ানো যায় unsigned। ঢালাই করার intকোনো সংখ্যা লক্ষ্য ধরনের মাপসই করা হবে জন্য গাণিতিক মান সংরক্ষণ প্রয়োজন। কারণ বিবর্তনটি নিশ্চিত করে যে শীর্ষ বিট 16-বিট সংখ্যার শূন্য হবে, মানটি ফিট হবে। তারপরে -1 এর অবিচ্ছিন্ন এবং বিয়োগ 2 এর পরিপূরক অবহেলার জন্য নিয়মটি প্রয়োগ করে। প্ল্যাটফর্মের উপর নির্ভর করে, এটি লক্ষ্যবস্তুর INT16_MINধরণে ফিট না হলে এখনও উপচে পড়তে পারে int, কোন ক্ষেত্রে longএটি ব্যবহার করা উচিত।

প্রশ্নের মূল সংস্করণে পার্থক্য ফিরে আসার সময় আসে। যদিও মূল মাত্র সবসময় বিয়োগ 0x10000এবং 2 এর সম্পূরক সাইন যাক ওভারফ্লো এটি মোড়ানো int16_tপরিসীমা, এই সংস্করণে স্পষ্ট হয়েছে ifযে এড়াতে wrapover স্বাক্ষরিত (যা হয় অনির্দিষ্ট )।

এখন অনুশীলনে, আজ ব্যবহৃত প্রায় সমস্ত প্ল্যাটফর্ম 2 এর পরিপূর্ণ প্রতিনিধিত্ব ব্যবহার করে। প্রকৃতপক্ষে, যদি প্ল্যাটফর্মটির মান-সম্মতিযুক্ত stdint.hযা সংজ্ঞা দেয় int32_t, তবে এটির জন্য এটি অবশ্যই 2 এর পরিপূরক ব্যবহার করবে। এই পদ্ধতির মাঝে মাঝে কিছু স্ক্রিপ্টিং ভাষা রয়েছে যেখানে পূর্ণসংখ্যার ডেটা ধরণের কিছু নেই - আপনি উপরের ফ্লোটগুলির জন্য প্রদর্শিত ক্রিয়াকলাপগুলি পরিবর্তন করতে পারেন এবং এটি সঠিক ফলাফল দেবে give


সি স্ট্যান্ডার্ড নির্দিষ্টভাবে আদেশ দেয় int16_tএবং যে কোনও intxx_tএবং তাদের স্বাক্ষরবিহীন রূপগুলি প্যাড বিট ছাড়াই 2 এর পরিপূরক উপস্থাপনা ব্যবহার করতে হবে। এই ধরণের হোস্ট করার জন্য intএবং এটির জন্য আরও একটি উপস্থাপনা ব্যবহার করতে একটি উদ্দেশ্যমূলক বিকৃত আর্কিটেকচার লাগবে , তবে আমার ধারণা ডিএস 9 কে এইভাবে কনফিগার করা যেতে পারে।
chqrlie

গুড বিন্দু @chqrlieforyellowblockquotes, আমি ব্যবহার করতে পরিবর্তিত intবিভ্রান্তির এড়ানো। প্রকৃতপক্ষে যদি প্ল্যাটফর্মটি সংজ্ঞায়িত করে তবে int32_tএটি অবশ্যই 2 এর পরিপূরক হতে হবে।
জেপি

এই ধরণের প্রকারগুলি C99 এ এভাবে প্রমিত করা হয়েছে: C99 7.18.1.1 সঠিক প্রস্থের পূর্ণসংখ্যার প্রকার টাইপডেফ নামটি intN_t একটি স্বাক্ষরিত পূর্ণসংখ্যার প্রস্থ N, প্রস্থের কোনও বিড, এবং কোনও দু'জনের পরিপূরক প্রতিনিধিত্ব করে না। সুতরাং, int8_tঠিক 8 বিটের প্রস্থ সহ একটি স্বাক্ষরিত পূর্ণসংখ্যা টাইপকে বোঝায়। অন্যান্য উপস্থাপনা এখনও স্ট্যান্ডার্ড দ্বারা সমর্থিত, তবে অন্যান্য পূর্ণসংখ্যার ধরণের জন্য।
chqrlie

আপনার আপডেট হওয়া সংস্করণ সহ, (int)valueপ্রয়োগের সংজ্ঞায়িত আচরণ রয়েছে যদি টাইপটিতে intকেবল 16 বিট থাকে। আমি ভীত আপনার ব্যবহার করা দরকার (long)value - 0x10000, তবে 2 টির পরিপূরক আর্কিটেকচারে, মানটি 0x8000 - 0x1000016-বিট হিসাবে উপস্থাপন করা intযায় না, তাই সমস্যাটি স্থির থাকে।
chqrlie

@ chqrlieforyellow blockquotes হ্যাঁ, ঠিক একই লক্ষ্য করেছি, আমি পরিবর্তে with দিয়ে ঠিক করেছি, তবে longএকইভাবে ভালভাবে কাজ করব।
জেপা

6

অন্য একটি পদ্ধতি - ব্যবহার করে union:

union B2I16
{
   int16_t i;
   byte    b[2];
};

প্রোগ্রামে:

...
B2I16 conv;

conv.b[0] = first_byte;
conv.b[1] = second_byte;
int16_t result = conv.i;

first_byteএবং second_byteঅল্প বা বড় এন্ডিয়ান মডেল অনুসারে অদলবদল করা যেতে পারে। এই পদ্ধতিটি আরও ভাল নয় তবে এটি বিকল্পগুলির একটি।


2
ইউনিয়ন টাইপ অনির্দিষ্ট আচরণ শাস্তি না ?
ম্যাক্সিম এগারুশকিন

1
@ ম্যাক্সিমএগরোশকিন: উইকিপিডিয়া সি স্ট্যান্ডার্ডকে ব্যাখ্যা করার জন্য কোনও অনুমোদিত উত্স নয়।
এরিক পোস্টপিসিল

2
@ এরিকপোস্টপিসিল ম্যাসেঞ্জারে ফোকাস দেওয়ার চেয়ে বার্তাটি বোকামি।
ম্যাক্সিম এগুরুশকিন

1
@ ম্যাক্সিম এগারোশকিন: ওহ হ্যাঁ, উফ, আমি আপনার মন্তব্যটি ভুলভাবে লিখেছি। ধরে নেওয়া byte[2]এবং int16_tএকই আকার, এটি দুটি সম্ভাব্য ক্রমের এক বা অন্যটি, কিছু স্বেচ্ছাচারিত বিটওয়াইজ স্থান মান নয়। সুতরাং আপনি কমপক্ষে কমপাইল সময়ে সনাক্ত করতে পারেন যে বাস্তবায়নের কী পরিণতি রয়েছে।
পিটার কর্ডেস ২

1
স্ট্যান্ডার্ডটি পরিষ্কারভাবে জানিয়েছে যে ইউনিয়ন সদস্যের মানটি সেই ধরণের মান উপস্থাপনা হিসাবে সদস্যের সঞ্চিত বিটকে ব্যাখ্যা করার ফলাফল। বাস্তবায়ন-সংজ্ঞায়িত দিকগুলি রয়েছে ইনফারাগুলিতে প্রকারের উপস্থাপনাটি বাস্তবায়ন-সংজ্ঞায়িত।
এমএম

6

পাটিগণিত অপারেটররা শিফট এবং বিটওয়াইস-বা এক্সপ্রেশন হিসাবে এর (uint16_t)data[0] | ((uint16_t)data[1] << 8)চেয়ে ছোট প্রকারের উপর কাজ করে না int, যাতে সেই uint16_tমানগুলিতে উন্নীত হয়int (বা unsignedযদি sizeof(uint16_t) == sizeof(int)) । তবুও, এটির সঠিক উত্তর পাওয়া উচিত, যেহেতু কেবলমাত্র নিম্ন 2 বাইটের মান থাকে।

বিগ-এন্ডিয়ান থেকে লিটল-এন্ডিয়ান রূপান্তর (লিটল-এডিয়ান সিপিইউ ধরে নেওয়া) এর জন্য অন্য একটি সঠিক সংস্করণ হ'ল:

#include <string.h>
#include <stdint.h>

int16_t be16_to_cpu_signed(const uint8_t data[2]) {
    int16_t r;
    memcpy(&r, data, sizeof r);
    return __builtin_bswap16(r);
}

memcpyএর প্রতিনিধিত্ব অনুলিপি করতে ব্যবহৃত হয় int16_tএবং এটি হ'ল স্ট্যান্ডার্ড-কমপ্লায়েন্ট উপায়। এই সংস্করণটি 1 টি নির্দেশিকায়ও সংকলিত হয় movbe, সমাবেশ দেখুন


1
@ মিমি __builtin_bswap16বিদ্যমান থাকার একটি কারণ হ'ল আইএসও সি-তে বাইট-অদলবদল কার্যকরভাবে কার্যকর করা যায় না।
ম্যাক্সিম এগুরুশকিন

1
সত্য না; সংকলক সনাক্ত করতে পারে যে কোডটি বাইট অদল-বদল করে এবং এটিকে একটি দক্ষ বিল্টিন হিসাবে অনুবাদ করে
এমএম ২

1
রূপান্তর int16_tকরার uint16_tভাল সংজ্ঞায়িত করা হয়: নেতিবাচক মান চেয়ে অনেক বেশী মান রূপান্তর INT_MAX, কিন্তু এই মান ফিরে রূপান্তর uint16_t: বাস্তবায়ন সংজ্ঞায়িত আচরণ 6.3.1.3 সাইন ইন এবং স্বাক্ষরবিহীন পূর্ণসংখ্যার , পূর্ণসংখ্যা ধরনের সঙ্গে একটি মান অন্য পূর্ণসংখ্যা টাইপ অন্যান্য than_Bool রূপান্তরিত হয় যখন 1. যদি মানটি নতুন ধরণের দ্বারা প্রতিনিধিত্ব করা যায়, এটি অপরিবর্তিত। ... 3. অন্যথায়, নতুন ধরণের স্বাক্ষরিত এবং এতে মানটি উপস্থাপন করা যায় না; হয় ফলাফল বাস্তবায়ন সংজ্ঞায়িত হয় বা বাস্তবায়ন সংজ্ঞায়িত সংকেত উত্থাপিত হয়।
chqrlie

1
@ ম্যাক্সিম এগারোশকিন জিসিসি 16-বিট সংস্করণে এত ভাল কাজ করেছে বলে মনে হচ্ছে না, তবে ঝাঁকুনিটিntohs / __builtin_bswapএবং |/ <<প্যাটার্নের জন্য একই কোড উত্পন্ন করে : gcc.godbolt.org/z/rJ-j87
PSkocik ২

3
@ মিমি: আমার ধারণা ম্যাক্সিম " বর্তমান সংকলকগুলির সাথে অনুশীলন করতে পারবেন না" বলছে । অবশ্যই একটি সংকলক একবারের জন্য স্তন্যপান করতে পারেন না এবং একটি পূর্ণসংখ্যার মধ্যে জটিল বাইট লোড করে সনাক্ত করতে পারে। GCC7 বা 8 পরিশেষে করেনি পুনরায় পরিচয় করিয়ে ক্ষেত্রে যেখানে বাইট-বিপরীত জন্য কোয়ালেসিং লোড / দোকান নয় প্রয়োজন, পরে GCC3 এটা দশক আগে ছেড়ে দিয়েছিলেন। তবে সাধারণ সংকলকগুলিতে সিপিইউগুলি দক্ষতার সাথে করতে পারে তবে আইএসও সি অবহেলিত / বহনযোগ্যভাবে প্রকাশ করতে অস্বীকার করেছে এমন অনেকগুলি স্টাফের সাথে অনুশীলনে সহায়তা প্রয়োজন। পোর্টেবল আইএসও সি দক্ষ কোড বিট / বাইট-ম্যানিপুলেশনের জন্য ভাল ভাষা নয়।
পিটার কর্ডেস ২

4

এখানে আরও একটি সংস্করণ রয়েছে যা কেবল পোর্টেবল এবং ভাল-সংজ্ঞায়িত আচরণের উপর নির্ভর করে (শিরোনামটি #include <endian.h>মান নয়, কোডটি হ'ল):

#include <endian.h>
#include <stdint.h>
#include <string.h>

static inline void swap(uint8_t* a, uint8_t* b) {
    uint8_t t = *a;
    *a = *b;
    *b = t;
}
static inline void reverse(uint8_t* data, int data_len) {
    for(int i = 0, j = data_len / 2; i < j; ++i)
        swap(data + i, data + data_len - 1 - i);
}

int16_t be16_to_cpu_signed(const uint8_t data[2]) {
    int16_t r;
#if __BYTE_ORDER == __LITTLE_ENDIAN
    uint8_t data2[sizeof r];
    memcpy(data2, data, sizeof data2);
    reverse(data2, sizeof data2);
    memcpy(&r, data2, sizeof r);
#else
    memcpy(&r, data, sizeof r);
#endif
    return r;
}

লিটল-এন্ডিয়ান সংস্করণটি একক movbeনির্দেশাবলীর সাথে সংকলিত হয়েছে clang, gccসংস্করণটি কম অনুকূল, সমাবেশ দেখুন


@chqrlieforyellowblockquotes আপনার প্রধান উদ্বেগ হচ্ছে বলে মনে হচ্ছে uint16_tথেকে int16_tরূপান্তর, এই সংস্করণে আপনি যেতে তাই এখানে যে রূপান্তর নেই।
ম্যাক্সিম এগারুশকিন

2

আমি তাদের উত্তরের জন্য সমস্ত অবদানকারীকে ধন্যবাদ জানাতে চাই। এখানে সম্মিলিত কাজগুলি এটিকে ফুটিয়ে তোলে:

  1. সি স্ট্যান্ডার্ড হিসাবে 7.20.1.1 যথাযথ প্রস্থ পূর্ণসংখ্যার প্রকার : প্রকারuint8_t , int16_tএবংuint16_t দুই এর সম্পূরক প্রতিনিধিত্ব কোনো প্যাডিং বিট ছাড়া unambiguously 2 বাইট সেই অ্যারের মধ্যে, দ্বারা নির্দিষ্ট অনুক্রমে ব্যবহার করা আবশ্যক, যাতে প্রতিনিধিত্ব প্রকৃত বিট ফাংশন নাম।
  2. স্বাক্ষরযুক্ত 16 বিট মানটির সাথে কম্পিউটিং করা (unsigned)data[0] | ((unsigned)data[1] << 8) (ছোট এন্ডিয়ান সংস্করণের জন্য) একটি একক নির্দেশিকায় সংকলন করে একটি স্বাক্ষরবিহীন 16-বিট মান দেয়।
  3. সি স্ট্যান্ডার্ড অনুসারে 6.3.1.3 স্বাক্ষরিত এবং স্বাক্ষরবিহীন পূর্ণসংখ্যার : প্রকারের মান রূপান্তরuint16_t স্বাক্ষরিত ধরণের সাথে int16_tসংজ্ঞা প্রয়োগের আচরণ হয় যদি মান গন্তব্যের ধরণের সীমার মধ্যে না থাকে। যাদের প্রতিনিধিত্ব সুনির্দিষ্টভাবে সংজ্ঞায়িত হয়েছে তাদের জন্য কোনও বিশেষ বিধান করা হয়নি।
  4. এই বাস্তবায়ন সংজ্ঞায়িত আচরণ এড়ানোর জন্য, INT_MAXস্বাক্ষরবিহীন মানটি বিয়োগ করে সংশ্লিষ্ট স্বাক্ষরিত মানটির চেয়ে বড় হয় কিনা তা পরীক্ষা করতে পারে 0x10000Zwol দ্বারা প্রস্তাবিত সমস্ত মানের জন্য int16_tএটি করা একই বাস্তবায়ন সংজ্ঞায়িত আচরণের সাথে সীমার বাইরে মান তৈরি করতে পারে ।
  5. 0x8000বিটের জন্য পরীক্ষা করা স্পষ্টতই সংকলকগুলিকে অক্ষম কোড তৈরি করতে বাধ্য করে।
  6. বাস্তবায়ন সংজ্ঞায়িত আচরণ ব্যবহার ছাড়াই আরও দক্ষ রূপান্তর ইউনিয়নের মাধ্যমে ধরণের পাপিং , তবে এই পদ্ধতির সংজ্ঞা সম্পর্কে বিতর্কটি এখনও সি স্ট্যান্ডার্ডের কমিটি পর্যায়ে উন্মুক্ত।
  7. প্রকারের শাস্তি বহনযোগ্যভাবে এবং সংজ্ঞায়িত আচরণের সাহায্যে সম্পাদন করা যেতে পারে memcpy

2 এবং 7 পয়েন্টের সংমিশ্রণ, এখানে একটি পোর্টেবল এবং সম্পূর্ণরূপে সংজ্ঞায়িত সমাধান রয়েছে যা জিসিসি এবং ঝনঝন উভয়ই একক নির্দেশকে দক্ষতার সাথে সংকলন করে :

#include <stdint.h>
#include <string.h>

int16_t be16_to_cpu_signed(const uint8_t data[2]) {
    int16_t r;
    uint16_t u = (unsigned)data[1] | ((unsigned)data[0] << 8);
    memcpy(&r, &u, sizeof r);
    return r;
}

int16_t le16_to_cpu_signed(const uint8_t data[2]) {
    int16_t r;
    uint16_t u = (unsigned)data[0] | ((unsigned)data[1] << 8);
    memcpy(&r, &u, sizeof r);
    return r;
}

-৪-বিট বিধানসভা :

be16_to_cpu_signed(unsigned char const*):
        movbe   ax, WORD PTR [rdi]
        ret
le16_to_cpu_signed(unsigned char const*):
        movzx   eax, WORD PTR [rdi]
        ret

আমি কোনও ভাষা আইনজীবী নই, তবে কেবল charপ্রকারভেদে অন্য কোনও ধরণের অবজেক্টের উপস্থাপনা থাকতে পারে বা থাকতে পারে। uint16_tনা এক char, যাতে ধরনের, memcpyএর uint16_tথেকে int16_tভালভাবে সংজ্ঞায়িত আচরণ নয়। মানকটির কেবলমাত্র সংজ্ঞায়িত করার জন্য char[sizeof(T)] -> T > char[sizeof(T)]রূপান্তর প্রয়োজন memcpy
ম্যাক্সিম এগারুশকিন

memcpyএর uint16_tথেকে int16_tবাস্তবায়ন-সংজ্ঞায়িত শ্রেষ্ঠ সময়ে ঠিক অপরের এক নিয়োগ যেমন পোর্টেবল না, না ভালভাবে সংজ্ঞায়িত, এবং আপনার সাথে যে জাদুর পাশকাটিয়ে করতে পারেন না memcpy। এটা কোন ব্যাপার না কিনা uint16_tব্যবহারসমূহ দুই এর সম্পূরক প্রতিনিধিত্ব বা না, অথবা প্যাডিং বিট বর্তমান বা না - যে আচরণ সংজ্ঞায়িত বা C মান দ্বারা প্রয়োজন হয় না।
ম্যাক্সিম এগারুশকিন

তাই অনেক শব্দ সঙ্গে, আপনার "সমাধান" প্রতিস্থাপন নিচে boils r = uকরতে memcpy(&r, &u, sizeof u)কিন্তু আধুনিক, কোন সাবেক বেশী ভালো তাই না?
ম্যাক্সিম এগারুশকিন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.