если постановка задачи - PullRequest
0 голосов
/ 11 августа 2011

видите, у меня есть один сложный код, но я кое-где застрял, поэтому просто даю вам часть этого ..

у меня есть одна функция

function(int a,uint64_t b,int c);

когда я вызывал функцию

  uint64_t b;
  int c;

  printf("enter b");
  scanf("%d",&b);  // i m giving 1

   printf("enter c");
   scanf("%d",&c);  // i m giving 2

  function(0xcd32ab00 ,b ,c);

в этом определении функции я сравниваю значение b с другим параметром, таким как

 /*  magicNum is type uint64_t type & it has value 1 */
if(magicNum == b) 
{
 // do something
}

Но этого "сделать что-то" не происходит; когда я печатаю magicNum & b, оба имеют значение 1, поэтому не могу понять, почему это происходит.

когда я пишу

if((uint64_t)magicNum == (uint64_t)b) 
{
 // do something
}

это прекрасно работает.

Я знаю, что делаю одну глупую ошибку, но я не понимаю ... Пожалуйста, помогите мне ... я работаю в 32-битной системе Linux

Ответы [ 2 ]

5 голосов
/ 11 августа 2011

Что-то не так с вашим исходным кодом, который вы нам не показали. Это потому, что следующее работает нормально:

#include <stdio.h>

static void fn (int a, uint64_t b, int c) {
    uint64_t magicNum = 1;
    if (magicNum == b)
        puts ("They match!");
    if ((uint64_t)magicNum == (uint64_t)b)
        puts ("They still match!");
}

int main (void) {

    fn (0xcd32ab00 ,1 ,2);
    return 0;
}

Вывод:

They match!
They still match!

Исходя из вашего обновления, которое вы используете scanf("%d") для получения значений, это довольно известная проблема для тех из нас, кто был извращен десятилетиями использования C: -)

Когда вы указываете %d в качестве спецификатора формата, он ожидает указатель на тип int и записывает в этот тип. Если указатель, указанный вами, имеет тип, который в два раза шире (скажем, 64 бита вместо 32), он будет записывать только в половину .

Вы можете увидеть это здесь:

int main (void) {
    uint64_t x = 0xffffffffffffffffULL;
    printf ("Enter your number: ");
    scanf ("%d", &x);     // signed int
    printf ("%llu\n", x); // unsigned long long
    return 0;
}

, который выводит -4294967295 при вводе 1 (потому что он не коснулся другой половины переменной, которая по-прежнему заполнена 1-битами).

Если вы измените строку формата scanf на %llu, она будет работать нормально.

Имейте в виду, что это только потому, что мои unsigned long long значения имеют ширину 64 бита, как и мои unit64_t. Для переносимости вы должны использовать макросы спецификатора формата, расположенные в inttypes.h. Для uint64_t правильным будет SCNu64. Имена макросов формируются с помощью:

  • PRI для строк формата printf или SCN для строк формата scanf.
  • d, i, o, u, x или X для указания десятичного знака со знаком (d и i), восьмеричного знака без знака, десятичного знака без знака, нижнего регистра без знака шестнадцатеричный и беззнаковый верхний регистр шестнадцатеричный.
  • необязательно LEAST, FAST, MAX или PTR для различных типов переменных.
  • N это размер бита.

SCNu64 расширяется до "llu" в моей реализации, но это не всегда так везде. В системе с 64-битным int и 256-битным long long он, скорее всего, будет "u" (поскольку он равен unsigned int).

Пример кода, показывающего, как использовать эти строки формата, показан ниже:

#include <stdio.h>
#include <inttypes.h>

int main (void) {
    uint64_t x = 0xffffffffffffffffULL;
    printf ("Enter your number: ");
    scanf ("%" SCNu64, &x);
    printf ("%" PRIu64 "\n", x);
    return 0;
}

Относительно того, почему ваш printf может распечатать уменьшенное значение, см. Этот код:

#include <stdio.h>
#include <inttypes.h>

int main (void) {
    uint64_t x = 0xffffffffffffffffULL;
    printf ("Enter your number: ");
    scanf ("%u", &x);
    printf ("uint64_t = %" PRIu64 "\n", x);
    printf ("uint64_t = %" PRIu64 " (when and'ed)\n", x & 0xffffffffU);
    printf ("uint     = %u\n", x);
    return 0;
}

который выводит:

Enter your number: 5
uint64_t = 18446744069414584325
uint64_t = 5 (when and'ed)
uint     = 5

Я подозреваю, что вы печатаете его также с форматной строкой меньшего размера. Когда вы делаете это, это на самом деле проблема выравнивания. Поскольку ваш процессор имеет младший порядок, он работает случайно (первые 32 бита 64-битного значения являются младшими значащими битами, 5 в приведенном выше примере).

Но он заполняет любые аргументы после , которые указывают в вашем printf, потому что вы поместили 64 бита в стек, а printf потребляет только 32, следовательно, смещение.

См. здесь и здесь для более ранних ответов, объясняющих, как это работает (или, вернее, не работает).

2 голосов
/ 11 августа 2011

аргументы a и b поменялись местами ??

 function(0xcd32ab00 ,1 ,2);

должно быть

 function(1, 0xcd32ab00 ,2);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...