将char数组分配给union数据类型时,我的编译器会抛出一个错误:“从char *转换为非标量类型”

时间:2013-12-01 06:40:04

标签: c unions type-conversion

让我解释一下我的计划的整体功能。用户可以输入字符串,并根据MD5哈希算法对该字符串进行哈希处理。然后它将字符串打印到stdout。

我发现使用联合结构简化了代码:

union md5hash
{
     uint ui[4]; //= 16 bytes --> 128 bits 
     char ch[16]; //= 16 bytes --> 128 bits
};

我的程序在这种情况下运行良好。

但是,我想扩展我的程序的功能。我希望通过stdin输入MD5哈希,而不是输入要进行哈希处理的字符串。

这是一个试图复制此功能的简短程序:

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

typedef unsigned int uint;

union md5hash
{
    uint ui[4]; //= 16 bytes --> 128 bits 
    char ch[16]; //= 16 bytes --> 128 bits
};

int main(void){


    std::string hash = "abcdefghjklqwertyuiopasdfghjklzx";
    std::cout << hash.length();
    char* chash = (char*) malloc(sizeof(hash.length()+1));
    memcpy(chash, hash.c_str(), hash.size()+1);
    for(int i = 0; chash[i] ; i++) printf("%c",chash[i]);
    md5hash test =  chash;
    getchar();

}

是的,我知道我的数组长度为32个字符,并且联合中的数组只有16个字符(这是我尚未解决的问题)。无论如何,我需要通过stdin输入的散列与散列的字符串的形式相同。

例如:

Enter string: "Hello"
Goes through hash algorithm: 5d41402abc4b2a76b9719d911017c592

Enter hash:"5d41402abc4b2a76b9719d911017c592"

Are they equal? (Compare their hash values).

但是,hash是一个char数组,而散列值是md5hash数据类型。如何将通过stdin输入的哈希值转换为md5hash数据类型?

另外,我正在使用Dev C ++ - 它使用GCC的Mingw端口(GNU编译器集合)作为它的编译器。我收到的错误是

 conversion from `char*' to non-scalar type `md5hash' requested. 

(我收到上述程序的错误并不感到惊讶。)

赞赏任何建设性的意见。

编辑:

这就是我对字符串进行哈希处理的方法(它不是完整的代码,但这是为字符串准备哈希的方式):

void md5_prep(char *c0)
{
  uint len = 0;
  char *c = c0; 
  while(*c) {len++; c++;}
  c[0] = 0x80; // bit 1 after the message (Appears counterintuitive, but remember c was incremented in the above loop
  ((uint*)c0)[14] = len * 8;    // message length in bits (Note: 4 * 14 is 56 - appends to end of buffer as stated in Wikipedia's psuedocode)
}

void print_md5(uint *hash, bool crlf)
{
  for(int i = 0; i != 16; i++) { printf("%02x", (uint)(((unsigned char *)hash)[i])); }
  if(crlf) printf("\n");
}

union md5hash
{
  uint ui[4]; //= 16 bytes --> 128 bits (allows the message to be divided into chunks due to union structure)
  char ch[16]; //= 16 bytes --> 128 bits
};


md5hash single_md5(char* ptext)
{
  md5hash h;

  char w[64] = {0}; //Declare an empty array
  //for(int i = 0; ptext[i]; i++) w[i] = ptext[i];
  strncpy(w, ptext, 56); //Copy over the text to be hashed; this effectively "zero pads" the string (limiting to 56 - my choice)
  md5_prep(w);
  MD5_CPU((uint*)&w[0], h.ui[0], h.ui[1], h.ui[2], h.ui[3]); //Hash the message

  return h;
}

//Test
int main(void){
  //Declarations
  std::string target = "Hello";

  char tes[120] = {0};
  tes[0] = 'h';
  tes[1] = 'e';
  for(int i =0; tes[i]; i++)
          printf("%c", tes[i]);
  printf("\n");

  //Execute
  md5hash test = single_md5(tes);
  print_md5(test.ui, false);

  return 0;
}

所以,如果我想将输入的哈希值与输入字符串中的计算哈希值进行比较,我可以这样做

   a == target[0] && b == target[1] && c == target[2] && d == target[3]

a,b,c,dui[1], ui[2], ui[3], ui[4]

但是,我需要以某种方式将哈希字符串转换为union所定义的格式。

2 个答案:

答案 0 :(得分:1)

似乎您的问题是用户输入哈希的32位文本(十六进制)表示,而您需要原始数据。所以,你必须在两者之间进行转换:

int hex2int(char ch)
{
    if (isdigit(ch))
        return ch - '0';

    switch (ch) {
    case 'a': case 'A': return 10;
    case 'b': case 'B': return 11;
    case 'c': case 'C': return 12;
    case 'd': case 'D': return 13;
    case 'e': case 'E': return 14;
    case 'f': case 'F': return 15;
    default: abort(); // shan't happen
    }
}

char md5_hex2raw(char raw[16], const char hex[32])
{
    for (int i = 0; i < 32; i += 2) {
        raw[i] = (hex2int(hex[0]) << 4) | hex2int(hex[1]);
    }
}

然后,您可以调用转换函数,以便将其直接复制到联合中:

md5hash hash;
md5_hex2raw(hash.ch, user_entered_string);

答案 1 :(得分:0)

我认为你应该编写一个函数来实现这个转换,如下所示:

 union md5hash str2md5hash(const char *str)
 {
    union md5hash out = {0};
    strcpy(out.ch,str);
    return out;
 }

 union md5hash int2md5hash(int data)
 {
    union md5hash out = {0};
    out.ui = data;
    return out;
 }