Solved

Yet another question - Writing bytes to file

Posted on 2006-07-04
8
212 Views
Last Modified: 2010-04-01
While I decide how to grade the other one - here is another question.  It is based on other questions I have asked in the past but now that I have a better understanding of what I am trying to do, I can scale down the question a bit.

Okay, here goes.

Here is my implementation to generate a header to write to a file (Linux platform):

I am writing 4 bytes out to a file:
short field1 = 0;
int field2 = 1;
int field3 = 1;
int field4 = 1;
int field5 = 0;

unsigned int hdr = 0;
hdr=field1 << 16;
hdr += (field2 << 14) + (field3 << 11) + (field4 << 8) + field5;
fwrite( &hdr, sizeof(hdr), 1, fp);

I have another file where I am writing 6 bytes out -
The first byte -bits 5 and up 0
                     bit 4 is a flag - set to 1
                      bits 3, 2, 11
                      bits 1, 0 is 11
The next 5 bytes - setting values of 4 bits, then 20 bits, then 4.  Then 12 bits. -
Totalling - 40 bits

My  question is - do I have the flexibility to use unsigned char - 1 byte then unsigned int (4 bytes) and set each one?  Does it make a difference to use 5 byte unsigned char rather than the above?
How does "byte-ordering" impact this?

Maybe I should post this in the C programming area?


      
0
Comment
Question by:jewee
8 Comments
 
LVL 15

Assisted Solution

by:bpmurray
bpmurray earned 100 total points
ID: 17038423
As you've noticed, the problem is the use of the unsigned int. Depending on the platform, it could be stored in multiple ways, for the value 0x01234567, it could be 01-23-45-67 or 67-45-23-01. If you know that the program will only ever run on one particular architecture, then you can make assumptions. If there is a chance it will have to run on a different endian-ness, you should use the unsigned char array.

One other thing to bear in mind is that the C standard does not explicitly define the size of int, so running on a 64-bit compiler means that it could be 64 bits, which is not what you intended. You could use 2 shorts, but that would be silly :-)

To be safe, I'd use the chars, even though they are marginally less efficient to process.
0
 
LVL 86

Accepted Solution

by:
jkr earned 350 total points
ID: 17038438
Why don't you use bitfields instead of shifting the bits around? E.g.

struct {

short field5 : 6;
short field4 : 1;
short empty3 : 3;
short field3: 1;
short empty2 : 2;
short field2 : 1;
short empty1 : 1;
short field1 : 1;

} hdr;

hdr.field1 = 0;
hdr.field2 = 1;
hdr.field3 = 1;
hdr.field4 = 1;
hdr.field5 = 0;

(the up-down order is intentional in the bitfield declaration)

You can use that kind of construct for the other file, too. See http://publications.gbdirect.co.uk/c_book/chapter6/bitfields.html

If you have endianity issues, you can fix these by using 'htons()' before writing to the file.
0
 

Author Comment

by:jewee
ID: 17038445
Jkr - that was the other question I posted - differences in implementation.

http://www.experts-exchange.com/Programming/Programming_Languages/Cplusplus/Q_21907992.html
0
 
LVL 17

Assisted Solution

by:rstaveley
rstaveley earned 50 total points
ID: 17038455
Yes, bitfields and unsigned chars, to control bits, but don't forget to pack them. #pragma pack(1) is most portable in my experience, though you get vilified by the GNU community.

e.g.

#include <iostream>

#pragma pack(1)
struct YourStruct {
      unsigned char      b_00:1;
      unsigned char      b_01:1;
      unsigned char      b_02:1;
      unsigned char      b_03:1;
      unsigned char      b_04:1;
      unsigned char      b_05:1;
      unsigned char      b_06:1;
      unsigned char      b_07:1;
      unsigned char      b_08:1;
      unsigned char      b_09:1;
      unsigned char      b_0a:1;
      unsigned char      b_0b:1;
      unsigned char      b_0c:1;
      unsigned char      b_0d:1;
      unsigned char      b_0e:1;
      unsigned char      b_0f:1;
      unsigned char      b_10:1;
      unsigned char      b_11:1;
      unsigned char      b_12:1;
      unsigned char      b_13:1;
      unsigned char      b_14:1;
      unsigned char      b_15:1;
      unsigned char      b_16:1;
      unsigned char      b_17:1;
      unsigned char      b_18:1;
      unsigned char      b_19:1;
      unsigned char      b_1a:1;
      unsigned char      b_1b:1;
      unsigned char      b_1c:1;
      unsigned char      b_1d:1;
      unsigned char      b_1e:1;
      unsigned char      b_1f:1;
      unsigned char      b_20:1;
      unsigned char      b_21:1;
      unsigned char      b_22:1;
      unsigned char      b_23:1;
      unsigned char      b_24:1;
      unsigned char      b_25:1;
      unsigned char      b_26:1;
      unsigned char      b_27:1;
};
#pragma pack()

