2012-06-19 2 views
0

Коротко: Вопрос связан с поразрядными операциями на hex-языке C; O.S: linuxПобитовые операции 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); 
} 

Может кто-нибудь, пожалуйста, дайте мне знать, как это сделать? thx

+0

Как первый результат при переполнении? –

+0

При компиляции я получаю: «предупреждение: переполнение в неявном постоянном преобразовании» –

+0

@DanF, 'log_2 (t1)' равно 79. Он переполняет 64-разрядное целое число без знака на 15 бит. – Matt

ответ

1

Побитовые операции обычно очень легко распространяются на большие числа.

Лучший способ сделать это - разбить их на 4 или 8 байтовых последовательностей и сохранить их в виде массива uints. В этом случае вам понадобится не менее 80 бит для этих конкретных строк.

Для И это довольно просто, что-то вроде:

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; 
} 
+0

Мне нужно вручную разбить его на байтовые последовательности. Не уверен, что я могу разделить строку символов, а затем передать ее как шестнадцатеричный, чтобы сохранить массив int, верно? –

+0

@TestTester, я добавил читателя на основе sscanf для ответа :) – Matt

+0

thx для вашего времени –

0

Вам обязательно понадобится библиотека, которая может обрабатывать произвольно длинные целые числа. Рассмотрим использование libgmp: http://gmplib.org/

0

Прежде чем вы сможете выполнять любые побитовые операции, вам нужно работать с целыми числами. "abeffccc" является не целое число. Это строка. Вам нужно использовать что-то вроде strtol , чтобы сначала преобразовать строку в целое число.

Если ваши значения слишком велики, чтобы вписаться в 64-разрядный long long int (0xFFFFFFFF, FFFFFFFF), вам понадобится библиотека Big Integer или что-то подобное, чтобы поддерживать сколь угодно большие значения. Как упоминалось в H2CO3, libgmp является отличным выбором для больших чисел в C.

+0

О, я мог бы объединить то, что большинство из вас говорит: Разделить на строку из 4 или 8 строк символов и сохранить в массиве (Мат упомянул об этом выше), а затем использовать strtol для преобразования каждого в целое число, а затем выполнять побитовые операции и не нужно библиотеки, как упоминалось в H2CO3. Не знаю, будет ли это лучше всего или если он будет работать –

0

Вместо использования unsigned long напрямую, вы можете попробовать использовать массив unsigned int. Каждый unsigned int содержит 32 бита или 8 шестнадцатеричных цифр. Поэтому Вам придется рубить-вашу константу на куски 8 шестнадцатеричных цифр каждый:

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

Обратите внимание, что для здравого смысла, вы должны хранить их в обратном порядке, так что первая запись t1 содержит биты низшего порядка ,

Смежные вопросы