将 unsigned int 传递给函数是否会使它丢失位?

Does passing an unsigned int to a function make it lose bits?

我的问题与 here 的问题非常相似,只是我使用的是 C。

我写了一些代码来旋转一个无符号整数;也就是说,函数 bitRotate()(下面的代码)。

当我直接输入要使用的文字而不是 printfs 和 scanfs 时,该函数运行良好,例如bitRotate(0xabcdef00,8);在主函数中。

但是,当我像下面的代码一样将 x 作为参数传递时,即从用户那里获取的 abcdef00,x 被损坏为 ab000000。我检查并仔细检查并调试了我的代码多次,我很确定错误出在这部分,但我不明白为什么。

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define WIDTH sizeof(unsigned int)*CHAR_BIT

unsigned int bitRotate(unsigned int, char );

int main()
{

    unsigned int x;
    char n;
    while(1)
    {
        printf("Enter x: ");
        scanf("%x", &x);
        printf("Enter n: ");
        scanf("%d", &n);
        printf("%x\n", bitRotate(x,n));
    }

    return 0;
}

unsigned int bitRotate(unsigned int value, char n)
{

    char un = abs(n);
    unsigned int fallen = ~(0u);

    if(un == WIDTH)
        return value;
    else if (un < WIDTH)
    {

        if (n < 0)
        {
            fallen >>= (WIDTH - n);
            fallen = value & fallen;
            fallen <<= (WIDTH - n);
            value >>= n;
        }
        else
        {
            fallen <<= (WIDTH - n);
            fallen = value & fallen;
            fallen >>= (WIDTH - n);
            value <<= n;
        }
        value |= fallen;
        return value;

    }
    else
        return 0;

}

bitRotate 函数很好,您调用它的方式也很好。

真正的罪魁祸首在这里:

char n;
scanf("%d", &n);  // <<<<<

您向 scanf 提供了错误的格式说明符,这会导致未定义的行为。您的编译器很可能警告过您。

%d 格式说明符需要一个指向 int 的指针(通常需要 32 位),但是您提供了指向 char 的指针,它需要 8 位。因此 scanf 很可能会破坏与 n 地址相邻的内存。

你想要这个:

int n;
scanf("%d", &n);

您的代码有未定义的行为。

在本次通话中

scanf("%d", &n);

您对 char 类型的对象使用了错误的转换说明符。此外,类型 char 可以表现为 signed charunsigned char,具体取决于编译器选项。

函数中当 n 为负数时使用了错误的表达式

fallen >>= (WIDTH - n);
                 ^^^
fallen <<= (WIDTH - n);
                 ^^^

我想你是说

fallen >>= (WIDTH + n);
                 ^^^
fallen <<= (WIDTH + n);
                 ^^^

无论如何,函数可以写得更简单。这是一个演示程序。

#include <stdio.h>
#include <limits.h>

unsigned int bitRotate(unsigned int value, int n )
{
    const int Width = sizeof( unsigned int ) * CHAR_BIT;

    n %= Width;

    if ( n < 0 )
    {
        value = ( value >> -n ) | ( value << ( Width + n ) );
    }
    else if ( n > 0 )
    {
        value = ( value << n ) | ( value >> ( Width - n ) );

    }

    return value;
}

int main(void) 
{
    while ( 1 )
    {
        unsigned int x;

        printf( "Enter a hexadecimal value of x (0 - exit): " );

        if ( scanf( "%x", &x ) != 1 || x == 0 ) break;

        int n;

        printf( "Enter a negative or positive value of n (0 - exit): " );
        if ( scanf( "%d", &n ) != 1 || n == 0 ) break;

        printf( "\n%#x shifted %d is %#x\n", x, n, bitRotate( x, n ) );
    }

    return 0;
}

它的输出可能看起来像

Enter a hexadecimal value of x (0 - exit): 0xabcdef00
Enter a negative or positive value of n (0 - exit): 16

0xabcdef00 shifted 16 is 0xef00abcd

Enter a hexadecimal value of x (0 - exit): 0xabcdef00
Enter a negative or positive value of n (0 - exit): -16

0xabcdef00 shifted -16 is 0xef00abcd

Enter a hexadecimal value of x (0 - exit): 0xabcdef00
Enter a negative or positive value of n (0 - exit): 32

0xabcdef00 shifted 16 is 0xabcdef00

Enter a hexadecimal value of x (0 - exit): 0

此代码显示该值是否有符号位:

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

int main(void) {
    const int arr[7] = {0x80000000u, -2, -1, 0, 1, 2, 0x7fffffffu};
    unsigned int i, j, signVal, uiSiz;

    uiSiz = sizeof(unsigned int);

    for (i = 0, j = 7; i < 7; i++) {
        signVal = ((unsigned int) arr[i] & (0x1u << ((8 * uiSiz) - 1))) >> ((8 * uiSiz) - 1);
        fprintf(stdout, "arr[%u]: %i, uiSiz: %u, signVal: %u;\n", i, arr[i], uiSiz, signVal);
    }

    return 0;
}

LINK@[https://ideone.com/rWiSrF]