The second one is easy. If you do
char *str2;
str2 points to nowhere and dereferencing it will cause an error.
If you do
char str2[80];
str2 is an array and if it is used like a pointer the pointer points to the start of the array - valid memory.

The first one is more complicated.
Every string literal you have in your code is hard coded into the exe and has a specific address. This is why char * str = "Hello" is valid. The pointer now points to the memory location of "Hello".
Then you call the function. Indeed, it is a call by value. The value of the pointer variable (the memory address) is copied to a new pointer variable. The string behind it is still the same, this is why the cout works. Both str and abc point to the string, but they are different variables.
When you do
abc = "meory";
you assign the memory address of "meory" to abc. str still points to "Hello". Therefore, when you then call cout, it outputs "Hello" again.

To make it work you would have to do
strcpy(abc, "meory");
but abc points to read-only memory (a location in the exe file), so this would cause an access violation.
Here is the code that really works:
PHP Code:
#include<iostream>  // the .h ending is no longer used in C++ headers
#include <cstring> // for strcpy
using namespace std;

// although some compilers seem to accept it, it is not a good idea
// to put function prototypes inside other functions
void ox(charabc);

void main() 

char str[50]; // reserve some memory
strcpy(str"Hello"); // [b]copy[/b] the string into the memory
ox(str); 
cout<<str// should now output "meory"


void ox(charabc

cout<<abc
strcpy(abc"meory"); // [b]copy[/b] the string into the memory