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 *として必要な他の引数を解析するためです。
コンパイラの警告を回避するには、次のものが必要です。
strncpy((char *)digest, argv[2], 20);
しかし、コンパイラの警告を回避することはしばしばnotが良い考えです。それは根本的な非互換性があることを伝えています。この場合、非互換性はchar
の範囲が-128〜+127(通常)であるのに対し、unsigned char
は0〜+255です。
正しくコピーすることはできません。型に違いがあるため、コンパイラーはそれについて警告します。
argv[2]
配列の生のビットをコピーする必要がある場合は、memcpy
関数を使用する必要があります。
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)
が必要だと思います。呼び出しで各要素のサイズを使用したい場合は、上のコードのようにオブジェクト自体を使用します。
Memcpyは次のように使用できます。
memcpy(digest, argv[2], strlen(argv[2]) + 1);
srcおよびdestポインターが指すオブジェクトの基礎となるタイプは、この関数には関係がないためです。
_char *
_を_unsigned char *
_に変換する方法は1つではありません。それらはデータを指しており、データの形式を知っている必要があります。
SHA-1ハッシュには、少なくとも3つの異なる形式があります。
"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'
_が含まれていると、ダイジェストの一部が失われます。
(char*)
の前または(unsigned char*)
警告は単にそれが言っていることです、あなたはそれが期待するものとは異なる署名であるstrncpy関数にunsigned char *ダイジェストを渡しています。