如何解决解引用char指针后,我得到了意外的输出
我想使用char ptr从缓冲区中发送16位数据中的一些8位数据(HEX格式),为此,我采用了“ Unsigned short int”数组,并使用char取消引用了。但是在输出中,额外的“ FFFFFF”会附加到我的数据中。
代码段:
unsigned short int buf[50]={0},j;
char *ptr=buf;
//entering some 16bit data manually
buf[0]=0xAAAA;
buf[1]=0xCCBB;
buf[2]=0x1234;
buf[3]=0xABCD;
for(j=0;j<8;j++)
{
printf("%X\t",*p);
p++;
}
输出:
FFFFFFAA FFFFFFAA FFFFFFBB FFFFFFCC 34 12 FFFFFFCD FFFFFFAB
对于0x1234数据,这里的格式正确,但是其余的如何处理。 谁能帮忙
解决方法
ptr
指针的类型需要在此处取消签名:
unsigned short int buf[50]={0},j;
unsigned char *ptr=buf;
//entering some 16bit data manually
buf[0]=0xAAAA;
buf[1]=0xCCBB;
buf[2]=0x1234;
buf[3]=0xABCD;
for(j=0;j<8;j++)
{
printf("%X\t",*ptr);
ptr++;
}
将为您提供预期的输出:(字节顺序取决于您的字节序,这里是X86 / little-endian)
AA AA BB CC 34 12 CD AB
,
-
char *ptr=buf;
这是无效的C。由于指针类型不兼容,因此这违反了“简单赋值”的约束。编译器必须为您提供诊断信息,例如警告。您可以通过在分配前进行投射来解决此问题:char*ptr = (char*)buf;
-
buf[1]=0xCCBB;
等将无符号的short存储在内存中,并且像任何整数类型一样,它根据字节顺序存储。如果您使用的是低端字节序的x86 PC,则0xBB将存储在最低地址上。这就是为什么当您稍后逐字节打印它们时它们会向后出现的原因。 -
printf("%X\t",*ptr);
这行上发生了很多奇怪的事情。- 首先,我们必须了解
char
具有实现定义的签名Is char signed or unsigned by default?。因此,这种类型绝对不能用于原始二进制操作或任何形式的算术。 - 在您的特定编译器上,
char
刚好被签名。 -
printf
是可变函数。这样的功能是奇特的(并且是不好的做法),并带有许多特殊规则。一条这样的特殊规则指出,传递给可变参数函数的每个参数都经过一种特殊的隐式提升,即“默认参数提升”。该规则说所有小整数类型(例如char
)都被提升为类型int
。 - 每当有符号的
char
或任何其他小整数类型被提升为较大的有符号类型时,它都是符号扩展,这意味着如果它持有一个负的十进制值,则该符号为保存。 - 如果您的8位带符号的
char
指向数据0xAA
,则它将被视为负数,因为0xAA
是8位2的补码格式的-86十进制。当将此-86
值转换为4字节带符号的int
时,该符号将保留,但其值仍为-86
。但是现在原始的二进制表示形式是0xFFFFFFAA
。这就是为什么您的所有具有MSB设置的十六进制值字节都附加了0xFFFFFF ...,而没有MSB设置的那些却按预期方式打印的原因。 - 最后,
%X
假定传递的参数是unsigned int
,因此printf
进行从内部int
到值为-86
的内部转换。无符号等效项0xFFFFFFAA
,即打印出来的内容。
- 首先,我们必须了解
我们可以这样修改代码:
#include <stdio.h>
#include <stdint.h>
int main()
{
uint16_t buf[50];
uint8_t* ptr = (uint8_t*)buf;
buf[0]=0xAAAA;
buf[1]=0xCCBB;
buf[2]=0x1234;
buf[3]=0xABCD;
for(int i=0; i<8; i++)
{
printf("%X\t",*ptr);
ptr++;
}
}
此处发生了将uint8_t
升级为int
的相同默认参数,但是这一次原始数据在升级之前被视为未签名,因此没有符号扩展发生。
首先,您的代码应如下所示;
unsigned short int buf[50] = {0},j;
char *ptr = (char *)buf;
//entering some 16bit data manually
buf[0] = 0xAAAA;
buf[1] = 0xCCBB;
buf[2] = 0x1234;
buf[3] = 0xABCD;
for (j = 0; j < 8; j++) {
printf("%X ",*ptr); // "p" is not defined any where
ptr++; // i think,it's got to be "ptr"
}
关于FF...
前缀:
-
前两行之后;
a)50 * 2(
short
的大小)= 100字节被清零,b),然后将前8个字节分配为
aa aa bb cc 34 12 cd ab
。 -
您的指针
ptr
是(char *)
(指向单个字节char
),但是您的printf
试图将它们打印为4个字节的整数。 / p> -
由于
*ptr
取消引用单个字节,printf
将其转换为4字节整数。您最好检查一下C书中有关将char
转换为int
和二进制数的章节。基本上,这一章会告诉你;在从1字节转换为4字节的过程中,最左边的位向左复制。那是
-
1 byte hex: aa
被1 byte bin: 10101010
转换为4 byte bin: 11111111...10101010
(最左边的1
位在完成4个字节时被复制到左边;这里是FF
前缀的所在来自) -
1 byte hex: 12
被1 byte bin: 00010010
转换为4 byte bin: 00000000...00010010
(完成时,最左边的0
位被复制到4个字节时被向左复制;全部归零,您看不到任何{{ 1}}前缀。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。