【问题标题】:Bitwise Operations C on long hex Linux长十六进制 Linux 上的位运算 C
【发布时间】:2012-06-21 18:28:19
【问题描述】:

简而言之:问题与十六进制语言 C 的按位运算有关;操作系统:linux

我只想对“长”十六进制字符串进行一些按位运算。 我尝试了以下方法:

第一次尝试:

由于溢出,我无法使用以下内容:

long  t1 = 0xabefffcccaadddddffff;
and t2 = 0xdeeefffffccccaaadacd;

第二次尝试:不起作用,因为 abcdef 被解释为字符串而不是十六进制

char* t1 = "abefffcccaadddddffff";
char* t2 = "deeefffffccccaaadacd";

int len = strlen(t1);

for (int i = 0; i < len; i++ )
    {
        char exor = *(t1 + i) ^ *(t2 + i);
    printf("%x", exor);
}

有人可以告诉我怎么做吗?谢谢

【问题讨论】:

  • 第一个怎么导致溢出?
  • 编译后我得到:“警告:隐式常量转换溢出”
  • @DanF, log_2(t1) 是 79。它将 64 位无符号整数溢出 15 位。
  • 这种情况下的问题是他试图分配给long 的值太大。你是对的,我算错了十六进制字符的数量和字节数。

标签: c linux hex bit-manipulation


【解决方案1】:

按位运算通常很容易扩展到更大的数字。

最好的方法是将它们分成 4 或 8 字节序列,并将它们存储为 uint 数组。在这种情况下,这些特定字符串至少需要 80 位。

对于 AND 它非常简单,例如:

unsigned int A[3] = { 0xabef, 0xffcccaad, 0xddddffff };
unsigned int B[3] = { 0xdeee, 0xfffffccc, 0xcaaadacd };
unsigned int R[3] = { 0 };

for (int b = 0; b < 3; b++) {
    R[b] = A[b] & B[b];
}

一个更完整的例子,包括扫描十六进制字符串并打印它们:

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

typedef unsigned int uint;

void long_Print(int size, const uint a[]) {
    printf("0x");
    for (int i = 0; i < size; i++) {
        printf("%x", a[i]);
    }
}

void long_AND(int size, const uint a[], const uint b[], uint r[]) {
    for (int i = 0; i < size; i++) {
        r[i] = a[i] & b[i];
    }
}

// Reads a long hex string and fills an array. Returns the number of elements filled.
int long_Scan(int size, const char* str, uint r[]) {
    int len = strlen(str);
    int ri = size;

    for (const char* here = &str[len]; here != str; here -= 8) {
        if (here < str) {
            char* tmp = (char*)malloc(4);

            tmp[0] = '%';
            tmp[1] = (char)(str - here + '0');
            tmp[2] = 'x';
            tmp[3] = '\0';

            sscanf(str, tmp, &r[ri--]);

            free(tmp);

            break;
        }
        else {
            sscanf(here, "%8x", &r[ri--]);
        }
    }

    for (; ri >= 0; ri--) {
        r[ri] == 0;
    }

    return size - ri;
}

int main(int argc, char* argv[])
{
    uint A[3] = { 0 };
    uint B[3] = { 0 };
    uint R[3] = { 0 };

    long_Scan(3, "abefffcccaadddddffff", A);
    long_Scan(3, "deeefffffccccaaadacd", B);

    long_Print(3, A);
    puts("\nAND");
    long_Print(3, B);
    puts("\n=");

    long_AND(3, A, B, R);
    long_Print(3, R);

    getchar();

    return 0;
}

【讨论】:

  • 是否需要手动将其拆分为字节序列。不确定我是否可以拆分 char 字符串,然后将其转换为十六进制以将其存储为 int 数组,对吗?
  • 如果除第一个单词之外的任何单词的上半字节为 0,则您的 long_Print 将出现错误行为(省略需要存在的 0)。您可能想要 printf("%08x", a[i]); 代替,尽管这也会打印所有前导 0。
  • @ChrisDodd,说得好。我现在会做一些改变。应该不会太棘手。
【解决方案2】:

您可以尝试使用unsigned int 的数组,而不是直接使用unsigned long。每个 unsigned int 包含 32 位或 8 个十六进制数字。因此,您必须将常量分成 8 个十六进制数字的块:

unsigned int t1[3] = { 0xabef , 0xffcccaad , 0xddddffff };

请注意,出于理智考虑,您应该以相反的顺序存储它们,以便t1 的第一个条目包含最低位。

【讨论】:

    【解决方案3】:

    在您可以进行任何类型的按位运算之前,您需要使用整数。 "abeffccc" 不是一个整数。它是一个字符串。你需要使用类似strtol 首先将字符串转换为整数。

    如果您的值太大而无法放入 64 位 long long int (0xFFFFFFFF,FFFFFFFF),那么您需要使用 Big Integer 库或类似的库来支持任意大的值。正如 H2CO3 所提到的,libgmp 是 C 中大量数字的绝佳选择。

    【讨论】:

    • 哦,我可以结合你们大多数人所说的:拆分为 4 或 8 个字符的字符串并存储在一个数组中(上面提到的 Mat),然后使用 strtol 将每个转换为整数然后进行按位运算,不需要提到 H2CO3 的库。不知道这是否是最好的事情,或者它是否会起作用
    【解决方案4】:

    您当然需要使用可以处理任意长整数的库。考虑使用 libgmp:http://gmplib.org/

    【讨论】:

      猜你喜欢
      • 2015-03-30
      • 1970-01-01
      • 1970-01-01
      • 2019-04-21
      • 2012-09-12
      • 2013-08-09
      • 2015-11-10
      • 2013-06-12
      • 2013-06-26
      相关资源
      最近更新 更多