Unlike C++, which actually extends C so that you can do things like "new" a char*, ObjC is, as porneL says, purely a superset and in many ways just some fancy syntactic sugar. +alloc isn't even strictly a language construct. It's just ObjC code that eventually calls malloc() and stores some stuff in an objc_object struct pointer, which you can access manually using standard C -> notation.
If you're interested in how all this works, The ObjC Runtime Programing Guide is a good place to start (though it doesn't discuss +alloc particularly, it demystifies objc_msgsend).
To your specific question, C data types are put on the stack if you do not allocate them on the heap with malloc(). ObjC objects always are allocated on the heap. But the analogy to C# is not really helpful in my opinion. Consider the following:
int x;
int *y;
NSObject *z;
"x" is what you're calling a "value type." Both y and z are what you're calling "reference types." It's not that two are C and one is ObjC; it's that two of them are pointers, and so are almost certainly pointing into dynamic memory on the heap. This is why you never have a non-pointer ObjC object ("id" is just a pointer to an objc_object struct). This is why you can use C pointer notation on ObjC objects to fetch they're ivars (you shouldn't, but you can). It's all just C.