- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我已经阅读了多个关于位域的类似主题,但我对它的理解还不够,所以我无法使用它。这是我的问题。我有这个 struct R
:
struct R{
unsigned int opcode: 6;
unsigned int rs: 5;
unsigned int rt: 5;
unsigned int rd: 5;
unsigned int shamt: 5;
unsigned int funct: 6;
};
我使用位字段来定义我的结构是 32 位数据。对于那些想知道的人来说,这个结构代表了一个R类型的MIPS
指令。
我想要的是将该数据写入名为 result
的文件中,为此我使用了以下代码:
struct R test = {32,0,11,21,19,0}
FILE *fp = fopen("./result", "rb");
fwrite(&test,sizeof(test),1,result);
使用这段代码,如果我运行到控制台 xxd -b result
,我希望看到这个:
00000000: 00100000 01011000 01110101 00000010
相反我得到
00000000: 00100000 10100000 01110011 00000001
我猜是fwrite
的问题,但我不太明白。
这是为了家庭作业,所以我想到了一个替代方案:
char sequence[32]
,其索引模拟 1 位。struct R{
char opcode[6];
char rs[5];
char rt[5];
char rd[5];
char shamt[5];
char funct[6];
};
00100000
给出 0x20
。putc
写入我的文件。我的选择很长,所以有没有办法直接做,或者有其他我应该知道的选择吗?
最佳答案
正如我在评论中指出的那样,
Bit-fields are an exasperating part of the C standard. Most aspects of their behaviour is implementation-defined. In particular, the mapping of different fields within a unit is implementation-defined, so whether
opcode
field occupies the most significant 6 bits or the least significant 6 bits is implementation defined.
参见 C11 §6.7.2.1 Structure and union specifiers , 特别是 ¶10继续。
C 标准没有规定位域的布局;它只是说实现必须记录它所做的事情。如果你发现当 opcode
首先列出,它进入最低有效位,然后就这样;这就是你的编译器所做的。如果你想要它在最高有效位,你可能需要将它移动到结构的另一端(并且也需要颠倒其他字段的顺序)。它完全依赖于编译器——尽管编译器可能会符合平台 ABI。请参阅关于 Implementation defined behaviour: Structures, unions, enumerations, and bit-fields 的 GCC 文档, 例如。 GCC 在某些地方引用(并遵从)平台 ABI .您可以通过 Google 找到 ABI 信息——您找到的内容不一定非常可读,但信息就在那里。
这是一些基于您的结构的代码(以及一些二进制数字格式化代码):
#include <stdio.h>
#include <assert.h>
static
void format_binary8v(unsigned char x, int n, char buffer[static 9])
{
assert(n > 0 && n <= 8);
int start = 1 << (n - 1);
for (int b = start; b != 0; b /= 2)
{
*buffer++ = ((b & x) != 0) ? '1' : '0';
x &= ~b;
}
*buffer = '\0';
}
static
void format_binary32(unsigned int x, char buffer[static 33])
{
for (unsigned b = 2147483648; b != 0; b /= 2)
{
*buffer++ = ((b & x) != 0) ? '1' : '0';
x &= ~b;
}
*buffer = '\0';
}
struct R
{
unsigned int opcode : 6;
unsigned int rs : 5;
unsigned int rt : 5;
unsigned int rd : 5;
unsigned int shamt : 5;
unsigned int funct : 6;
};
static void dump_R(const char *tag, struct R r)
{
union X
{
struct R r;
unsigned int i;
};
printf("%s:\n", tag);
union X x = { .r = r };
char buffer[33];
format_binary32(x.i, buffer);
printf("Binary: %s\n", buffer);
format_binary8v(x.r.opcode, 6, buffer);
printf(" - opcode: %s\n", buffer);
format_binary8v(x.r.rs, 5, buffer);
printf(" - rs: %s\n", buffer);
format_binary8v(x.r.rt, 5, buffer);
printf(" - rt: %s\n", buffer);
format_binary8v(x.r.rd, 5, buffer);
printf(" - rd: %s\n", buffer);
format_binary8v(x.r.shamt, 5, buffer);
printf(" - shamt: %s\n", buffer);
format_binary8v(x.r.funct, 6, buffer);
printf(" - funct: %s\n", buffer);
}
int main(void)
{
char filename[] = "filename.bin";
FILE *fp = fopen(filename, "w+b");
if (fp == NULL)
{
fprintf(stderr, "failed to open file '%s' for reading and writing\n", filename);
return 1;
}
//struct R test = {32, 0, 11, 21, 19, 0};
struct R test = { 32, 7, 11, 21, 19, 3 };
fwrite(&test, sizeof(test), 1, fp);
dump_R("test - after write", test);
rewind(fp);
fread(&test, sizeof(test), 1, fp);
dump_R("test - after read", test);
fclose(fp);
return 0;
}
在运行 macOS 10.14.5 Mojave 和 GCC 9.1.0 的 MacBook Pro 上运行时,我得到:
test - after write:
Binary: 00001110011101010101100111100000
- opcode: 100000
- rs: 00111
- rt: 01011
- rd: 10101
- shamt: 10011
- funct: 000011
test - after read:
Binary: 00001110011101010101100111100000
- opcode: 100000
- rs: 00111
- rt: 01011
- rd: 10101
- shamt: 10011
- funct: 000011
原始二进制输出文件:
$ xxd -b filename.bin
00000000: 11100000 01011001 01110101 00001110 .Yu.
$
我的解释是,在我的机器上,opcode
的数据bit-field在存储单元的最低6位,数据为funct
bit-field 在最高 6 位,其他元素在中间。查看 32 位值时,这一点很明显。一路xxd -b
拆分它需要更多解释:
opcode
的所有 6 位最低有效位;它包含 rs
的两个最低有效位也是最高有效位。rs
的三个最高有效位作为其最低有效位,以及来自 rt
的所有 5 位作为其最重要的位。rd
的所有 5 位在其最低有效位和 shamt
的 3 个最低有效位中在其最高有效位。shamt
的 2 个最重要位在其最低有效位,以及所有 6 位 funct
在其最高有效位。这一切都有点令人兴奋!
当我恢复您对 test
的值时结构 ( struct R test = {32, 0, 11, 21, 19, 0};
),我得到:
test - after write:
Binary: 00000010011101010101100000100000
- opcode: 100000
- rs: 00000
- rt: 01011
- rd: 10101
- shamt: 10011
- funct: 000000
test - after read:
Binary: 00000010011101010101100000100000
- opcode: 100000
- rs: 00000
- rt: 01011
- rd: 10101
- shamt: 10011
- funct: 000000
和
00000000: 00100000 01011000 01110101 00000010 Xu.
您的硬件和/或编译器与我的不同;它可能有不同的位域布局规则。
请注意,此代码假设 unsigned
未经测试或 unsigned int
是一个 32 位的量。如果您使用的系统不适用,则需要修改代码以使用类似 uint32_t
的类型。和 uint8_t
等,如 <stdint.h>
中所见(以及在 <inttypes.h>
中找到的格式说明符)。
与原始代码相比,此代码以各种方式组织得更好。
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct R
{
unsigned int opcode : 6;
unsigned int rs : 5;
unsigned int rt : 5;
unsigned int rd : 5;
unsigned int shamt : 5;
unsigned int funct : 6;
};
static void test_r(const char *tag, struct R r, FILE *fp);
static void run_xxd(const char *file);
int main(void)
{
char filename[] = "filename.bin";
FILE *fp = fopen(filename, "w+b");
if (fp == NULL)
{
fprintf(stderr, "failed to open file '%s' for reading and writing\n", filename);
return 1;
}
struct R r[] =
{
{ 32, 0, 11, 21, 19, 0 },
{ 32, 7, 11, 21, 19, 3 },
{ 6, 21, 10, 14, 10, 8 },
};
enum { NUM_R = sizeof(r) / sizeof(r[0]) };
for (int i = 0; i < NUM_R; i++)
{
char name[16];
snprintf(name, sizeof(name), "r%d", i+1);
test_r(name, r[i], fp);
}
fclose(fp);
run_xxd(filename);
return 0;
}
static void run_one_xxd(const char *command, const char *filename)
{
char cmd[256];
snprintf(cmd, sizeof(cmd), "%s %s", command, filename);
printf("\nCommand: %s\n", cmd);
fflush(stdout);
system(cmd);
putchar('\n');
}
static void run_xxd(const char *filename)
{
run_one_xxd("xxd -c 4 -b ", filename);
run_one_xxd("xxd -c 4 -g 1 -u", filename);
}
static void format_binary8v(unsigned char x, int n, char buffer[static 9]);
static void format_binary32(unsigned x, char buffer[static 33]);
static void dump_bitfield(int nbits, unsigned value, const char *name);
static void dump_bytes(const char *tag, struct R r);
static void dump_R(const char *tag, struct R r);
static void test_r(const char *tag, struct R r, FILE *fp)
{
char buffer[32];
long offset = sizeof(struct R);
putchar('\n');
fwrite(&r, sizeof(r), 1, fp);
snprintf(buffer, sizeof(buffer), "%s - after write", tag);
dump_R(buffer, r);
fseek(fp, -offset, SEEK_CUR);
struct R s;
fread(&s, sizeof(s), 1, fp);
fseek(fp, 0, SEEK_CUR); // Ready for reading or writing!
snprintf(buffer, sizeof(buffer), "%s - after read", tag);
dump_R(buffer, s);
/* Safe regardless of whether struct R uses all bits in its storage unit */
assert(r.opcode == s.opcode);
assert(r.rs == s.rs );
assert(r.rs == s.rs );
assert(r.rs == s.rs );
assert(r.shamt == s.shamt );
assert(r.funct == s.funct );
/* Only safe because struct R uses all bits of its storage unit */
assert(memcmp(&r, &s, sizeof(struct R)) == 0);
}
static void dump_R(const char *tag, struct R r)
{
printf("%s:\n", tag);
dump_bytes("Binary", r);
dump_bitfield(6, r.opcode, "opcode");
dump_bitfield(5, r.rs, "rs");
dump_bitfield(5, r.rt, "rt");
dump_bitfield(5, r.rd, "rd");
dump_bitfield(5, r.shamt, "shamt");
dump_bitfield(6, r.funct, "funct");
}
static void dump_bytes(const char *tag, struct R r)
{
union X
{
struct R r;
unsigned i;
};
union X x = { .r = r };
char buffer[33];
printf("%s: 0x%.8X\n", tag, x.i);
format_binary32(x.i, buffer);
//printf("%s: MSB %s LSB\n", tag, buffer);
printf("%s: MSB", tag);
for (int i = 0; i < 4; i++)
printf(" %.8s", &buffer[8 * i]);
puts(" LSB (big-endian)");
printf("%s: LSB", tag);
for (int i = 0; i < 4; i++)
printf(" %.8s", &buffer[8 * (3 - i)]);
puts(" MSB (little-endian)");
}
static void dump_bitfield(int nbits, unsigned value, const char *name)
{
assert(nbits > 0 && nbits <= 32);
char vbuffer[33];
char nbuffer[8];
snprintf(nbuffer, sizeof(nbuffer), "%s:", name);
format_binary8v(value, nbits, vbuffer);
printf(" - %-7s %6s (%u)\n", nbuffer, vbuffer, value);
}
static
void format_binary8v(unsigned char x, int n, char buffer[static 9])
{
assert(n > 0 && n <= 8);
int start = 1 << (n - 1);
for (int b = start; b != 0; b /= 2)
{
*buffer++ = ((b & x) != 0) ? '1' : '0';
x &= ~b;
}
*buffer = '\0';
}
static
void format_binary32(unsigned x, char buffer[static 33])
{
for (unsigned b = 2147483648; b != 0; b /= 2)
{
*buffer++ = ((b & x) != 0) ? '1' : '0';
x &= ~b;
}
*buffer = '\0';
}
它产生输出:
r1 - after write:
Binary: 0x02755820
Binary: MSB 00000010 01110101 01011000 00100000 LSB (big-endian)
Binary: LSB 00100000 01011000 01110101 00000010 MSB (little-endian)
- opcode: 100000 (32)
- rs: 00000 (0)
- rt: 01011 (11)
- rd: 10101 (21)
- shamt: 10011 (19)
- funct: 000000 (0)
r1 - after read:
Binary: 0x02755820
Binary: MSB 00000010 01110101 01011000 00100000 LSB (big-endian)
Binary: LSB 00100000 01011000 01110101 00000010 MSB (little-endian)
- opcode: 100000 (32)
- rs: 00000 (0)
- rt: 01011 (11)
- rd: 10101 (21)
- shamt: 10011 (19)
- funct: 000000 (0)
r2 - after write:
Binary: 0x0E7559E0
Binary: MSB 00001110 01110101 01011001 11100000 LSB (big-endian)
Binary: LSB 11100000 01011001 01110101 00001110 MSB (little-endian)
- opcode: 100000 (32)
- rs: 00111 (7)
- rt: 01011 (11)
- rd: 10101 (21)
- shamt: 10011 (19)
- funct: 000011 (3)
r2 - after read:
Binary: 0x0E7559E0
Binary: MSB 00001110 01110101 01011001 11100000 LSB (big-endian)
Binary: LSB 11100000 01011001 01110101 00001110 MSB (little-endian)
- opcode: 100000 (32)
- rs: 00111 (7)
- rt: 01011 (11)
- rd: 10101 (21)
- shamt: 10011 (19)
- funct: 000011 (3)
r3 - after write:
Binary: 0x214E5546
Binary: MSB 00100001 01001110 01010101 01000110 LSB (big-endian)
Binary: LSB 01000110 01010101 01001110 00100001 MSB (little-endian)
- opcode: 000110 (6)
- rs: 10101 (21)
- rt: 01010 (10)
- rd: 01110 (14)
- shamt: 01010 (10)
- funct: 001000 (8)
r3 - after read:
Binary: 0x214E5546
Binary: MSB 00100001 01001110 01010101 01000110 LSB (big-endian)
Binary: LSB 01000110 01010101 01001110 00100001 MSB (little-endian)
- opcode: 000110 (6)
- rs: 10101 (21)
- rt: 01010 (10)
- rd: 01110 (14)
- shamt: 01010 (10)
- funct: 001000 (8)
Command: xxd -c 4 -b filename.bin
00000000: 00100000 01011000 01110101 00000010 Xu.
00000004: 11100000 01011001 01110101 00001110 .Yu.
00000008: 01000110 01010101 01001110 00100001 FUN!
Command: xxd -c 4 -g 1 -u filename.bin
00000000: 20 58 75 02 Xu.
00000004: E0 59 75 0E .Yu.
00000008: 46 55 4E 21 FUN!
关于c - 使用位字段在新的二进制文件中写入自定义的 n 位数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56621360/
好的,所以我编辑了以下... 只需将以下内容放入我的 custom.css #rt-utility .rt-block {CODE HERE} 但是当我尝试改变... 与 #rt-sideslid
在表格 View 中,我有一个自定义单元格(在界面生成器中高度为 500)。在该单元格中,我有一个 Collection View ,我按 (10,10,10,10) 固定到边缘。但是在 tablev
对于我的无能,我很抱歉,但总的来说,我对 Cocoa、Swift 和面向对象编程还很陌生。我的主要来源是《Cocoa Programming for OS X》(第 5 版),以及 Apple 的充满
我正在使用 meta-tegra 为我的 NVIDIA Jetson Nano 构建自定义图像。我需要 PyTorch,但没有它的配方。我在设备上构建了 PyTorch,并将其打包到设备上的轮子中。现
在 jquery 中使用 $.POST 和 $.GET 时,有没有办法将自定义变量添加到 URL 并发送它们?我尝试了以下方法: $.ajax({type:"POST", url:"file.php?
Traefik 已经默认实现了很多中间件,可以满足大部分我们日常的需求,但是在实际工作中,用户仍然还是有自定义中间件的需求,为解决这个问题,官方推出了一个 Traefik Pilot[1] 的功
我想让我的 CustomTextInputLayout 将 Widget.MaterialComponents.TextInputLayout.OutlinedBox 作为默认样式,无需在 XML 中
我在 ~/.emacs 中有以下自定义函数: (defun xi-rgrep (term) (grep-compute-defaults) (interactive "sSearch Te
我有下表: 考虑到每个月的权重,我的目标是在 5 个月内分散 10,000 个单位。与 10,000 相邻的行是我最好的尝试(我在这上面花了几个小时)。黄色是我所追求的。 我试图用来计算的逻辑如下:计
我的表单中有一个字段,它是文件类型。当用户点击保存图标时,我想自然地将文件上传到服务器并将文件名保存在数据库中。我尝试通过回显文件名来测试它,但它似乎不起作用。另外,如何将文件名添加到数据库中?是在模
我有一个 python 脚本来发送电子邮件,它工作得很好,但问题是当我检查我的电子邮件收件箱时。 我希望该用户名是自定义用户名,而不是整个电子邮件地址。 最佳答案 发件人地址应该使用的格式是: You
我想减小 ggcorrplot 中标记的大小,并减少文本和绘图之间的空间。 library(ggcorrplot) data(mtcars) corr <- round(cor(mtcars), 1)
GTK+ noob 问题在这里: 是否可以自定义 GtkFileChooserButton 或 GtkFileChooserDialog 以删除“位置”部分(左侧)和顶部的“位置”输入框? 我实际上要
我正在尝试在主页上使用 ajax 在 magento 中使用 ajax 显示流行的产品列表,我可以为 5 或“N”个产品执行此操作,但我想要的是将分页工具栏与结果集一起添加. 这是我添加的以显示流行产
我正在尝试使用 PasswordResetForm 内置函数。 由于我想要自定义表单字段,因此我编写了自己的表单: class FpasswordForm(PasswordResetForm):
据我了解,新的 Angular 7 提供了拖放功能。我搜索了有关 DnD 的 Tree 组件,但没有找到与树相关的内容。 我在 Stackblitz 上找到的一个工作示例.对比drag'ndrop功能
我必须开发一个自定义选项卡控件并决定使用 WPF/XAML 创建它,因为我无论如何都打算学习它。完成后应该是这样的: 到目前为止,我取得了很好的进展,但还有两个问题: 只有第一个/最后一个标签项应该有
我要定制xtable用于导出到 LaTeX。我知道有些问题是关于 xtable在这里,但我找不到我要找的具体东西。 以下是我的表的外观示例: my.table <- data.frame(Specif
用ejs在这里显示日期 它给我结果 Tue Feb 02 2016 16:02:24 GMT+0530 (IST) 但是我需要表现为 19th January, 2016 如何在ejs中执行此操作?
我想问在 JavaFX 中使用自定义对象制作 ListView 的最佳方法,我想要一个每个项目如下所示的列表: 我搜了一下,发现大部分人都是用细胞工厂的方法来做的。有没有其他办法?例如使用客户 fxm
我是一名优秀的程序员,十分优秀!