ccs50

Why is sizeof(HEADER_SIZE) = 4 when it was initialized as 44?


Given below is my solution to CS50's Week 4: Volume. The problem I was trying to solve was to read a .wav file and change its volume based on a comandline argument 'factor'.

Problem: When I was testing this code I initially used fread(header, HEADER_SIZE, 1, input); My code would compile without error and an output file would be produced for the following: ./volume input.wav output.wav 1.0

But a currupted output file would be produced if I changed the volume factor to anything else other than 1.0.

// Modifies the volume of an audio file

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

// Number of bytes in .wav header
const int HEADER_SIZE = 44;

void copy_header(FILE *input, FILE *output);
void copy_samples(FILE *input, FILE *output, float factor);

int main(int argc, char *argv[])
{
    // Check command-line arguments
    if (argc != 4)
    {
        printf("Usage: ./volume input.wav output.wav factor\n");
        return 1;
    }

    // Open files and determine scaling factor
    FILE *input = fopen(argv[1], "r");
    if (input == NULL)
    {
        printf("Could not open file.\n");
        return 1;
    }

    FILE *output = fopen(argv[2], "w");
    if (output == NULL)
    {
        printf("Could not open file.\n");
        return 1;
    }

    float factor = atof(argv[3]);

    copy_header(input, output);
    copy_samples(input, output, factor);

    // Close files
    fclose(input);
    fclose(output);
}

void copy_header(FILE *input, FILE *output)
    {
        uint8_t header[HEADER_SIZE];

        fread(header, sizeof(HEADER_SIZE), 1, input);
        fwrite(header, sizeof(HEADER_SIZE), 1, output);
        printf("header: %s; header_size: %lu; HEADER_s: %lu\n", header, sizeof(header), sizeof(HEADER_SIZE));
    }

void copy_samples(FILE *input, FILE *output, float factor)
{
    int16_t buffer;

    while (fread(&buffer, sizeof(int16_t), 1, input) != 0)
    {
        buffer = buffer * factor;
        fwrite(&buffer, sizeof(int16_t), 1, output);
    }
}

After a lot of digging, I found that the output for:

printf("header: %s; header_size: %lu; HEADER_s: %lu\n", header, sizeof(header), sizeof(HEADER_SIZE)); Would be:

header: RIFFDb; header_size: 44; HEADER_s: 4

Why did the value of sizeof(HEADER_SIZE) change to 4? Am I completely missing something here? Did I approach this problem right?

I fixed the error in my code by using: fread(header, sizeof(header), 1, input);

But i want to know why and how I borked this code. Thanks in advance!


Solution

  • When looking at these lines:

        uint8_t header[HEADER_SIZE];
    
        fread(header, sizeof(HEADER_SIZE), 1, input);
        fwrite(header, sizeof(HEADER_SIZE), 1, output);
    

    You seem to be under the impression that, after the declaration of header, that the size of HEADER_SIZE is now linked to the size of header. That is not the case.

    The sizeof operator evaluates to the size in bytes of its operand. In the case of sizeof(HEADER_SIZE) the operand is the variable HEADER_SIZE (or more accurately, the parenthesized variable) whose type is int. This evaluates to 4 because an int takes up 4 bytes on your system.

    This caused problem in your code by only reading in 4 bytes instead of 44 as you intended.

    This works:

    fread(header, sizeof(header), 1, input);
    

    Because sizeof(header) gives you the size in bytes of the header array which is 44.

    This would also work:

    fread(header, HEADER_SIZE, 1, input);
    

    As it would be passing in 44 as the number of bytes to be read.