It's because you cannot pass an array directly to a function. You can only pass a pointer to an element within such an array.
In function parameters, the [] does not mean array, it means a pointer
int dupes(int a[])
is exactly the same as
int dupes(int *a)
When you use the name of an array as a value, it actually means the pointer to the 1. element in that array. And a pointer is just that, a pointer. It doesn't know it's pointing into an array of a given size.
So e.g. int *a = x; will assign a pointer to the first element in x to a- Same thing when you call a function, dupes(x) will pass a pointer to the first element in x as the argument to the dupes function. This is exactly the same as calling dupes(&x[0])
Inside the dupes() function, its argument is just a pointer. So sizeof x/sizeof x[0] is equivialent to sizeof(int*)/sizeof(int), which is 1 if your pointers are the same size as an int.
(However, since you passed a pointer to the 1. element in an array, you can increment that pointer to access the other elements. e.g. x + 2 will make x point to the 3. element (counting from 1) in that array. And if you dereference that pointer, you get its value: *(x + 2). And remember that as a value, x[2] is the same as *(x + 2)