First, what is a string? It's an array of characters and then a \0. Just to make sure we all agree on that.
So the question is, can you pass an array of characters by value? And the answer is yes, but only if it's inside a struct or union:
struct String40Chars {
char str[41];
};
void f(struct String40Chars s) {
// s was passed by value - including s.str
}
However, you can't pass an array directly due to a historical quirk:
void f(char str[41]) {
// you would think this would work,
// but actually, the compiler converts it to void f(char *str)
}
That is unfortunate for people who really do want to pass arrays by value.
Luckily you usually don't need to. In every case I can think of, a pointer is good enough, and faster as well since it doesn't need to copy the array. Maybe you can elaborate on why you need to pass an array by value.
P.S. You talk about "strings being pointers" but that is nonsense. Strings are arrays. You can have pointers to arrays but the pointer is not the array.