2011-08-04 20 views
18

कैसे मैं सही ढंग से एक अहस्ताक्षरित चार * करने के लिए एक चार * कॉपी कर सकता सी के बाद में मेरे कोड हैअहस्ताक्षरित चार में कनवर्ट कर चार * *

int main(int argc, char **argv) 
{ 
    unsigned char *digest; 

    digest = malloc(20 * sizeof(unsigned char)); 
    strncpy(digest, argv[2], 20); 
    return 0; 
} 

मैं चाहूँगा सही ढंग से चार कॉपी करने के लिए * अहस्ताक्षरित चार के लिए सरणी * सरणी। अधिक जानकारी जोड़ना, मेरे आवश्यकता है कि फोन करने वाले एक SHA कमांड लाइन पर एक स्ट्रिंग और मुख्य कार्य आंतरिक रूप से बचाने के रूप में मुख्य कार्य करने के लिए पचाने प्रदान करना है: मैं ऊपर कोड

warning: pointer targets in passing argument 1 of âstrncpyâ differ in signedness 

संपादित का उपयोग कर निम्न चेतावनी मिल यह पाचन में है। एसएए डाइजेस्ट को एक हस्ताक्षरित चार का उपयोग करके सबसे अच्छा प्रतिनिधित्व किया जा सकता है।

अब पकड़ यह है कि मैं मुख्य फ़ंक्शन (** char) के हस्ताक्षर को नहीं बदल सकता क्योंकि मुख्य फ़ंक्शन अन्य तर्कों को पार करता है जिन्हें इसे char * और हस्ताक्षरित char * के रूप में आवश्यक नहीं है।

+2

एक हैश डाइजेस्ट आमतौर पर डाइजेस्ट के हेक्स वैल्यू के एएससीआईआई प्रतिनिधित्व के रूप में व्यक्त किया जाता है (उदाहरण के लिए "' b6379dab2c ... '")। इसके लिए एक 'char' बिल्कुल ठीक है! –

+0

@oli तो मूल रूप से कलाकारों को बिना किसी समस्या के ठीक काम करना चाहिए ((char *) पाचन, argv [2], 20); चूंकि हम ASCII से निपट रहे हैं? – Rajiv

+0

@ राजीव: एसएचए -1 डाइजेस्ट का प्रतिनिधित्व करने के दो अलग-अलग तरीके हैं, जो कि 160 बिट्स हैं। उन तरीकों में से एक 20 8-बिट बाइट्स का उपयोग करना है, और 'हस्ताक्षरित char' इसके लिए सबसे अच्छा प्रकार है। दूसरा तरीका एएससीआईआई प्रतिनिधित्व का उपयोग करना है जिसमें प्रत्येक चरित्र एक हेक्साडेसिमल अंक है, जो 4 बिट्स का प्रतिनिधित्व करता है, और इसलिए उनमें से 40 आवश्यक हैं। स्पष्ट रूप से 'strncpy' उनके बीच परिवर्तित नहीं होने जा रहा है। –

उत्तर

10

संकलक चेतावनी से बचने के लिए, आप बस की जरूरत है:

strncpy((char *)digest, argv[2], 20); 

लेकिन संकलक चेतावनी से बचने अक्सर नहीं एक अच्छा विचार है; यह आपको बता रहा है कि एक मौलिक असंगतता है। इस मामले में, असंगतता यह है कि char में -128 से +127 (आमतौर पर) की एक श्रृंखला है, जबकि unsigned char 025 से 025 है।

+0

हाँ, समस्या है, मैं असंगतता को बेहतर तरीके से कैसे हल करूं? – Rajiv

+0

यदि आप हमें बता सकते हैं कि आपको एक हस्ताक्षरित चार के रूप में क्यों आवश्यकता है, तो यह हमें जवाब देने में मदद कर सकता है? बेहतर समाधान पर अनुमान लगाने के लिए आपको शायद हस्ताक्षरित चार मेमोरी के ब्लॉब के बजाय संरचना या संघ का उपयोग करना चाहिए। – noelicus

+0

'char *' बनाम 'हस्ताक्षरित चार *' के मामले में, चेतावनी (जो मानक के अनुसार, संकलक को त्रुटि के रूप में माना जाता है!) मानक में किसी बग को छोड़कर किसी भी बग का शायद ही संकेत मिलता है। लगभग सभी मानक कार्य 'char *' लेते हैं लेकिन डेटा से निपटते हैं जिसे वास्तव में 'हस्ताक्षरित चार' की सरणी के रूप में माना जाता है। 'Strcmp' देखें। –

4

आप सही ढंग से कॉपी नहीं कर सकते हैं क्योंकि प्रकारों में अंतर है, संकलक आपको इसके बारे में चेतावनी देता है।

यदि आपको argv[2] सरणी के कच्चे बिट्स कॉपी करने की आवश्यकता है तो आपको memcpy फ़ंक्शन का उपयोग करना चाहिए।

+0

'memcpy' के साथ, आपको सरणी के बाहर तत्वों तक पहुंचने से बचने के लिए पहले' argv [2] 'की लंबाई जांचनी होगी। – pmg

+0

@pmg इसके बारे में कोई संदेह नहीं है! –

0

चेतावनी बस यह कहती है कि आप क्या कहते हैं, आप एक अनगिनत char * पाचन को strncpy फ़ंक्शन में पास कर रहे हैं जो कि इसकी अपेक्षा से अलग हस्ताक्षर में है।

