cstructbit-manipulationbit-shiftid3v2

Bitwise array error


I am new in programming and even more in c programming. I am trying to read a binary file and then do bitwise process. Sample of my code and how I have written my program so far.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <inttypes.h> /* Use C99 format specifiers: "%" PRIu8 "\n", "%" PRIu32 "\n" */

typedef struct{
  uint32_t size; /* Unsigned int 4 bytes (32 bits) */
}mp3_Header;

int main (int argc, char *argv[]) {

mp3_Header first;
unsigned int memory_int[4];


FILE *file = fopen( "song.mp3" , "rb" );

/* 1 Byte flags + revision_number 1 Byte + major_version 1 Byte + header_id 3 Bytes = 6 */
if ( fseek( file , 6 , SEEK_SET ) == -1 ) {
  fprintf( stderr, "Not able to fseek at possition 6" );
  return EXIT_FAILURE;
}

if ( fread( memory_int , sizeof(memory_int) , 1 , file ) != 1) {
  printf("Could not read first.size\n");
  exit (0);
}

printf ("This is first.size before sync_safe: %u\n", memory_int);

first.size = (memory_int[3] & 0xFF) |
     ((memory_int[2] & 0xFF) << 7 ) |
((memory_int[1] & 0xFF) << 14 ) |
((memory_int[0] & 0xFF) << 21 );

printf ("This is first.size after sync_safe: %" PRIu32"\n", first.size);

fclose(file);
return 0;
}

When I am compiling the code I get the error message:

error: subscripted value is neither array nor pointer nor vector first.size = (first.size[3] & 0xFF) |

I tried to declare another value as:

unsigned int memory_int[4];

When I compile the code I get the warning:

warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 2 has type ‘unsigned int *’ [-Wformat=] printf ("This is memset memory_int: %u\n", memory_int);

Although that I changed the %" PRIu32" to %u I still get this warning.

I know so far that when I am using typedef struct I can call the content by using name.parameter, and the program seems to be operating correctly when I call first.size the value when need it. But I encounter a problem when I am trying to bitwise because I am asking the value to be broken in bits. Theoretically it should be possible since I have define it as 32 bit, but practically I am missing something extremely small. I tried to assign another value as uint32_t and also as unsigned int size[4] both times not successfully. Can some explain to me the reason and how to solve this problem?


Solution

  • There are some things to be modified in your code.

    First, use " " in the name of the file to be read, as the fopen synax is

    FILE *fopen(const char *path, const char *mode);
    

    This way, the filename [path] will be const char *

    Second, add the following lines to your code [after the existing line].

    FILE *file = fopen("song.mp3" , "rb" );
    if (!file)
            {
             printf("Unable to open the file for reading\n");
             exit (0);
            }
    

    It will help you handle some unexpected conditions like "File does not exist"

    Third, declare memory_int as an array of unsigned int containing 4 elements.

    unsigned int memory_int[4] = {0};
    

    Finally, altogether, the code looks like this.

    #include <stdint.h>
    #include <unistd.h>
    #include <inttypes.h> /* Use C99 format specifiers: "%" PRIu8 "\n", "%" PRIu32 "\n" */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdint.h>
    #include <unistd.h>
    #include <inttypes.h> /* Use C99 format specifiers: "%" PRIu8 "\n", "%" PRIu32 "\n" */
    
    typedef struct{
            uint32_t size; /* Unsigned int 4 bytes (32 bits) */
    }mp3_Header;
    
    int main (int argc, char *argv[]) {
    
            unsigned int memory_int[4] = {0};
            mp3_Header first;
    
            FILE *file = fopen("song.mp3" , "rb" );
            if (!file)
            {
                    printf("Unable to open the file for reading\n");
                    exit (0);
            }
    
            /* 1 Byte flags + revision_number 1 Byte + major_version 1 Byte + header_id 3 Bytes = 6 */
            if ( fseek( file , 6 , SEEK_SET ) == -1 ) {
                    fprintf( stderr, "Not able to fseek at possition 6" );
                    return EXIT_FAILURE;
            }
    
            if ( fread( memory_int , sizeof(memory_int) , 1 , file ) != 1) {
                    printf("Could not read first.size\n");
                    exit (0);
            }
    
            printf ("This is first.size before sync_safe: %u %u %u %u\n", memory_int[0],memory_int[1],memory_int[2],memory_int[3]);
    
            first.size = (memory_int[3] & 0xFF) |
                    ((memory_int[2] & 0xFF) << 7 ) |
                    ((memory_int[1] & 0xFF) << 14 ) |
                    ((memory_int[0] & 0xFF) << 21 );
    
            printf ("This is first.size after sync_safe: %u\n", first.size);
    
            fclose(file);
            return 0;
    }
    

    Hope this works!!