Search code examples
carrayspointersgccgcc-warning

Why does taking sizeof(array) give warnings in a function, but not in main()?


I'm currently coding some encryption algorithm, and I am facing a GCC compilation error I can't understand. Here is the problem :

In my int main(void) function I got :

uint32_t block[2];
memset(block, 0x0, sizeof(block));
printf("%ld \n", sizeof(block));

Which looks okay for GCC.

Then, I pass this uint32_t array named block to a function :

void readOneBlockFromFile(int fd, uint32_t block[2]){
  if(fd == -1){
    perror("fd");
    errno = EIO;
    exit(errno);
  }
  int nb_bytes_read = 0;
  while(1){
    memset(block, 0x0, sizeof(block));
    nb_bytes_read = read(fd, block, sizeof(block));
    if(nb_bytes_read == -1){
      perror("read");
      exit(errno);
    }
    if(nb_bytes_read == 0){
      break; //EOF
    }
  }
}

And here I get some GCC warnings :

SPN.c: In function ‘readOneBlockFromFile’:
SPN.c:46:30: warning: ‘sizeof’ on array function parameter ‘block’ will return size of ‘uint32_t * {aka unsigned int *}’ [-Wsizeof-array-argument]
     memset(block, 0x0, sizeof(block));
                              ^
SPN.c:38:44: note: declared here
 void readOneBlockFromFile(int fd, uint32_t block[2]){
                                            ^~~~~
SPN.c:47:43: warning: ‘sizeof’ on array function parameter ‘block’ will return size of ‘uint32_t * {aka unsigned int *}’ [-Wsizeof-array-argument]
     nb_bytes_read = read(fd, block, sizeof(block));
                                           ^
SPN.c:38:44: note: declared here
 void readOneBlockFromFile(int fd, uint32_t block[2]){
                                            ^~~~~

So my GCC is giving me warning when I'm using block without using block[0] or *block.

I can't figure out why GCC gives me warning for this, as I can do the same stuff without any problem in main.


Solution

  • In your function heading

    void readOneBlockFromFile(int fd, uint32_t block[2])
    

    you declare block to be an array of size 2. However, in C an array is always pased as a pointer to its first element. Therefore sizeof will return the size of the pointer, not of the array.

    (In essence, declaring the size of an array you pass helps the compiler check your code, whether you pass the right arguments. In multi-demensional arrays the compiler lets you use [][] indexing. Without declaring the size of the array passed, that would not be possible.)

    You further seem to know already what size the array is, so pass that to read, e.g. sizeof(uint32_t [2]).


    In my opinion a more usefull interface is:

    int readOneBlockFromFile(int fd, void *block, int size)
    {
         int nb_bytes_read = read(fd, block, size);
         //...
         return nb_bytes_read;
    }
    int example(void)
    {
        uint32_t block[2];
        if (readOneBlockFromFile(1,block,sizeof(block))==0) {
            // EOF
        }
    }