2

कास्ट signedness strncpy() कॉल

strncpy((char*)digest, argv[2], 20); 

में दूर या परिचय एक और चर

#include <stdlib.h> 
#include <string.h> 

int main(int argc, char **argv) 
{ 
    unsigned char *digest; 
    void *tmp;     /* (void*) is compatible with both (char*) and (unsigned char*) */ 

    digest = malloc(20 * sizeof *digest); 
    if (digest) { 
     tmp = digest; 
     if (argc > 2) strncpy(tmp, argv[2], 20); 
     free(digest); 
    } else { 
     fprintf(stderr, "No memory.\n"); 
    } 
    return 0; 
} 

भी ध्यान रखें कि malloc(20 * sizeof(unsigned char*)) शायद आप क्या चाहते हैं नहीं है। मुझे लगता है कि आप malloc(20 * sizeof(unsigned char)) चाहते हैं, या परिभाषा के अनुसार sizeof (unsigned char)1, malloc(20) है। यदि आप वास्तव में कॉल में प्रत्येक तत्व के आकार का उपयोग करना चाहते हैं, तो ऊपर दिए गए मेरे कोड में ऑब्जेक्ट का उपयोग करें।

+1

आईएमओ, यहां एक डमी वैरिएबल पेश करने से कोड को खराब कर दिया गया है, बिना किसी लाभ के। –

+0

ओपी स्पष्ट रूप से "एक कलाकार से बेहतर तरीका" चाहता है। Obfuscated '(शून्य *)' चर अलग तरीके से पूरा करता है: यदि यह ओपी के लिए बेहतर है तो मैं निर्णय छोड़ दूंगा (जैसे आप, @ ओली, मुझे लगता है कि यह नहीं है)। – pmg

1

आप के रूप में memcpy का उपयोग कर सकते हैं:

memcpy(digest, argv[2], strlen(argv[2]) + 1); 

के रूप में वस्तुओं के अंतर्निहित प्रकार के द्वारा src और गंतव्य संकेत दिए गए इस कार्य के लिए अप्रासंगिक हैं ओर इशारा किया।

+0

आपके पास 'argv [2] [1 9]' की अनुमति नहीं है। – pmg

+0

@pmg संपादित wrt u good चिंता –

+0

मुझे यकीन नहीं है कि 'digest' में '\ 0'' की आवश्यकता है। वैसे भी, अब आपको यह जांचना होगा कि 'strlen (argv [2]) 'digest' के लिए आवंटित आकार के लिए पर्याप्त छोटा है :) – pmg

0

char * से unsigned char * को परिवर्तित करने का कोई भी तरीका नहीं है। वे डेटा इंगित करते हैं, और आपको डेटा के प्रारूप को जानना चाहिए।,

  • कच्चे द्विआधारी वास्तव में 20 ओक्टेट्स
  • हेक्साडेसिमल स्ट्रिंग के रूप में संग्रह की एक सरणी के रूप में पचाने "e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4"
  • की तरह:

    एक SHA-1 हैश के लिए कम से कम 3 विभिन्न स्वरूपों रहे हैं एक Base64 स्ट्रिंग के रूप में संग्रह, जैसे "5en6G6MezRroT3XKqkdPOmY/BfQ="

आपका malloc(20 * sizeof(unsigned char)) एक द्विआधारी डाइजेस्ट का सही आकार की है, लेकिन बहुत आह फिट करने के लिए छोटा है exadecimal स्ट्रिंग या एक बेस 64 स्ट्रिंग। मुझे लगता है कि unsigned char * बाइनरी डाइजेस्ट को इंगित करता है।

लेकिन char *main() के कमांड लाइन तर्क से आया, इसलिए char * शायद एक स्ट्रिंग को इंगित करता है। कमांड लाइन तर्क हमेशा सी तार होते हैं; वे एनयूएल टर्मिनेटर '\0' के साथ समाप्त होते हैं और स्ट्रिंग में '\0' कभी नहीं होते हैं। कच्चे बाइनरी डाइजेस्ट में '\0' हो सकता है, इसलिए वे कमांड लाइन तर्क के रूप में काम नहीं करते हैं।

कोड SHA-1 कच्चे बाइनरी में हेक्साडेसिमल स्ट्रिंग से पचाने की तरह

#include <stdio.h> 
#include <stdlib.h> 

unsigned char * 
sha1_from_hex(char *hex) 
{ 
    int i, m, n, octet; 
    unsigned char *digest; 

    digest = malloc(20); 
    if (!digest) 
     return NULL; 

    for (i = 0; i < 20; i++) { 
     sscanf(hex, " %n%2x%n", &m, &octet, &n); 
     if (m != 0 || n != 2) 
      goto fail; 
     digest[i] = octet; 
     hex += 2; 
    } 
    if (*hex) 
     goto fail; 
    return digest; 

fail: 
    free(digest); 
    return NULL; 
} 

लग सकता है strncpy(dst, src, 20) का प्रयोग न करें कच्चे द्विआधारी डाइजेस्ट कॉपी करने के लिए कन्वर्ट करने के लिए। strncpy(3) फ़ंक्शन प्रतिलिपि रोकता है अगर उसे '\0' मिल जाता है; इसलिए यदि आपके पाचन में '\0' है, तो आप पाचन का हिस्सा खो देते हैं।