1

I thought I understood c and pointers but was just debugging someone elses code that I thought should not work but did. As a (crude) example....

void clear_buffer(char* buff, int len)
{
    while(len)
    {
        *buff++ = ' ';
        len--;
    }
}

main()
{
    char buffer[10];

    clear_buffer(&buffer,10);   // 1. what I found, it still works...
    clear_buffer(buffer,10);    // 2. what I would have wrote
}

What suprised me was that both calls above do work exactly the same way. The first one gives a compiler warning (incompatible pointer types) but it still builds and runs correctly. So my question is: is this the expected behaviour in C or is it just the compiler I am using being clever and fixing a bug? fwiw, this is using the microchip xc16 compiler.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Toby
  • 131
  • 2
  • 8
  • `buffer` is of type char array. arrays decay implicitly when you pass them to a function taking a pointer. It is valid, But I would prefer passing `&buffer[0]` instead. – Raildex May 25 '21 at 10:45
  • To clarify the duplicate: once the address is received by the `clear_buffer` function, it will be interpreted as a `char*` *whatever* the argument type was. As the array's address is the same as the address of its first element, your program works. – Adrian Mole May 25 '21 at 10:50
  • "but it still builds and runs correctly" Please see [What must a C compiler do when it finds an error?](https://software.codidact.com/posts/277340) – Lundin May 25 '21 at 11:01

2 Answers2

2

In the expression clear_buffer(buffer, 10), buffer is converted to a pointer to its first element, so is equivalent to &buffer[0]. In the expression clear_buffer(&buffer, 10), buffer is not converted to a pointer to its first element because it is the operand of the & address operator. That is one of the exceptions to the rule of arrays decaying to pointers in expressions. (The other exception to the rule is the sizeof operator.)

The first element of an array is at the same address as the array itself, so &buffer and &buffer[0] have the same address, but different types. &buffer has type char (*)[10] (pointer to array [10] of char), and &buffer[0] has type char *.

The warning is due to the pointer type mismatch in the call clear_buffer(&buffer, 10).

Ian Abbott
  • 15,083
  • 19
  • 33
1

This call

clear_buffer(&buffer,10);

is incorrect and the compiler shall issue an error message.

The type of the expression &buffer is char ( * )[10] while the type of the corresponding function parameter is char * and there is no implicit conversion from one type to another.

The program works as expected because the values of the expressions &buffer and buffer are the same: it is the address of the extent of memory occupied by the array though types of the expressions are different.

Consider another example. Here is a demonstrative program

#include <stdio.h>

int main(void) 
{
    struct A
    {
        int x;
    } a = { 10 };
    
    printf( "&a   = %p\n", ( void * )&a );
    printf( "&a.x = %p\n", ( void * )&a.x );

    return 0;
}

The program output is

&a   = 0x7ffef64abb84
&a.x = 0x7ffef64abb84

as you can see the program outputs equal addresses though the types of the expressions &a and &a.x are different.

The same takes place in your program. The address of a whole array equal to the address of its first element though the types of the whole array and its element are different.

In fact in your function you are reinterpreting the pointer to the whole array of the type char ( * )[10] as a pointer to the first array element of the type char *.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335