Why does fprintf print extra values
I want to encode tags that will contain a field number and a wire type for the purpose of protocol buffers. The problem that I am having now is that whenever my value for 'tag' is below '8' fprintf writes additional values next to the correct ones. i.e. instead of 38 it prints 38c0 3. If the value of tag is 8 or higher the script works fine. Below is the code with irrelavent lines omitted.
int uint32_pack (uint8_t *fieldnumber, uint32_t value, uint8_t *out);
int main(){
uint32_t initvalue = 2;
int return_rv;
uint8_t *tag = (uint8_t *) malloc(sizeof(uint8_t));
uint8_t *tempout= (uint8_t *) malloc(sizeof(uint32_t));
*tag = 7; //value to be encoded (won't work for values less than 8)
return_rv = uint32_pack (tag, initvalue, tempout);
free(tempout);
}
/* === pack() === */
/* Pack an unsigned 32-bit integer in base-128 encoding, and return the number
of bytes needed: this will be 5 or less. */
int uint32_pack (uint8_t *fieldnumber, uint32_t value, uint8_t *out)
{
unsigned rv = 0;
FILE *wiretypetag;
int secondaryvalue;
wiretypetag = fopen("wiretype.txt","w");
//encodes wire type and the field number
if (*fieldnumber <16){
*fieldnumber <<= 3;
fprintf(wiretypetag,"%x",fieldnumber[0]);
}
if (*fieldnumber < 32 && *fieldnumber > 15){
*fieldnumber <<= 3;
secondaryvalue = 0x01;
fprintf(wiretypetag,"%x %x",fieldnumber[0],secondaryvalue);
}
if (*fieldnumber < 48 && *fieldnumber > 31){
*fieldnumber += 0x10;
*fieldnumber &= 0x1F;
*fieldnumber <<= 3;
secondaryvalue = 0x02;
fprintf(wiretypetag,"%x %x",fieldnumber[0], secondaryvalue);
}
if (*fieldnumber < 64 && *fieldnumber > 47){
*fieldnumber &= 0x开发者_开发问答1F;
*fieldnumber <<= 3;
secondaryvalue = 0x03;
fprintf(wiretypetag,"%x %x",fieldnumber[0], secondaryvalue);
}
/* assert: value<128 */
out[rv++] = value;
if (rv == 1){
fprintf(outfile,"%x",out[0]);
}
if (rv == 2){
fprintf(outfile,"%x %x",out[0], out[1]);
}
if (rv == 3){
fprintf(outfile,"%x %x %x",out[0],out[1],out[2]);
}
if (rv == 4){
fprintf(outfile,"%x %x %x %x",out[0],out[1],out[2],out[3]);
}
if (rv == 5){
fprintf(outfile,"%x %x %x %x %x",out[0],out[1],out[2],out[3],out[4]);
}
fclose(wiretypetag);
return rv;
}
if (fieldnumber <16){
should be
if (*fieldnumber <16){
You can simplify the code by using else
at:
//encodes wire type and the field number
if (*fieldnumber <16){
*fieldnumber <<= 3;
fprintf(wiretypetag,"%d",fieldnumber[0]);
}
if (*fieldnumber < 32 && *fieldnumber > 15){
*fieldnumber <<= 3;
Replace with:
//encodes wire type and the field number
if (*fieldnumber < 16) {
*fieldnumber <<= 3;
fprintf(wiretypetag, "%d", fieldnumber[0]);
}
else if (*fieldnumber < 32) {
*fieldnumber <<= 3;
...
This is a common idiom and one you should use when appropriate - as now. It will improve the legibility of the code.
That may not be the whole problem; it probably isn't.
Explanation of Problem
In fact, using an else if
chain corrects the code. Because the first if
modifies *fieldnumber
with the <<=
operator, when the second condition is evaluated, *fieldnumber
is no longer 7 but 56, so the condition for
if (*fieldnumber < 64 && *fieldnumber > 47){
is also executed, printing out more information.
The else if
chain will resolve that by ensuring that only one alternative is executed.
Since you have:
unsigned rv = 0;
[...]
/* assert: value<128 */
out[rv++] = value;
if (rv == 1){
fprintf(outfile,"%x",out[0]);
}
This fprintf()
should be executed, but the following ones for rv
equal to 2, 3, 4, 5 should never be executed.
精彩评论