There are actually two related but independent rules in play here.
One is that an expression of array type is, in most contexts, implicitly converted (at compile time) into a pointer to (i.e., the address of) the first element of the array.  The exceptions are when it's the operand of sizeof, when it's the operand of unary &, and when it's a string literal in an initializer used to initialize an array object.
The other is that a function parameter declared to be of an array type is really of a pointer type -- and if the array type includes a length, that length is silently ignored.  This is the rule that causes the behavior you're seeing.
Strongly recommended reading: Section 6 of the comp.lang.c FAQ.
EDIT : Your program has several errors that would prevent it from compiling, which means you couldn't have seen the results you say you're seeing.  You apparently re-typed the program when posting it here.  Instead, you should copy-and-paste the exact code as you fed it to the compiler.
Here's a corrected version of your code, with a bit of commentary added.
#include <stdio.h> /* required for printf */
void foo(const char data[10]) /* NOTE: The 10 is quietly ignored */
{
    char copy[10];
    /* syntax, [10] follows "copy", not "char" */
    const char copy1[10]; // = {};
    /* as above, and standard C disallows empty initializer */
    printf("%d", (int)sizeof copy);  // prints 10, as expected
    printf("%d", (int)sizeof copy1); // prints 10, as expected
    printf("%d", (int)sizeof data);  // prints 4 (sizeof (char*), as expected
    /*
     * "%i" or "%d" requires an int argument; sizeof yields size_t.
     * You need to convert the result.
     * "%d" is more common and idiomatic than the equivalent "%i"
     * When sizeof is applied to an expression, no parentheses are needed
     * (it's an operator, not a function
     */
}