C++位流解码函数返回较差的值(指针问题?)
我的函数 READ() 似乎工作正常,但当我转储输入时,我得到的内容超出了我的要求。既不是 0
也不是 1
的奇怪字符。我敢打赌这是由于我的指针使用(取消引用运算符)造成的,但我似乎无法弄清楚正在做什么。任何使其输出正确数据的帮助都会有所帮助。另外,还解释了为什么它的用法是错误的,以及一些关于如何不再这样做的好提示。谢谢你们,你们是最棒的。
在MSVC++ 2010 Express下编译:
#include <iostream>
using namespace std;
struct Holder
{
unsigned char *bits; // holds our bits
unsigned char header[6]; // Always 6 bits
unsigned char hasid[1]; // Always 1 bit
unsigned char cid[4]; // always 4 bits
};
// Turns our Bytes Into Bits
// Credit: Ben Voigt(http://stackoverflow.com)
void BIT(const char *bytes, size_t len, char *bitStr)
{
while (len--) {
bitStr[0] = (*bytes & 0x80) ? '1': '0';
bitStr[1] = (*bytes & 0x40) ? '1': '0';
bitStr[2] = (*bytes & 0x20) ? '1': '0';
bitStr[3] = (*bytes & 0x10) ? '1': '0';
bitStr[4] = (*bytes & 0x08) ? '1': '0';
bitStr[5] = (*bytes & 0x04) ? '1': '0';
bitStr[6] = (*bytes & 0x02) ? '1': '0';
bitStr[7] = (*bytes & 0x01) ? '1': '0';
bitStr += 8;
bytes++;
}
*bitStr = 0;
}
// This function is not working correctly
void READ( unsigned char *BITS, unsigned char *PACKET_ID, unsigned char *HAS_CHANNEL_ID, unsigned char *CHANNEL_ID, unsigned char *PACKET)
{
//=====================================================
// The Below Header Info Is Always The Same
//=====================================================
// Packet ID ALWAYS 6 BITS
PACKET_ID[0] = BITS[2];
PACKET_ID[1] = BITS[3];
PACKET_ID[2] = BITS[4];
PACKET_ID[3] = BITS[5];
PACKET_ID[4] = BITS[6];
PACKET_ID[5] = BITS[7];
// Packet Has Channel ID (1==true) ALWAYS 1 BIT
HAS_CHANNEL_ID[0] = BITS[1];
// Channel ID ALWAYS 4 BIT
CHANNEL_ID[0] = BITS[0];
CHANNEL_ID[1] = BITS[15];
CHANNEL_ID[2] = BITS[14];
CHANNEL_ID[3] = BITS[13];
//=====================================================
// The above Header Info Is Always The Same
//=====================================================
//Variables For Looping
int P = 16; // This is the start of all data, always
int B = 24; // Every 24 bits, the loop goes into an IF_STATMENT and reads backwards into the array, then continues normally
int A = 1; // This Increases every 24 bits
int Z = 0; // This holds how many times we loop. Used for IF_STATMENT formula
int I = 0; // This gets zeroed out every IF_STATMENT and keeps our loop int i in sync
PACKET[0] = BITS[12];
PACKET[1] = BITS[11];
PACKET[2] = BITS[10];
PACKET[3] = BITS[9];
PACKET[4] = BITS[8];
// Starts our main loop...
for(int i=5 ; i < sizeof(BITS) ; i++, P++, Z++)
{
PACKET[i] = BITS[P];
if( (A * B) == Z) // A==1 B==24 Z==FOR_LOOP
{
I = 0; // ZERO THIS OUT. THIS IS USED FOR P COUNTER
A++; // Increase by one for IF_STATMENT formula
if( (P+7) <= sizeof(BITS)) // if P+7 is less then or equal to BITS then its okay todo the following
{ // which is needed because maybe P+7 is bigger then BITS, so this wouldnt be good ...
PACKET[i] = BITS[P+7];
I++;
}
if( (P+6) <= sizeof(BITS)) // Explained Above
{
PACKET[i+1] = BITS[P+6];
I++;
}
if( (P+5) <= sizeof(BITS)) // Explained Above
{
PACKET[i+2] = BITS[P+5];
I++;
}
if( (P+4) <= sizeof(BITS)) // Explained Above
{
PACKET[i+3] = BITS[P+4];
I++;
}
if( (P+3) <= sizeof(BITS)) // Explained Above
{
PACKET[i+4] = BITS[P+3];
I++;
}
if( (P+2) <= sizeof(BITS)) // Explained Above
{
PACKET[i+5] = BITS[i+2];
I++;
}
if( (P+1) <= sizeof(BITS)) // Explained Above
{
PACKET[i+6] = BITS[P+1];
I++;
}
if( P <= sizeof(BITS)) // Explained Above
{
PACKET[i+7] = BITS[P];
I++;
}
P += I; // We have been increasing I each time we do one of the statments to keep track of how many loops
if(I != 0) // we need to add to P to keep it on track ... + I-1 to keep i on track
i += I-1;
}
}
}
int main()
{
const char p40[] =
{
0x81, 0x11, 0xb6, 0x1e, 0xc9, 0x67, 0x0e, 0x52, 0x0b, 0xec, 0xff, 0x3b, 0xa8, 0xfa, 0x2a, 0x62,
0x41, 0x79, 0xd2, 0x75, 0x7b, 0x93, 0xaf, 0xb4, 0xcf, 0x10, 0x3a, 0x12, 0x4d, 0x4b, 0x60, 0x64,
0xcc, 0x78, 0x01, 0xd1, 0x83, 0xbc, 0x27
};
Holder k; // Call our struct for holding stuff
unsigned char bitbit[sizeof(p40)*8]; // bitbit is an array that is p40 * 8 to get the amount of bits being made using BIT function
BIT(p40,sizeof(p40),(char*)bitbit); // BIT takes p40, and turns it into bits and stores them in bitbit
k.bits = bitbit; // now k.bits is equal to bitbit
cout << k.bits; // dumps k.bits to screen
cout << "\n"; // space to see ...
unsigned char r[sizeof(k.bits-11)]; // r is k.bits - 11 because 11 bits are used for something else
READ(k.bits, k.header,k.hasid, k.cid,r); //This puts k.bits into READ function. Itll store the info into the struct
cout << "\nPACKET_HEADER:\n";
cout << k.header; // This dump seems to be displaying more then what its suppose too...
cout << "\nHAS_CANNEL:\n";
cout << k.hasid; // This dump seems to be displaying more then what its suppose too...
cout << "\nCHANNEL_ID:\n";
cout << k.cid; // This dump seems to be displaying more then what its suppose too...
cout << "\nPACKET_BITS:\n";
cout << r; // The last dump (r) is displaying all inputs into the function READ + r.
int a; // Used to hang program ...
cin >> a;
return 0;
}
My function READ()
, seems to be working correctly, except when I dump the inputs I am getting more than what I asked for. Weird chars that are not 0
s nor 1
s. I bet it is due to my pointer usage (dereference operators), but I just cant seem to figure out what is doing it. Any help on making it output the correct data would be helpful. Also, some explanation why its wrong usage, and some good tips on how to never do it again. Thanks, you guys are the best.
Compiling under MSVC++ 2010 Express:
#include <iostream>
using namespace std;
struct Holder
{
unsigned char *bits; // holds our bits
unsigned char header[6]; // Always 6 bits
unsigned char hasid[1]; // Always 1 bit
unsigned char cid[4]; // always 4 bits
};
// Turns our Bytes Into Bits
// Credit: Ben Voigt(http://stackoverflow.com)
void BIT(const char *bytes, size_t len, char *bitStr)
{
while (len--) {
bitStr[0] = (*bytes & 0x80) ? '1': '0';
bitStr[1] = (*bytes & 0x40) ? '1': '0';
bitStr[2] = (*bytes & 0x20) ? '1': '0';
bitStr[3] = (*bytes & 0x10) ? '1': '0';
bitStr[4] = (*bytes & 0x08) ? '1': '0';
bitStr[5] = (*bytes & 0x04) ? '1': '0';
bitStr[6] = (*bytes & 0x02) ? '1': '0';
bitStr[7] = (*bytes & 0x01) ? '1': '0';
bitStr += 8;
bytes++;
}
*bitStr = 0;
}
// This function is not working correctly
void READ( unsigned char *BITS, unsigned char *PACKET_ID, unsigned char *HAS_CHANNEL_ID, unsigned char *CHANNEL_ID, unsigned char *PACKET)
{
//=====================================================
// The Below Header Info Is Always The Same
//=====================================================
// Packet ID ALWAYS 6 BITS
PACKET_ID[0] = BITS[2];
PACKET_ID[1] = BITS[3];
PACKET_ID[2] = BITS[4];
PACKET_ID[3] = BITS[5];
PACKET_ID[4] = BITS[6];
PACKET_ID[5] = BITS[7];
// Packet Has Channel ID (1==true) ALWAYS 1 BIT
HAS_CHANNEL_ID[0] = BITS[1];
// Channel ID ALWAYS 4 BIT
CHANNEL_ID[0] = BITS[0];
CHANNEL_ID[1] = BITS[15];
CHANNEL_ID[2] = BITS[14];
CHANNEL_ID[3] = BITS[13];
//=====================================================
// The above Header Info Is Always The Same
//=====================================================
//Variables For Looping
int P = 16; // This is the start of all data, always
int B = 24; // Every 24 bits, the loop goes into an IF_STATMENT and reads backwards into the array, then continues normally
int A = 1; // This Increases every 24 bits
int Z = 0; // This holds how many times we loop. Used for IF_STATMENT formula
int I = 0; // This gets zeroed out every IF_STATMENT and keeps our loop int i in sync
PACKET[0] = BITS[12];
PACKET[1] = BITS[11];
PACKET[2] = BITS[10];
PACKET[3] = BITS[9];
PACKET[4] = BITS[8];
// Starts our main loop...
for(int i=5 ; i < sizeof(BITS) ; i++, P++, Z++)
{
PACKET[i] = BITS[P];
if( (A * B) == Z) // A==1 B==24 Z==FOR_LOOP
{
I = 0; // ZERO THIS OUT. THIS IS USED FOR P COUNTER
A++; // Increase by one for IF_STATMENT formula
if( (P+7) <= sizeof(BITS)) // if P+7 is less then or equal to BITS then its okay todo the following
{ // which is needed because maybe P+7 is bigger then BITS, so this wouldnt be good ...
PACKET[i] = BITS[P+7];
I++;
}
if( (P+6) <= sizeof(BITS)) // Explained Above
{
PACKET[i+1] = BITS[P+6];
I++;
}
if( (P+5) <= sizeof(BITS)) // Explained Above
{
PACKET[i+2] = BITS[P+5];
I++;
}
if( (P+4) <= sizeof(BITS)) // Explained Above
{
PACKET[i+3] = BITS[P+4];
I++;
}
if( (P+3) <= sizeof(BITS)) // Explained Above
{
PACKET[i+4] = BITS[P+3];
I++;
}
if( (P+2) <= sizeof(BITS)) // Explained Above
{
PACKET[i+5] = BITS[i+2];
I++;
}
if( (P+1) <= sizeof(BITS)) // Explained Above
{
PACKET[i+6] = BITS[P+1];
I++;
}
if( P <= sizeof(BITS)) // Explained Above
{
PACKET[i+7] = BITS[P];
I++;
}
P += I; // We have been increasing I each time we do one of the statments to keep track of how many loops
if(I != 0) // we need to add to P to keep it on track ... + I-1 to keep i on track
i += I-1;
}
}
}
int main()
{
const char p40[] =
{
0x81, 0x11, 0xb6, 0x1e, 0xc9, 0x67, 0x0e, 0x52, 0x0b, 0xec, 0xff, 0x3b, 0xa8, 0xfa, 0x2a, 0x62,
0x41, 0x79, 0xd2, 0x75, 0x7b, 0x93, 0xaf, 0xb4, 0xcf, 0x10, 0x3a, 0x12, 0x4d, 0x4b, 0x60, 0x64,
0xcc, 0x78, 0x01, 0xd1, 0x83, 0xbc, 0x27
};
Holder k; // Call our struct for holding stuff
unsigned char bitbit[sizeof(p40)*8]; // bitbit is an array that is p40 * 8 to get the amount of bits being made using BIT function
BIT(p40,sizeof(p40),(char*)bitbit); // BIT takes p40, and turns it into bits and stores them in bitbit
k.bits = bitbit; // now k.bits is equal to bitbit
cout << k.bits; // dumps k.bits to screen
cout << "\n"; // space to see ...
unsigned char r[sizeof(k.bits-11)]; // r is k.bits - 11 because 11 bits are used for something else
READ(k.bits, k.header,k.hasid, k.cid,r); //This puts k.bits into READ function. Itll store the info into the struct
cout << "\nPACKET_HEADER:\n";
cout << k.header; // This dump seems to be displaying more then what its suppose too...
cout << "\nHAS_CANNEL:\n";
cout << k.hasid; // This dump seems to be displaying more then what its suppose too...
cout << "\nCHANNEL_ID:\n";
cout << k.cid; // This dump seems to be displaying more then what its suppose too...
cout << "\nPACKET_BITS:\n";
cout << r; // The last dump (r) is displaying all inputs into the function READ + r.
int a; // Used to hang program ...
cin >> a;
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您将数据保存在 char 数组中,因此当您将它们传递给 std::cout 时,运算符假定以 null 结尾的 C 字符串。除非你的标头保证以空终止,否则 std::cout 将会超出数组的末尾并打印比你想要的更多的内容。
解决此问题的一种巧妙方法是:
假设您的编译器没有对 Holder 中的字段重新排序,这应该会导致 std::cout 仅打印您期望的字节数。
这仅回答了您问题的一部分。我现在正在发帖,如果我弄清楚其余部分,我将进行编辑。
ETA:查看 READ,您的问题似乎又是缺少空终止。数组中需要一个额外的字符来保存空字符('\0',几乎普遍等于 NULL,本身几乎总是 0),这将告诉
std::cout
C 字符串正在结束。另外,这是一种为 Holder 提供空终止的更简洁的方法:我保留了上面原始的、丑陋的修复,因为它说明了导致代码打印额外垃圾的规则。
You are holding your data in char arrays, and so when you pass them to
std::cout
the operator assumes null-terminated C strings. Unless your headers are guaranteed to be null-terminated,std::cout
is going to run off the end of the arrays and print more than you want them to.A kind of hacky way to fix this:
Assuming your compiler doesn't re-order the fields in Holder, this should cause
std::cout
to print only the number of bytes you expect.This answers only part of your problem. I'm posting for now and will edit if I figure out the rest.
ETA: Looking over READ, it appears your problem is again an absence of null-termination. You need one extra char in the array to hold the null character ('\0', near universally equal to NULL, itself almost always 0) which will tell
std::cout
that the C string is ending. Also, this is a cleaner way to provide null-termination to Holder:I'm keeping the original, ugly fix above because it illustrates the rules that cause your code to print extra garbage.