2010-08-18 12 views
7

मैं एक सरणी है कि इस तरह है:memcpy एक बाइट की शुरुआत करने के लिए एफएफ एफएफ एफएफ कहते हैं

unsigned char array[] = {'\xc0', '\x3f', '\x0e', '\x54', '\xe5', '\x20'}; 
unsigned char array2[6]; 

जब मैं memcpy का उपयोग करें:

memcpy(array2, array, 6); 

और उन दोनों को मुद्रित:

printf("%x %x %x %x %x %x", array[0], // ... etc 
printf("%x %x %x %x %x %x", array2[0], // ... etc 

एक प्रिंट की तरह:

c0 3f e 54 e5 20 

लेकिन अन्य एक प्रिंट

ffffffc0 3f e 54 ffffffe5 20 

क्या हुआ?

+4

क्या आप कृपया 'array2' की परिभाषा को दोबारा जांच सकते हैं? –

+3

ऐसा लगता है कि हस्ताक्षरित वर्णों के बजाय साइन इन की तरह सरणी 2 का इलाज किया जा रहा है। –

+0

array2 एक हस्ताक्षरित char है [] – Hock

उत्तर

13

मैं एक पूरी compilable उदाहरण में अपने कोड बदल दिया है। मैंने एक 'सामान्य' char की तीसरी सरणी भी जोड़ा जो मेरे पर्यावरण पर हस्ताक्षर किए गए हैं।

#include <cstring> 
#include <cstdio> 

using std::memcpy; 
using std::printf; 

int main() 
{ 

     unsigned char array[] = {'\xc0', '\x3f', '\x0e', '\x54', '\xe5', '\x20'}; 
     unsigned char array2[6]; 
     char array3[6]; 

     memcpy(array2, array, 6); 
     memcpy(array3, array, 6); 

     printf("%x %x %x %x %x %x\n", array[0], array[1], array[2], array[3], array[4], array[5]); 
     printf("%x %x %x %x %x %x\n", array2[0], array2[1], array2[2], array2[3], array2[4], array2[5]); 
     printf("%x %x %x %x %x %x\n", array3[0], array3[1], array3[2], array3[3], array3[4], array3[5]); 

     return 0; 
} 

मेरे परिणाम थे कि मैं क्या उम्मीद।

c0 3f e 54 e5 20 
c0 3f e 54 e5 20 
ffffffc0 3f e 54 ffffffe5 20 

आप देख सकते हैं, केवल जब सरणी एक हस्ताक्षरित चार प्रकार का है 'अतिरिक्त' ff संलग्न मिलता है। कारण यह है कि जब memcpy पर हस्ताक्षर किए char की सरणी भरता है, अब सेट एक उच्च बिट के साथ मान नकारात्मक char मूल्यों के अनुरूप है। printf पर char को int प्रकारों पर पदोन्नत किया जाता है जो प्रभावी रूप से एक साइन एक्सटेंशन का अर्थ है।

%x उन्हें हेक्साडेसिमल में प्रिंट रूप में यद्यपि वे unsigned int थे, लेकिन के रूप में तर्क int के रूप में पारित किया गया था व्यवहार तकनीकी रूप से अनिर्धारित रहता है। आम तौर पर दो की पूरक मशीन पर व्यवहार मानक के समान हस्ताक्षरित रूपांतरण के समान होता है जो मॉड 2^एन अंकगणित (जहां एन unsigned int में मूल्य बिट्स की संख्या है) का उपयोग करता है। चूंकि मान केवल 'थोड़ा' नकारात्मक था (एक संकीर्ण हस्ताक्षरित प्रकार से आ रहा था), पोस्ट रूपांतरण मूल्य अधिकतम संभव unsigned int मान के करीब है, यानी इसमें हेक्स में 1 (बाइनरी में) या f अग्रणी हैं।

+0

आपको हमेशा प्रिंट स्टाइल स्टेटमेंट के साथ मेमोरी के मूल्य की जांच करने की सावधानी बरतनी होगी - डीबगर का उपयोग करने के लिए बहुत बेहतर –

2

% x प्रारूप पूर्णांक प्रकार की अपेक्षा करता है। कास्टिंग का उपयोग करने का प्रयास करें:

 
printf("%x %x %x %x %x %x", (int)array2[0], ... 

संपादित करें: चूंकि मेरी पोस्ट पर नई टिप्पणी कर रहे हैं, मैं कुछ जानकारी जोड़ना चाहते हैं। Printf फ़ंक्शन को कॉल करने से पहले, कंपाइलर कोड उत्पन्न करता है जो पैरामीटर (...) की स्टैक चर सूची पर धक्का देता है। कंपाइलर printf प्रारूप कोड के बारे में कुछ नहीं जानता है, और उनके प्रकार के अनुसार पैरामीटर धक्का देता है। printf स्ट्रिंग के अनुसार स्टैक से पैरामीटर एकत्र करता है। तो, सरणी [i] को चार के रूप में धक्का दिया जाता है, और printf द्वारा int के रूप में संभाला जाता है। इसलिए, कास्टिंग करना हमेशा अच्छा विचार है, अगर पैरामीटर प्रकार बिल्कुल प्रारूप विनिर्देश से मेल नहीं खाता है, तो printf/scanf कार्यों के साथ काम कर रहा है।

+0

char पूर्णांक प्रकार है। सी 99 std: 6.2.5 पैरा 4: 'पांच मानक हस्ताक्षरित पूर्णांक प्रकार हैं, जिन्हें हस्ताक्षरित चार, लघु int, int, long int, और लंबे लंबे int के रूप में नामित किया गया है। (ये और अन्य प्रकार हो सकते हैं जैसा कि 6.7.2 में वर्णित कई अतिरिक्त तरीकों से नामित किया गया है।) ' – osgx

+0

लेकिन चार बाइट्स में स्टैक पर एक चार पारित नहीं किया जा सकता है, जो'% x' की अपेक्षा की जा रही है। –

+0

फ़ंक्शन कॉल चार के int को बढ़ावा देगा (और मौजूदा प्रचार को भरें) – KevinDTimm

4

समस्या memcpy नहीं है (जब तक कि आपका चार प्रकार वास्तव में 8 बिट्स के बजाय 32 बिट्स न हो), यह प्रिंटिंग के दौरान पूर्णांक साइन एक्सटेंशन की तरह दिखता है।

आप स्पष्ट रूप से, अहस्ताक्षरित चार रूपांतरण का उपयोग करने यानी अपने printf बदलने के लिए कर सकते हैं।

printf("%hhx %hhx...", array2[0], array2[1],...); 

एक अनुमान के रूप में, यह संभव है कि आपके संकलक/अनुकूलक array (जिसका आकार और सामग्री संकलन समय पर जाना जाता है) और array2 अलग ढंग से निपटने की है, पहली जगह में ढेर पर निरंतर मूल्यों को आगे बढ़ाने और ग़लती से संकेत धक्का है दूसरे में विस्तारित मूल्य।

4

आप उच्च बिट्स बंद मुखौटा चाहिए, क्योंकि अपने वर्ण int आकार के लिए लागू किया जाएगा जब एक varargs फ़ंक्शन कॉल:

printf("%x %x %x %x %x %x", array[0] & 0xff, // .. 
+0

% एचएचएक्स बेहतर है। – osgx

+0

@osgx - हाँ, लेकिन हमारे पुराने सी लोगों ने लंबे समय से पहले और 0xff को सीखा :) पुरानी आदतें मर जाती हैं – KevinDTimm

+2

'% hhx' (अभी तक) सी ++ नहीं है, याद रखें कि सी ++ इसके लिए पूर्व-सी 99 मानक संस्करण को संदर्भित करता है 'printf' अनुबंध। –

संबंधित मुद्दे