web-dev-qa-db-ja.com

char *からunsigned char *への変換

Cでchar *をunsigned char *に正しくコピーするにはどうすればよいですか?以下は私のコードです

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

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

Char *配列をunsigned char *配列に正しくコピーしたいと思います。上記のコードを使用して次の警告が表示されます

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

[〜#〜] edit [〜#〜]:さらに情報を追加します。私の要件は、呼び出し元がSHAダイジェストを文字列としてメイン関数に提供することです。コマンドラインとメイン関数は、それをダイジェストに内部的に保存します。SHAダイジェストは、符号なし文字を使用して最もよく表すことができます。

ここでの問題は、メイン関数(** char)の署名を変更できないことです。これは、メイン関数がunsigned char *ではなくchar *として必要な他の引数を解析するためです。

19
Rajiv

コンパイラの警告を回避するには、次のものが必要です。

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

しかし、コンパイラの警告を回避することはしばしばnotが良い考えです。それは根本的な非互換性があることを伝えています。この場合、非互換性はcharの範囲が-128〜+127(通常)であるのに対し、unsigned charは0〜+255です。

11

正しくコピーすることはできません。型に違いがあるため、コンパイラーはそれについて警告します。

argv[2]配列の生のビットをコピーする必要がある場合は、memcpy関数を使用する必要があります。

5
Petr Abdulin

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)1malloc(20)が必要だと思います。呼び出しで各要素のサイズを使用したい場合は、上のコードのようにオブジェクト自体を使用します。

2
pmg

Memcpyは次のように使用できます。

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

srcおよびdestポインターが指すオブジェクトの基礎となるタイプは、この関数には関係がないためです。

1
cyber_raj

_char *_を_unsigned char *_に変換する方法は1つではありません。それらはデータを指しており、データの形式を知っている必要があります。

SHA-1ハッシュには、少なくとも3つの異なる形式があります。

  • 正確な20オクテットの配列としての生のバイナリダイジェスト
  • _"e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4"_のような16進数文字列としてのダイジェスト
  • _"5en6G6MezRroT3XKqkdPOmY/BfQ="_のようなBase64文字列としてのダイジェスト

あなたのmalloc(20 * sizeof(unsigned char))は、バイナリダイジェストの正確なサイズを持っていますが、16進数文字列またはBase64文字列に合わせるには小さすぎます。 _unsigned char *_がバイナリダイジェストを指していると思います。

ただし、_char *_はmain()のコマンドライン引数から取得されているため、_char *_はおそらく文字列を指します。コマンドライン引数は常にC文字列です。それらはNULターミネーター_'\0'_で終わり、文字列に_'\0'_が含まれることはありません。生のバイナリダイジェストには_'\0'_が含まれている場合があるため、コマンドライン引数として機能しません。

SHA-1ダイジェストを16進数の文字列から生のバイナリに変換するコードは次のようになります。

_#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'_が含まれていると、ダイジェストの一部が失われます。

0
George Koehler

(char*)の前または(unsigned char*)

0
Johnny camargo

警告は単にそれが言っていることです、あなたはそれが期待するものとは異なる署名であるstrncpy関数にunsigned char *ダイジェストを渡しています。

0
Sandeep Pathak