int main()
{
      YourStruct x;
      memset(&x,0,sizeof(x));

      x.b_21 = 1;

      std::cout << "Size is: " << sizeof(YourStruct) << '\n';
      std::cout << "Bit b_00 is " << static_cast<int>(x.b_00) << ", ";
      std::cout << "Bit b_01 is " << static_cast<int>(x.b_01) << ", ";
      std::cout << "Bit b_02 is " << static_cast<int>(x.b_02) << ", ";
      std::cout << "Bit b_03 is " << static_cast<int>(x.b_03) << ", ";
      std::cout << "Bit b_04 is " << static_cast<int>(x.b_04) << ", ";
      std::cout << "Bit b_05 is " << static_cast<int>(x.b_05) << ", ";
      std::cout << "Bit b_06 is " << static_cast<int>(x.b_06) << ", ";
      std::cout << "Bit b_07 is " << static_cast<int>(x.b_07) << ", ";
      std::cout << "Bit b_08 is " << static_cast<int>(x.b_08) << ", ";
      std::cout << "Bit b_09 is " << static_cast<int>(x.b_09) << ", ";
      std::cout << "Bit b_0a is " << static_cast<int>(x.b_0a) << ", ";
      std::cout << "Bit b_0b is " << static_cast<int>(x.b_0b) << ", ";
      std::cout << "Bit b_0c is " << static_cast<int>(x.b_0c) << ", ";
      std::cout << "Bit b_0d is " << static_cast<int>(x.b_0d) << ", ";
      std::cout << "Bit b_0e is " << static_cast<int>(x.b_0e) << ", ";
      std::cout << "Bit b_0f is " << static_cast<int>(x.b_0f) << ", ";
      std::cout << "Bit b_10 is " << static_cast<int>(x.b_10) << ", ";
      std::cout << "Bit b_11 is " << static_cast<int>(x.b_11) << ", ";
      std::cout << "Bit b_12 is " << static_cast<int>(x.b_12) << ", ";
      std::cout << "Bit b_13 is " << static_cast<int>(x.b_13) << ", ";
      std::cout << "Bit b_14 is " << static_cast<int>(x.b_14) << ", ";
      std::cout << "Bit b_15 is " << static_cast<int>(x.b_15) << ", ";
      std::cout << "Bit b_16 is " << static_cast<int>(x.b_16) << ", ";
      std::cout << "Bit b_17 is " << static_cast<int>(x.b_17) << ", ";
      std::cout << "Bit b_18 is " << static_cast<int>(x.b_18) << ", ";
      std::cout << "Bit b_19 is " << static_cast<int>(x.b_19) << ", ";
      std::cout << "Bit b_1a is " << static_cast<int>(x.b_1a) << ", ";
      std::cout << "Bit b_1b is " << static_cast<int>(x.b_1b) << ", ";
      std::cout << "Bit b_1c is " << static_cast<int>(x.b_1c) << ", ";
      std::cout << "Bit b_1d is " << static_cast<int>(x.b_1d) << ", ";
      std::cout << "Bit b_1e is " << static_cast<int>(x.b_1e) << ", ";
      std::cout << "Bit b_1f is " << static_cast<int>(x.b_1f) << ", ";
      std::cout << "Bit b_20 is " << static_cast<int>(x.b_20) << ", ";
      std::cout << "Bit b_21 is " << static_cast<int>(x.b_21) << ", ";
      std::cout << "Bit b_22 is " << static_cast<int>(x.b_22) << ", ";
      std::cout << "Bit b_23 is " << static_cast<int>(x.b_23) << ", ";
      std::cout << "Bit b_24 is " << static_cast<int>(x.b_24) << ", ";
      std::cout << "Bit b_25 is " << static_cast<int>(x.b_25) << ", ";
      std::cout << "Bit b_26 is " << static_cast<int>(x.b_26) << ", ";
      std::cout << "Bit b_27 is " << static_cast<int>(x.b_27) << ", ";
}
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:jewee
ID: 17038528
Will the bitfield approach using the struct also work if I am reading in a file - lets say 6 byte header.  Could I read it into a struct then say something like
if (hdr.field5 == 22)
 ...then do something?
Would I have to cast it?
0
 
LVL 86

Expert Comment

by:jkr
ID: 17038543
>>Will the bitfield approach using the struct also work if I am reading in a file - lets say 6 byte header

Yes, that would work. Hoever, if 'field5' is declared as one single bit, it won't, you'll need at least 5 bits to represent '22'.
0
 

Author Comment

by:jewee
ID: 17038845
I don't understand the difference with packing them.  Could you elaborate on that?
0
 
LVL 86

Expert Comment

by:jkr
ID: 17038920
If the size of your bitfield is not a multiple of four, you will have to, since otherwise the compiler will add padding space of up to 3 bytes to make sure that the size is alibned on a 4 byte boundary, which renders them useless when writing them to file, since that additional padding space would make it's way into the file also.
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now