将 unsigned int 传递给函数是否会使它丢失位?
Does passing an unsigned int to a function make it lose bits?
我的问题与 here 的问题非常相似,只是我使用的是 C。
我写了一些代码来旋转一个无符号整数;也就是说,函数 bitRotate()
(下面的代码)。
当我直接输入要使用的文字而不是 printf
s 和 scanf
s 时,该函数运行良好,例如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 char
或 unsigned 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]
我的问题与 here 的问题非常相似,只是我使用的是 C。
我写了一些代码来旋转一个无符号整数;也就是说,函数 bitRotate()
(下面的代码)。
当我直接输入要使用的文字而不是 printf
s 和 scanf
s 时,该函数运行良好,例如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 char
或 unsigned 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]