The difference is the following:
p {} only is a master declaration for your whole page. Definitions here will be inherited by all p tags by default. It is like a default style for p tags.
.name p {} can be used to change the default setting to something else, which will have priority over the default declaration. Note that .name is a class in CSS, so you can reuse it several times, while #name is specific ID in you html code that you want explicitly to modify by css.
For example, if you are building up a forum, you can specify that all p tags by default show in red.
However, each post which is e.g. div, containing some p in it needs to be blue. So it will look like this
<body>
<p>All these will be shown in red</p>
<div class="posts" ><p>My blue content here</p></div>
</body> But if you want some special formatting do be applied on a specific section of your page only - e.g. header, footer, news, etc..., you should do it like this.
<body>
<p>All these will be shown in red</p>
<div class="posts" ><p>My blue content here</p></div>
<div id="sections_unique_name_here"><p>Only this here will be purple</p></div>
</body>
Note that classes (.name) can appear on a single page multiple times, while id's (#name) can appear on a single page ONLY ONCE!