What you are doing is clearly UNDEF, but.. Let's try to understand WHY it works with ints and not with chars..
TL;DR: printf uses the stack, overwriting some of the space pointed by str, but since the int array is bigger in memory than the char array, it is "far ahead" in the stack and doesn't get overwritten.
An int is 4 bytes, so 256 ints will be 1024 bytes.
If the array is in the stack, this will point to RBP - 1024 for example.
With chars, a char is 1 byte, 256 chars will be 256 bytes.
If the array is in the stack, this will point to RBP - 256 for example.
What does this mean? the str pointer will point to 1024 or 256 bytes "ahead" of the current stack pointer when foo returns.
SO.. when you call strcpy(str, "yourstring"); that memory could get overwritten with the stack that strcpy and printf uses. The thing here is that it IS overwritten but not all the stack, just a little, but enough to cover 256 bytes, and thus, that function can overwrite the copied string, this doesn't happen with your int array, because the string will be copied 1024 bits ahead of the stack pointer and strcpy and printf don't use so much stack.
Let me show you how your stack will end up:

If you change the size of the char array it will probably work.
All of this is undefined behaviour and completely depends on your architecture, computer and compiler. I'm using Linux x86_64 at the moment.