Here's how HTTP protocol works:
You send this kind of header with your browser:
GET /questions/712326/why-cant-i-use-sessionstart-in-my-php-script-it-says-headers-are-already-sen HTTP/1.1
Host: stackoverflow.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fi; rv:1.9.0.8) Gecko/2009032609 Firefox/3.0.8 (.NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fi-fi,fi;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://stackoverflow.com/questions/tagged/php
Cookie: *censored*
Cache-Control: max-age=0
First server sends you headers:
HTTP/1.x 200 OK
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Expires: Fri, 03 Apr 2009 02:14:49 GMT
Vary: Accept-Encoding
Server: Microsoft-IIS/7.0
Set-Cookie: *censored*
Date: Fri, 03 Apr 2009 02:14:49 GMT
Content-Length: 9346
Then server sends you the actual page data
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd" >
<html>
<head>
<title>Why can't I use session_start() in my php script? It says headers are already sent. - Stack Overflow</title>
<link rel="stylesheet" href="/Content/all.min.css?v=2743">
..snip..
So you see you can't FIRST send HTML data (DOCTYPE) and then header data because header is already processed. You can go around with PHP's Output Control but more recommended is that you use MVC design where you buffer all data that user sees last.