变量值在结构赋值后打印和没有结构赋值打印时是不同的
A variable value is different when it is printed after structural assignment and when printed without the structural assignment
我不知道如何用合适的标题来说明问题。因此,如果您有更丰富的标题要编辑,请随意。
为了理解这个问题,让我解释一下我在做什么。
我创建了一个结构如下:
typedef union __attribute__ ((__packed__)) adcs_measurements_t
{
unsigned char raw[72];
struct __attribute__ ((__packed__)) //191
{
int magneticFieldX : 16;
int magneticFieldY : 16;
int magneticFieldZ : 16;
int coarseSunX : 16;
int coarseSunY : 16;
int coarseSunZ : 16;
int sunX : 16;
int sunY : 16;
int sunZ : 16;
int nadirX : 16;
int nadirY : 16;
int nadirZ : 16;
int XAngularRate : 16;
int YAngularRate : 16;
int ZAngularRate : 16;
int XWheelSpeed : 16;
int YWheelSpeed : 16;
int ZWheelSpeed : 16;
int star1BX : 16;
int star1BY : 16;
int star1BZ : 16;
int star1OX : 16;
int star1OY : 16;
int star1OZ : 16;
int star2BX : 16;
int star2BY : 16;
int star2BZ : 16;
int star2OX : 16;
int star2OY : 16;
int star2OZ : 16;
int star3BX : 16;
int star3BY : 16;
int star3BZ : 16;
int star3OX : 16;
int star3OY : 16;
int star3OZ : 16;
} fields;
} adcs_measurements_t;
我通过调用如下函数来填充结构:
void adcsTM191_measurements(adcs_measurements_t* dataOut)
{
int pass;
unsigned char TMID = 191;
unsigned char readBuff[72] = {0};
pass = I2C_write(ADCS_ADDR, &TMID, 1);
if(pass != 0)
{
printf("write error %d\n", pass);
}
pass = I2C_read(ADCS_ADDR, readBuff, 72);
if(pass != 0)
{
printf("read error %d\n", pass);
}
dataOut->fields.magneticFieldX = (readBuff[1] & 0x00FF) << 8 | (readBuff[0] & 0x00FF);
dataOut->fields.magneticFieldY = (readBuff[3] & 0x00FF) << 8 | (readBuff[2] & 0x00FF);
dataOut->fields.magneticFieldZ = (readBuff[5] & 0x00FF) << 8 | (readBuff[4] & 0x00FF);
dataOut->fields.coarseSunX = (readBuff[7] & 0x00FF) << 8 | (readBuff[6] & 0x00FF);
dataOut->fields.coarseSunY = (readBuff[9] & 0x00FF) << 8 | (readBuff[8] & 0x00FF);
dataOut->fields.coarseSunZ = (readBuff[11] & 0x00FF) << 8 | (readBuff[10] & 0x00FF);
dataOut->fields.sunX = (readBuff[13] & 0x00FF) << 8 | (readBuff[12] & 0x00FF);
dataOut->fields.sunY = (readBuff[15] & 0x00FF) << 8 | (readBuff[14] & 0x00FF);
dataOut->fields.sunZ = (readBuff[17] & 0x00FF) << 8 | (readBuff[16] & 0x00FF);
dataOut->fields.nadirX = (readBuff[19] & 0x00FF) << 8 | (readBuff[18] & 0x00FF);
dataOut->fields.nadirY = (readBuff[21] & 0x00FF) << 8 | (readBuff[20] & 0x00FF);
dataOut->fields.nadirZ = (readBuff[23] & 0x00FF) << 8 | (readBuff[22] & 0x00FF);
dataOut->fields.XAngularRate = (readBuff[25] & 0x00FF) << 8 | (readBuff[24] & 0x00FF);
dataOut->fields.YAngularRate = (readBuff[27] & 0x00FF) << 8 | (readBuff[26] & 0x00FF);
dataOut->fields.ZAngularRate = (readBuff[29] & 0x00FF) << 8 | (readBuff[28] & 0x00FF);
dataOut->fields.XWheelSpeed = (readBuff[31] & 0x00FF) << 8 | (readBuff[30] & 0x00FF);
dataOut->fields.YWheelSpeed = (readBuff[33] & 0x00FF) << 8 | (readBuff[32] & 0x00FF);
dataOut->fields.ZWheelSpeed = (readBuff[35] & 0x00FF) << 8 | (readBuff[34] & 0x00FF);
dataOut->fields.star1BX = (readBuff[37] & 0x00FF) << 8 | (readBuff[36] & 0x00FF);
dataOut->fields.star1BY = (readBuff[39] & 0x00FF) << 8 | (readBuff[38] & 0x00FF);
dataOut->fields.star1BZ = (readBuff[41] & 0x00FF) << 8 | (readBuff[40] & 0x00FF);
dataOut->fields.star1OX = (readBuff[43] & 0x00FF) << 8 | (readBuff[42] & 0x00FF);
dataOut->fields.star1OY = (readBuff[45] & 0x00FF) << 8 | (readBuff[44] & 0x00FF);
dataOut->fields.star1OZ = (readBuff[47] & 0x00FF) << 8 | (readBuff[46] & 0x00FF);
dataOut->fields.star2BX = (readBuff[49] & 0x00FF) << 8 | (readBuff[48] & 0x00FF);
dataOut->fields.star2BY = (readBuff[51] & 0x00FF) << 8 | (readBuff[50] & 0x00FF);
dataOut->fields.star2BZ = (readBuff[53] & 0x00FF) << 8 | (readBuff[52] & 0x00FF);
dataOut->fields.star2OX = (readBuff[55] & 0x00FF) << 8 | (readBuff[54] & 0x00FF);
dataOut->fields.star2OY = (readBuff[57] & 0x00FF) << 8 | (readBuff[56] & 0x00FF);
dataOut->fields.star2OZ = (readBuff[59] & 0x00FF) << 8 | (readBuff[58] & 0x00FF);
dataOut->fields.star3BX = (readBuff[61] & 0x00FF) << 8 | (readBuff[60] & 0x00FF);
dataOut->fields.star3BY = (readBuff[63] & 0x00FF) << 8 | (readBuff[62] & 0x00FF);
dataOut->fields.star3BZ = (readBuff[65] & 0x00FF) << 8 | (readBuff[64] & 0x00FF);
dataOut->fields.star3OX = (readBuff[67] & 0x00FF) << 8 | (readBuff[66] & 0x00FF);
dataOut->fields.star3OY = (readBuff[69] & 0x00FF) << 8 | (readBuff[68] & 0x00FF);
dataOut->fields.star3OZ = (readBuff[71] & 0x00FF) << 8 | (readBuff[70] & 0x00FF);
}
最后我打印出来,比如YWheelSpeed
。
adcsTM191_measurements(&temp);
printf("structure y wheel speed is: %d \n", temp.fields.YWheelSpeed);
这个值应该打印一个负值,它确实是:
structure y wheel speed is: -97
现在事情是这样的,如果我打印 (readBuff[27] & 0x00FF) << 8 | (readBuff[26] & 0x00FF)
,它对应于 Y 轮速度变量中填充的内容,adcsTM191_measurements(adcs_measurements_t* dataOut)
中的任何地方都不会打印这个负值。相反,它打印无符号字符的最大值 (65,535)。
int y = (int) (readBuff[33] & 0x00FF) << 8 | (readBuff[32] & 0x00FF);
printf("inside struct y is: %d", y);
我期望存储在结构内部会进行一种隐式转换,因此它会按预期打印负值。它是怎么做到的?如何在不使用结构的情况下打印正确的值?
您可能有 32 位 int
,因此初始化从不设置符号位。但是结构字段只有16位,在调用printf()
时转换为int
时会被符号扩展。
根据 C 2018 脚注 128,用 int
定义的位字段是有符号的还是无符号的,由实现定义。由于您的实现显示负值,推测它是有符号的,因此,作为 16 位有符号整数,它可以表示从 −32,768 到 32,767 的值。
我们还可以推断出 int
在您的实现中超过 16 位,可能是 32 位(根据事实是,在 int y
打印有“ %d”)。
考虑这个作业:
dataOut->fields.YWheelSpeed = (readBuff[33] & 0x00FF) << 8 | (readBuff[32] & 0x00FF);`
在此表达式中,readBuff[33]
和 readBuff[32]
通过 常规提升 转换为 int
。 0x00FF
也是一个 int
.
如果我们假设readBuff[33]
是255,readBufff[32]
是159(即28−97),那么表达式上的值=
的右侧是 65,439(即 216−97)。在赋值中,右操作数被转换为左操作数的类型,即 16 位有符号整数。在这种情况下,值 65,439 不能用 16 位有符号整数表示。 C 2018 6.3.1.3 3 告诉我们“要么结果是实现定义的,要么引发了实现定义的信号。”
此转换的常见实现方式是生成对 216 取模的结果,或者等效地,将 int
的 16 位低位重新解释为二进制补码16 位整数。这会产生 −97。由于您的实现随后显示了 −97 的值,因此大概这就是您的实现所做的。
因此,dataOut->fields.YWheelSpeed
被赋值为 −97。稍后打印时:
printf("structure y wheel speed is: %d \n", temp.fields.YWheelSpeed);
然后 默认参数提升 ,其中包括通常的整数提升,将 temp.fields.YWheelSpeed
从值为 −97 的有符号 16 位整数转换为 int
的值为 −97,并打印出“-97”。
相反,假设 (readBuff[33] & 0x00FF) << 8 | (readBuff[32] & 0x00FF)
打印为 %d
。正如我们在上面看到的,这个表达式的值为 65,439,因此应该打印“65439”。
问题说明:
Now here is the thing, if I print (readBuff[27] & 0x00FF) << 8 | (readBuff[26] & 0x00FF)
, which corresponds to what was populated inside the Y wheel speed variable,… it prints the maximum value of an unsigned char (65,535).
但是,(readBuff[27] & 0x00FF) << 8 | (readBuff[26] & 0x00FF)
并不是赋给YWheelSpeed
的值,推测是“Y轮速度变量”。 YWheelSpeed
是从 readBuff
元素 32 和 33 赋值的,而不是 26 和 27。因此我们不应该对打印出一些不同的值而不是 65,439 感到惊讶。
我不知道如何用合适的标题来说明问题。因此,如果您有更丰富的标题要编辑,请随意。
为了理解这个问题,让我解释一下我在做什么。
我创建了一个结构如下:
typedef union __attribute__ ((__packed__)) adcs_measurements_t
{
unsigned char raw[72];
struct __attribute__ ((__packed__)) //191
{
int magneticFieldX : 16;
int magneticFieldY : 16;
int magneticFieldZ : 16;
int coarseSunX : 16;
int coarseSunY : 16;
int coarseSunZ : 16;
int sunX : 16;
int sunY : 16;
int sunZ : 16;
int nadirX : 16;
int nadirY : 16;
int nadirZ : 16;
int XAngularRate : 16;
int YAngularRate : 16;
int ZAngularRate : 16;
int XWheelSpeed : 16;
int YWheelSpeed : 16;
int ZWheelSpeed : 16;
int star1BX : 16;
int star1BY : 16;
int star1BZ : 16;
int star1OX : 16;
int star1OY : 16;
int star1OZ : 16;
int star2BX : 16;
int star2BY : 16;
int star2BZ : 16;
int star2OX : 16;
int star2OY : 16;
int star2OZ : 16;
int star3BX : 16;
int star3BY : 16;
int star3BZ : 16;
int star3OX : 16;
int star3OY : 16;
int star3OZ : 16;
} fields;
} adcs_measurements_t;
我通过调用如下函数来填充结构:
void adcsTM191_measurements(adcs_measurements_t* dataOut)
{
int pass;
unsigned char TMID = 191;
unsigned char readBuff[72] = {0};
pass = I2C_write(ADCS_ADDR, &TMID, 1);
if(pass != 0)
{
printf("write error %d\n", pass);
}
pass = I2C_read(ADCS_ADDR, readBuff, 72);
if(pass != 0)
{
printf("read error %d\n", pass);
}
dataOut->fields.magneticFieldX = (readBuff[1] & 0x00FF) << 8 | (readBuff[0] & 0x00FF);
dataOut->fields.magneticFieldY = (readBuff[3] & 0x00FF) << 8 | (readBuff[2] & 0x00FF);
dataOut->fields.magneticFieldZ = (readBuff[5] & 0x00FF) << 8 | (readBuff[4] & 0x00FF);
dataOut->fields.coarseSunX = (readBuff[7] & 0x00FF) << 8 | (readBuff[6] & 0x00FF);
dataOut->fields.coarseSunY = (readBuff[9] & 0x00FF) << 8 | (readBuff[8] & 0x00FF);
dataOut->fields.coarseSunZ = (readBuff[11] & 0x00FF) << 8 | (readBuff[10] & 0x00FF);
dataOut->fields.sunX = (readBuff[13] & 0x00FF) << 8 | (readBuff[12] & 0x00FF);
dataOut->fields.sunY = (readBuff[15] & 0x00FF) << 8 | (readBuff[14] & 0x00FF);
dataOut->fields.sunZ = (readBuff[17] & 0x00FF) << 8 | (readBuff[16] & 0x00FF);
dataOut->fields.nadirX = (readBuff[19] & 0x00FF) << 8 | (readBuff[18] & 0x00FF);
dataOut->fields.nadirY = (readBuff[21] & 0x00FF) << 8 | (readBuff[20] & 0x00FF);
dataOut->fields.nadirZ = (readBuff[23] & 0x00FF) << 8 | (readBuff[22] & 0x00FF);
dataOut->fields.XAngularRate = (readBuff[25] & 0x00FF) << 8 | (readBuff[24] & 0x00FF);
dataOut->fields.YAngularRate = (readBuff[27] & 0x00FF) << 8 | (readBuff[26] & 0x00FF);
dataOut->fields.ZAngularRate = (readBuff[29] & 0x00FF) << 8 | (readBuff[28] & 0x00FF);
dataOut->fields.XWheelSpeed = (readBuff[31] & 0x00FF) << 8 | (readBuff[30] & 0x00FF);
dataOut->fields.YWheelSpeed = (readBuff[33] & 0x00FF) << 8 | (readBuff[32] & 0x00FF);
dataOut->fields.ZWheelSpeed = (readBuff[35] & 0x00FF) << 8 | (readBuff[34] & 0x00FF);
dataOut->fields.star1BX = (readBuff[37] & 0x00FF) << 8 | (readBuff[36] & 0x00FF);
dataOut->fields.star1BY = (readBuff[39] & 0x00FF) << 8 | (readBuff[38] & 0x00FF);
dataOut->fields.star1BZ = (readBuff[41] & 0x00FF) << 8 | (readBuff[40] & 0x00FF);
dataOut->fields.star1OX = (readBuff[43] & 0x00FF) << 8 | (readBuff[42] & 0x00FF);
dataOut->fields.star1OY = (readBuff[45] & 0x00FF) << 8 | (readBuff[44] & 0x00FF);
dataOut->fields.star1OZ = (readBuff[47] & 0x00FF) << 8 | (readBuff[46] & 0x00FF);
dataOut->fields.star2BX = (readBuff[49] & 0x00FF) << 8 | (readBuff[48] & 0x00FF);
dataOut->fields.star2BY = (readBuff[51] & 0x00FF) << 8 | (readBuff[50] & 0x00FF);
dataOut->fields.star2BZ = (readBuff[53] & 0x00FF) << 8 | (readBuff[52] & 0x00FF);
dataOut->fields.star2OX = (readBuff[55] & 0x00FF) << 8 | (readBuff[54] & 0x00FF);
dataOut->fields.star2OY = (readBuff[57] & 0x00FF) << 8 | (readBuff[56] & 0x00FF);
dataOut->fields.star2OZ = (readBuff[59] & 0x00FF) << 8 | (readBuff[58] & 0x00FF);
dataOut->fields.star3BX = (readBuff[61] & 0x00FF) << 8 | (readBuff[60] & 0x00FF);
dataOut->fields.star3BY = (readBuff[63] & 0x00FF) << 8 | (readBuff[62] & 0x00FF);
dataOut->fields.star3BZ = (readBuff[65] & 0x00FF) << 8 | (readBuff[64] & 0x00FF);
dataOut->fields.star3OX = (readBuff[67] & 0x00FF) << 8 | (readBuff[66] & 0x00FF);
dataOut->fields.star3OY = (readBuff[69] & 0x00FF) << 8 | (readBuff[68] & 0x00FF);
dataOut->fields.star3OZ = (readBuff[71] & 0x00FF) << 8 | (readBuff[70] & 0x00FF);
}
最后我打印出来,比如YWheelSpeed
。
adcsTM191_measurements(&temp);
printf("structure y wheel speed is: %d \n", temp.fields.YWheelSpeed);
这个值应该打印一个负值,它确实是:
structure y wheel speed is: -97
现在事情是这样的,如果我打印 (readBuff[27] & 0x00FF) << 8 | (readBuff[26] & 0x00FF)
,它对应于 Y 轮速度变量中填充的内容,adcsTM191_measurements(adcs_measurements_t* dataOut)
中的任何地方都不会打印这个负值。相反,它打印无符号字符的最大值 (65,535)。
int y = (int) (readBuff[33] & 0x00FF) << 8 | (readBuff[32] & 0x00FF);
printf("inside struct y is: %d", y);
我期望存储在结构内部会进行一种隐式转换,因此它会按预期打印负值。它是怎么做到的?如何在不使用结构的情况下打印正确的值?
您可能有 32 位 int
,因此初始化从不设置符号位。但是结构字段只有16位,在调用printf()
时转换为int
时会被符号扩展。
根据 C 2018 脚注 128,用 int
定义的位字段是有符号的还是无符号的,由实现定义。由于您的实现显示负值,推测它是有符号的,因此,作为 16 位有符号整数,它可以表示从 −32,768 到 32,767 的值。
我们还可以推断出 int
在您的实现中超过 16 位,可能是 32 位(根据事实是,在 int y
打印有“ %d”)。
考虑这个作业:
dataOut->fields.YWheelSpeed = (readBuff[33] & 0x00FF) << 8 | (readBuff[32] & 0x00FF);`
在此表达式中,readBuff[33]
和 readBuff[32]
通过 常规提升 转换为 int
。 0x00FF
也是一个 int
.
如果我们假设readBuff[33]
是255,readBufff[32]
是159(即28−97),那么表达式上的值=
的右侧是 65,439(即 216−97)。在赋值中,右操作数被转换为左操作数的类型,即 16 位有符号整数。在这种情况下,值 65,439 不能用 16 位有符号整数表示。 C 2018 6.3.1.3 3 告诉我们“要么结果是实现定义的,要么引发了实现定义的信号。”
此转换的常见实现方式是生成对 216 取模的结果,或者等效地,将 int
的 16 位低位重新解释为二进制补码16 位整数。这会产生 −97。由于您的实现随后显示了 −97 的值,因此大概这就是您的实现所做的。
因此,dataOut->fields.YWheelSpeed
被赋值为 −97。稍后打印时:
printf("structure y wheel speed is: %d \n", temp.fields.YWheelSpeed);
然后 默认参数提升 ,其中包括通常的整数提升,将 temp.fields.YWheelSpeed
从值为 −97 的有符号 16 位整数转换为 int
的值为 −97,并打印出“-97”。
相反,假设 (readBuff[33] & 0x00FF) << 8 | (readBuff[32] & 0x00FF)
打印为 %d
。正如我们在上面看到的,这个表达式的值为 65,439,因此应该打印“65439”。
问题说明:
Now here is the thing, if I print
(readBuff[27] & 0x00FF) << 8 | (readBuff[26] & 0x00FF)
, which corresponds to what was populated inside the Y wheel speed variable,… it prints the maximum value of an unsigned char (65,535).
但是,(readBuff[27] & 0x00FF) << 8 | (readBuff[26] & 0x00FF)
并不是赋给YWheelSpeed
的值,推测是“Y轮速度变量”。 YWheelSpeed
是从 readBuff
元素 32 和 33 赋值的,而不是 26 和 27。因此我们不应该对打印出一些不同的值而不是 65,439 感到惊讶。