需要帮助理解在 C 中将双精度数转换为二进制数的代码
Need help understanding code converting doubles to binary in C
所以下面是一些代码,我用它来了解如何在 C 中获取双精度二进制数,但是代码的某些区域对我来说没有意义,我尝试使用 print 语句来提供帮助我但无济于事
#include <stdio.h>
#include <string.h>
#include <limits.h>
void double_to_bits(double val);
int main(void)
{
unsigned idx;
double vals[] = { 10 };
for (idx = 0; idx < 4; idx++ ) {
printf("\nvals[%u]= %+lf-->>", idx, vals[idx] );
double_to_bits(vals[idx] );
}
printf("\n");
return 0;
}
void double_to_bits(double val)
{
unsigned idx;
unsigned char arr[sizeof val];
memcpy (arr, &val, sizeof val);
printf("array is : %s\n", arr);
for (idx=CHAR_BIT * sizeof val; idx-- ; ) {
putc(
( arr[idx/CHAR_BIT] & (1u << (idx%CHAR_BIT) ) )
? '1'
: '0'
, stdout
);
}
}
arr[idx/CHAR_BIT] return 是什么意思?我知道如果 idx = 63 那么我们得到 arr[7] 但在打印语句中这些似乎只是给出随机整数值 .
还有为什么arr[idx/CHAR_BIT]和(1u%CHAR_BIT)之间的&操作数会给出2个奇怪的字符符号? & 操作数如何作用于这两个值?
感谢您的宝贵时间和帮助。
此代码定义 vals
有一个元素:
double vals[] = { 10 };
此代码使用 vals
就好像它有四个元素:
for (idx = 0; idx < 4; idx++ ) {
printf("\nvals[%u]= %+lf-->>", idx, vals[idx] );
double_to_bits(vals[idx] );
}
正因为如此,程序的行为并没有被C标准定义,不同的编译器会做不同的事情。您没有向我们展示您得到的输出,因此我们无法分析您的编译器做了什么。我的似乎认为,由于 vals
只有一个元素,它永远不需要计算 vals[idx]
中 idx
的值;它总是可以使用 vals[0]
。因此每次迭代都对值 10 进行操作。您的编译器可能已从数组外部的内存加载并使用了不同的值。
What does arr[idx/CHAR_BIT] return?
CHAR_BIT
在<limits.h>
中定义为一个字节中的位数。由于 unsigned char arr[sizeof val];
的定义,arr
是一个数组,其元素(每个字节)与 double
中的字节数一样多。因此,例如,如果一个字节有 8 位,double
有 8 个字节,那么 arr
有 8 个 8 位元素,总共 64 位。
使用这些示例数字,for
循环迭代 idx
从 63 到 0 的数字。然后代码使用 idx
作为 [=21] 中的位的计数器=].表达式 idx/CHAR_BIT
找出数组的哪个元素包含编号为 idx
的位:每个数组元素有 CHAR_BIT
位,位 0-7(当 CHAR_BIT
为 8 时)是在元素 0 中,第 8-15 位在元素 1 中,第 16-23 位在元素 2 中,依此类推。因此,将 idx
除以 CHAR_BIT
并截断为整数(这是 /
运算符对整数操作数所做的)给出数组元素的索引,该数组元素的位为 idx
.
然后 arr[idx/CHAR_BIT]
获取该元素。然后我们需要从该元素中挑选出单个位。 idx%CHAR_BIT
取 idx
除以 CHAR_BIT
的余数,因此它给出了一个字节中的一位数。然后 1u << (idx%CHAR_BIT)
按该数字移动 1。结果是一个数字,当以二进制表示时,该数字的位为 1,其他位为 0。
然后 &
运算符将其与数组元素进行 AND 运算。如果数组元素在 1 移至的位置有 0,则结果为零。如果数组元素有一个 1,其中 1 已被移至,结果是该位(仍在其位置)。
然后 ? '1' : '0;'
使用 AND 的结果 select 字符“1”(如果结果不为零)或字符“0”(如果结果为零) .该字符被传递给 putc
进行打印。
I understand say if idx = 63 then we get arr[7] but in print statements these seem to just give random integer values .
当上述数组边界问题得到纠正并且 double_to_bits
传递了一个有效值时,它应该打印编码 double
值的位。在大多数 C 实现中,这将是 01000000001001000000000000000000000000000000000000000000000000000,这是 IEEE-754 二进制 64 格式的编码,也称为双精度。
Also why does the & operand between arr[idx/CHAR_BIT] and (1u%CHAR_BIT) give 2 weird character symbols?
您没有显示奇怪的字符符号或其他输出,因此我们没有可解释的输出。
语句 printf("array is : %s\n", arr);
打印 arr
就好像它是包含可打印字符的字符串一样,但它用于包含“原始二进制数据”,因此您不应期望该数据会导致打印时有意义的字符。删除该声明。此外,您的程序越界访问 vals
这一事实可能会导致输出出现其他问题。
所以下面是一些代码,我用它来了解如何在 C 中获取双精度二进制数,但是代码的某些区域对我来说没有意义,我尝试使用 print 语句来提供帮助我但无济于事
#include <stdio.h>
#include <string.h>
#include <limits.h>
void double_to_bits(double val);
int main(void)
{
unsigned idx;
double vals[] = { 10 };
for (idx = 0; idx < 4; idx++ ) {
printf("\nvals[%u]= %+lf-->>", idx, vals[idx] );
double_to_bits(vals[idx] );
}
printf("\n");
return 0;
}
void double_to_bits(double val)
{
unsigned idx;
unsigned char arr[sizeof val];
memcpy (arr, &val, sizeof val);
printf("array is : %s\n", arr);
for (idx=CHAR_BIT * sizeof val; idx-- ; ) {
putc(
( arr[idx/CHAR_BIT] & (1u << (idx%CHAR_BIT) ) )
? '1'
: '0'
, stdout
);
}
}
arr[idx/CHAR_BIT] return 是什么意思?我知道如果 idx = 63 那么我们得到 arr[7] 但在打印语句中这些似乎只是给出随机整数值 .
还有为什么arr[idx/CHAR_BIT]和(1u%CHAR_BIT)之间的&操作数会给出2个奇怪的字符符号? & 操作数如何作用于这两个值?
感谢您的宝贵时间和帮助。
此代码定义 vals
有一个元素:
double vals[] = { 10 };
此代码使用 vals
就好像它有四个元素:
for (idx = 0; idx < 4; idx++ ) {
printf("\nvals[%u]= %+lf-->>", idx, vals[idx] );
double_to_bits(vals[idx] );
}
正因为如此,程序的行为并没有被C标准定义,不同的编译器会做不同的事情。您没有向我们展示您得到的输出,因此我们无法分析您的编译器做了什么。我的似乎认为,由于 vals
只有一个元素,它永远不需要计算 vals[idx]
中 idx
的值;它总是可以使用 vals[0]
。因此每次迭代都对值 10 进行操作。您的编译器可能已从数组外部的内存加载并使用了不同的值。
What does arr[idx/CHAR_BIT] return?
CHAR_BIT
在<limits.h>
中定义为一个字节中的位数。由于 unsigned char arr[sizeof val];
的定义,arr
是一个数组,其元素(每个字节)与 double
中的字节数一样多。因此,例如,如果一个字节有 8 位,double
有 8 个字节,那么 arr
有 8 个 8 位元素,总共 64 位。
使用这些示例数字,for
循环迭代 idx
从 63 到 0 的数字。然后代码使用 idx
作为 [=21] 中的位的计数器=].表达式 idx/CHAR_BIT
找出数组的哪个元素包含编号为 idx
的位:每个数组元素有 CHAR_BIT
位,位 0-7(当 CHAR_BIT
为 8 时)是在元素 0 中,第 8-15 位在元素 1 中,第 16-23 位在元素 2 中,依此类推。因此,将 idx
除以 CHAR_BIT
并截断为整数(这是 /
运算符对整数操作数所做的)给出数组元素的索引,该数组元素的位为 idx
.
然后 arr[idx/CHAR_BIT]
获取该元素。然后我们需要从该元素中挑选出单个位。 idx%CHAR_BIT
取 idx
除以 CHAR_BIT
的余数,因此它给出了一个字节中的一位数。然后 1u << (idx%CHAR_BIT)
按该数字移动 1。结果是一个数字,当以二进制表示时,该数字的位为 1,其他位为 0。
然后 &
运算符将其与数组元素进行 AND 运算。如果数组元素在 1 移至的位置有 0,则结果为零。如果数组元素有一个 1,其中 1 已被移至,结果是该位(仍在其位置)。
然后 ? '1' : '0;'
使用 AND 的结果 select 字符“1”(如果结果不为零)或字符“0”(如果结果为零) .该字符被传递给 putc
进行打印。
I understand say if idx = 63 then we get arr[7] but in print statements these seem to just give random integer values .
当上述数组边界问题得到纠正并且 double_to_bits
传递了一个有效值时,它应该打印编码 double
值的位。在大多数 C 实现中,这将是 01000000001001000000000000000000000000000000000000000000000000000,这是 IEEE-754 二进制 64 格式的编码,也称为双精度。
Also why does the & operand between arr[idx/CHAR_BIT] and (1u%CHAR_BIT) give 2 weird character symbols?
您没有显示奇怪的字符符号或其他输出,因此我们没有可解释的输出。
语句 printf("array is : %s\n", arr);
打印 arr
就好像它是包含可打印字符的字符串一样,但它用于包含“原始二进制数据”,因此您不应期望该数据会导致打印时有意义的字符。删除该声明。此外,您的程序越界访问 vals
这一事实可能会导致输出出现其他问题。