Which is the better way to get the status of a post?

None of them.

A, C and D all indicate that you’re inside a loop, and want the status for the current post. But if that’s the case then the first line on all of them is redundant. This is all you’d need if you want the status of the ‘current post’:

$current_post_status = get_post_status();

get_post_status() calls get_post() internally, which gets the current post for you. So providing it the ID of the current post, or the current post’s object, is unnecessary.

If you want the status of a post that is not the current post, then use the get_post_status() function and pass a full post object, if you have it:

$current_post_status = get_post_status( $post );

Otherwise use the function and pass an ID:

$current_post_status = get_post_status( 12 );

You should prefer passing the whole post object, rather than just the post ID. This is because otherwise the get_post_status() function will need to do the work internally to turn the ID into a post object itself, which is a waste of time if you’ve already got the full object.

The advantage of get_post_status() over $post->post_status is that the function has additional logic to handle the status of attachments, which might be relevant, and it also passes the result through the get_post_status filter, which could be important if you’re using a plugin that interacts with the post status in some way.

If a function is available to get a post’s property, then that will usually be preferable to accessing the property directly, if only because it will apply the correct filters to the result.