cfile-ioincrement

C increment ++ unexpected result


I have a problem with using increment ++ while trying to increase the value of an int variable. I'm passing the address of the variable called records to the function open() than opens a file in binary mode and then parses the file to find the amount of struct record elements present in the file. The problem is that when using the increment ++ as *records++; the result is not what expected, for example I have 4 records in the .dat file and it prints:

HELLO! 1
HELLO! 0
HELLO! -251258176
HELLO! 22074

Back in main it prints:

Records in file: 0.

Now the weird thing is that instead of using increment ++, I use *records += 1;, the result is as expected!

HELLO! 1
HELLO! 2
HELLO! 3
HELLO! 4

Back in main:

Records in file: 4.

I can't understand where is the issue. Part of code is included below:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define true 1
#define false 0
#define size 100

typedef struct record {
    char firstName[size], lastName[size];
    int age;
    double grade;
} record;

int open(const char *filename, FILE **fp, int *records);

int main() {
    FILE *fp;
    char filename[] = "records.dat";
    int records = 0, opened = false, ch = 1;

    while(ch > 0 && ch < 5) {

        printf("Select your choice from the list below: \n");
        printf("1. Open file and get amount of records in it\n");
        printf("Enter your choice: ");
        scanf("%d", &ch);
        while(getchar() != '\n');

        switch(ch) {
            case 1:
                if(opened) {
                    printf("\nFile already open, try closing it first please.\n");
                    break;
                }

                opened = open(filename, &fp, &records);

                if(opened) {
                    printf("\nRecords in file: %d.\n", records);
                } else { // Failed to open AND create file
                    return 1;
                }

                break;

            default:
                printf("\nGoodbye!\n");
                if(opened) {
                    fclose(fp);
                }
                return 0;
                break;
        }
    }
}

int open(const char *filename, FILE **fp, int *records) {
    char temp[size];
    record r;
    *records = 0;

    printf("Attempting to open file...\n");
    *fp = fopen(filename, "rb+");
    if(*fp == NULL) {
        printf("File doesn't exit, attempting to create file...\n");
        *fp = fopen(filename, "wb+");
        if(*fp == NULL) {
            fprintf(stderr, "Couldn't open neither create %s, exiting...\n", filename);
            return false;
        }
        printf("File created.\n");
        return true;
    }
    printf("File found!\n");

    while(fread(&r, sizeof(r), 1, *fp) == 1) {
        *records++;
        //*records += 1;
        printf("HELLO! %d\n", *records);
    }

    return true;
}

Solution

  • The ++ (increment) is binding more tightly than * (dereference). Basically, what you're doing is changing the pointer, not the value. It's equivalent to:

    *(records+=1);
    

    Try (*records)++ instead to force the dereference to happen first.

    But mostly, don't modify parameters like that -- instead make it a return value:

    int open(...) {
      int records=-1;
      while( read ...) {
        // do stuff
        records++;
      }
      return records;
    }
    

    and use -1 to mean "error".

    Or, if you must modify the parameter:

    int open(..., int* records) {
       int records_read = 0;
       while( read ... ) {
         // do stuff
         records_read++;
       }
       *records = records_read;
       return true;
    }