fwrite a one byte integer

This is a discussion on fwrite a one byte integer within the C Programming forums, part of the General Programming Boards category; I'm making a program that edits a binary file. Most of this binary file is composed of single byte unsigned ...

  1. #1
    Registered User
    Join Date
    Nov 2008
    Location
    Bay Area, CA
    Posts
    53

    fwrite a one byte integer

    I'm making a program that edits a binary file. Most of this binary file is composed of single byte unsigned integers. At the moment, I'm making sure the values are validated to be within a single byte before writing them to the file, and I'm using unsigned shorts, since that's as small as I get get with an actual, real integer type. For number of bytes and elements to pass to fwrite, I'm just putting 1 for both (1 element, 1 byte) so that it just writes the first byte of the short, since as before, I've already validated the data by this point to be contained within that first byte.

    Is there a better, safer, more legitimate way of writing one byte integer values to a binary file? Because my way seems kinda, I dunno, ghetto.

    I'm reading the values from the file into unsigned char arrays, but I wasn't sure if writing them back the same way would work ok.

    I tried googling around for it, but didn't come up with much, aside from some post I came across in the results that involved some combination of casting, int, char, and pointers, which I haven't been able to find again.

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    2,676
    Why not, unsigned char is one byte, and it is a true integer type?

    Jim

  3. #3
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    You seem to think that char's are not "true" integers. Actually, there's nothing special about them at all. They are simply one-byte integers (actually, they don't have to be one byte but on the machines most of us use they are). They are called char's because they are often used for characters, but that's not all they're used for (and sometimes they're not even used for that).

    Writing the first byte of a short to the file only works because of the particular "endianness" of your machine, which is little-endian: i.e, the least significant byte is lower in memory so that's the one you get with your "1 element, 1 byte" method. But if the machine was big-endian you'd just get 0 for that byte (assuming the short was in the range of 0 to 255).
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  4. #4
    Registered User
    Join Date
    Nov 2008
    Location
    Bay Area, CA
    Posts
    53
    Quote Originally Posted by jimblumberg View Post
    Why not, unsigned char is one byte, and it is a true integer type?

    Jim
    Quote Originally Posted by oogabooga View Post
    You seem to think that char's are not "true" integers. Actually, there's nothing special about them at all. They are simply one-byte integers (actually, they don't have to be one byte but on the machines most of us use they are). They are called char's because they are often used for characters, but that's not all they're used for (and sometimes they're not even used for that).

    Writing the first byte of a short to the file only works because of the particular "endianness" of your machine, which is little-endian: i.e, the least significant byte is lower in memory so that's the one you get with your "1 element, 1 byte" method. But if the machine was big-endian you'd just get 0 for that byte (assuming the short was in the range of 0 to 255).
    Thinking about it more, I guess the issue is less about the fwrite, and more about how I'm collecting the information from the user, since the program is console based at the moment. I need to collect and validate the information from the user. Do I really just plug unsigned char in everywhere, instead of unsigned short? And how does that change my validation (i.e. if outside of range, reprompt user)?

    It's funny that you mention the endian thing, I'm actually already going between little-endian and big-endian for this project. My editor is for savegame files for a particular Sega Saturn game, and the Saturn used a Motorola processor, which was big-endian. I already do proper conversion throughout the program as necessary (there are a small percentage of arrays in the file with two-byte values). When reading from the file and into memory, when reading from memory back to the file, etc.

  5. #5
    Registered User
    Join Date
    May 2009
    Posts
    2,481
    I would use "unsigned char" type (or a typedef of one) for the variable type used in the fread/fwrite statements.
    You could use the larger size elsewhere.

    Tim S.
    "Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the Universe is winning." Rick Cook

  6. #6
    cas
    cas is offline
    Registered User
    Join Date
    Sep 2007
    Posts
    975
    The follow all assumes 8-bit bytes, which is rather common. If you are using C99, you can use uint8_t, which won't exist if bytes are larger than 8 bits, meaning you'll get a compile-time error.
    Do I really just plug unsigned char in everywhere, instead of unsigned short? And how does that change my validation (i.e. if outside of range, reprompt user)?
    I don't completely understand the question. If you read one unsigned char from a file, you don't need to do any validation to discover whether it's in the range of a byte: it has to be.

    Let's say your file starts with two single-byte values followed by a big-endian two-byte value. All you need is something like:
    Code:
    unsigned char val1, val2, lobyte, hibyte;
    unsigned short val3;
    FILE *fp = fopen(..., "rb");
    
    val1 = getc(fp);
    val2 = getc(fp);
    hibyte = getc(fp);
    lobyte = getc(fp);
    val3 = (hibyte << 8) | lobyte;
    
    /* to write out */
    putc(val1, fp);
    putc(val2, fp);
    putc(val3 >> 8, fp);
    putc(val3 & 0xff, fp);
    Real code will check for EOF before assigning to an unsigned char, of course.

  7. #7
    Registered User
    Join Date
    Nov 2008
    Location
    Bay Area, CA
    Posts
    53
    The reading from file part is fine, my last question was in regards to user input. Am I just using a normal unsigned int and then assigning the value to an unsigned char after it's been validated, because I don't think scanf-ing ints into a char is going to work. That's the part I'm unclear on - keyboard input from user.

  8. #8
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Quote Originally Posted by Sorin View Post
    That's the part I'm unclear on - keyboard input from user.
    What is the user supposed to input? One byte? Sequence of bytes? Which base (octal, decimal, hexadecimal, binary)?
    Show us an example of a valid input and someone here will probably have a good solution :-).

    Bye, Andreas

  9. #9
    cas
    cas is offline
    Registered User
    Join Date
    Sep 2007
    Posts
    975
    The reading from file part is fine, my last question was in regards to user input. Am I just using a normal unsigned int and then assigning the value to an unsigned char after it's been validated, because I don't think scanf-ing ints into a char is going to work. That's the part I'm unclear on - keyboard input from user.
    If you're concerned about problems with user input, scanf() is not the way to go. If the user enters a too-large value (for the type you're reading into), the behavior is undefined. Generally speaking, it's better to read a line with fgets() and then convert it to a long with strtol(). At that point you can do your validation.

    Otherwise, if you do use scanf(), then yes, you'll just read into some integer type (the larger the better to avoid undefined behavior), validate, and assign to your unsigned char. The latest C standards do allow reading directly into an unsigned char with %hhu, but you'll be able to do no validation: if the user enters a too-large value, you're out of luck.

    No matter what you do, C is a bit annoying when it comes to text processing like this.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. byte array plus integer literal question
    By pauljcx in forum C Programming
    Replies: 2
    Last Post: 08-04-2011, 01:31 PM
  2. File Comparision byte by byte
    By anusha2489 in forum C Programming
    Replies: 12
    Last Post: 05-16-2011, 06:58 AM
  3. reading files byte by byte
    By cpsc in forum C++ Programming
    Replies: 12
    Last Post: 01-07-2011, 02:54 PM
  4. Byte Array / Integer conversion
    By AdLab in forum C Programming
    Replies: 2
    Last Post: 05-07-2008, 08:04 AM
  5. 5 Byte Integer
    By NewPappa in forum C Programming
    Replies: 11
    Last Post: 07-22-2004, 11:57 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21