[Courses] C Programming For Absolute Beginners, Lesson 1: Setting Up, First Program

jim jim at well.com
Mon Feb 6 02:28:08 UTC 2012


    You end your response with "all the best". All the best, 
indeed; I've never read such good stuff; big thanks! 
    A few questions and surmises: 
* How to configure things so that the #include < > point 
  to some other directory? 
* man stdio (not man stdio.h) gave me a headache, but I'll 
  come back to it. 
* I'm guessing that the final executable binary contains 
  almost nothing directly compiled in the stdio.h file 
  (because this program only calls printf (puts) and getchar). 
  Rather, (I'm guessing) that almost all of the contents 
  of the compiled binary is precompiled code having to do 
  with loading the executable's main function. 
* Using vi I search for ld-linux.so.2 or libc.so.2 and find 
  neither. Searching for #include I find    libio.h  
  bits/stdio_lim.h  bits/sys_errlist.h 
  Searching libio.h for #include yields  _G_config.h  but 
  neither libc nor ld-linux. 
  Searching _G_config.h for #include yields  bits/types.h  
  stddef.h  wchar.h  but neither libc nor ld-linux. 
  I give up. I assume puts and getchar are names of functions 
  in libc and somehow the #include <stdio.h> directive 
  specifies a way for the compiler to extract from libc the 
  code for both puts and getchar. (Also, there's the matter 
  of resolving a call to printf to be a call to the less 
  expensive puts--for the reason that there is only one 
  argument to printf in the source code.) 
* what's an "anchor"? something in the stdio.h file or in 
  the libc library or in some particular function in libc? 

with much thanks... 




On Mon, 2012-02-06 at 11:45 +1100, Jacinta Richardson wrote:
> On 06/02/12 10:49, jim wrote:
> >      Note that the #include preprocessor directive seems to take
> > <stdio.h>
> > as an argument.
> >      The<  >  angle bracket characters have a special meaning:
> > /usr/include/
> >
> 
> The angle brackets refer to the system directories, which might not always be 
> /usr/include but could even be /opt/usr/include etc.
> 
> >      The #include preprocessor directive opens the file and pastes
> > its entire contents into the C program at that location. This
> > means what the compiler compiles is not only the code but all of
> > the code in the stdio.h file, yes?
> stdio.h is a *header* file.  This means it's actually just the headers for an 
> underlying pre-compiled C library.  So when we include the header file, we 
> compile links to the existing C library.  So when we compile our program we 
> compile all of our code and all the headers they include and get all the links 
> to the functions defined in those headers etc.  Note that stdio.h also includes 
> other headers, which may also include other header files recursively.  (There 
> are ways of preventing loops that I imagine we'll cover much, much, much later).
> 
> Note that this linking to existing pre-compiled C libraries makes our program 
> much smaller than if we included everything in it directly, but it also makes 
> the compiled code non-portable.  You can write, compile and execute the code 
> Carla's given us, on Windows and *nix without issue; but you cannot take the 
> Windows executable and run it on *nix or visa versa.  In fact, as you may 
> eventually discover, you can't take a *nix executable and assume it'll run on a 
> different flavour of *nix.  It used to be that you couldn't even necessarily run 
> it on different versions of the same *nix flavour, although I believe that 
> that's gotten a lot better over the last decade and a half (ymmv).
> 
> Later I expect Carla will talk about creating our own header files and linking 
> shared object files but right now that's way out of scope.
> 
> >      How does one "look up the spec" for stdio.h?
> >
> 
> man stdio
> 
> >      A look at my working directory:
> > ls -l
> > -rwxr-xr-x 1 jim jim 7180 2012-02-05 15:18 welcome
> > -rw-r--r-- 1 jim jim  108 2012-02-05 15:18 welcome.c
> >
> > ---------------------^^^^---------------------------
> >
> >      The welcome.c source code is 108 bytes, but the welcome
> > binary program is 7180 bytes.
> >      Wait a minute. The stdio.h file is 31KB, a lot bigger.
> > What's going on?
> >
> 
> The stdio.h has a lot of definitions, comments, whitespace etc in it that pretty 
> much vanishes when we compile it.  Thus your executable is bigger than your 
> source file because it does contain the information from stdio.h, but it loses 
> information such as variable names, function names, comments, #defines etc.
> 
> > $ strings welcome
> > strings lchix
> > /lib/ld-linux.so.2
> > __gmon_start__
> > libc.so.6
> > _IO_stdin_used
> > puts
> > getchar
> > __libc_start_main
> > GLIBC_2.0
> > PTRh0
> > [^_]
> > Hello, and welcome to the Beginning C Course!
> >
> >      There are not many strings in the welcome binary file.
> >      How'd the welcome binary file get to be over 7KB but not
> > have hardly any of the stdio.h file contents?
> 
> Because large parts of the binary bits are links to the precompiled libraries.
> 
> >      And what's up with the Martian (like [^_] and /lib/ld-linux.so.2
> > and __gmon_start__ and _IO_stdin_used and PTRh0 and so on)?
> >
> 
> strings doesn't exist to make compiled code easier for humans to read.  It 
> exists to pull out sequences of two or more ascii characters in a row.  I'm 
> actually surprised there isn't more Martian. ;)  ([^_] and PTRh0 are Martian and 
> can be ignored)
> 
> /lib/ld-linux.so.2 is a shared object file.  It's what is going to be used to 
> help your executable find any other shared object files it needs.  More here: 
> http://www.cs.virginia.edu/~dww4s/articles/ld_linux.html
> 
> __gmon_start__ is an anchor to where the relevant stuff for <sys/gmon.h> starts.
> 
>   _IO_stdin_used is an internal symbol used by libio.h (which stdio.h 
> includes).  I'm guessing this is set because our code uses getchar which gets a 
> character from STDIN.
> 
> >      How come one of strings is
> > puts?
> 
> man -s3 puts
> 
> printf is a very fancy way of printing characters to the screen.  The "f" at the 
> end of the function name tells us that it can take a format string so we could 
> write:
> 
>      printf("%-50s", "Hello World!");
> 
> if we wanted to.  With straightforward strings like this that have no variables 
> that need to be worked out at run time, we can convert the (more expensive) call 
> to printf(ormat) to a simple call to puts(tring) to output it to STDOUT.
> 
> >      I used the printf() function, not the puts() function.
> 
> As above.
> 
> >      I'm betting that libc.so.6 stores the binary code for printf
> > and puts and getchar on other stdio.h functions, yes?
> 
> Probably, but you don't need to care about those details. You need only to 
> include the stdio.h file and whichever precompiled library that currently houses 
> the files you need is the one that will be used.
> 
> >      What's __libc_start_main about? And GLIBC_2.0 ?
> >
> 
> GLIBC_2.0 is the GNU Shared Lib C library 2.0.
> 
> __libc_start_main is another anchor.  Presumably to the start of the compiled 
> links to libc.
> 
> >      And how come the "Hello, and welcome tothe Beginning C Course!"
> > is on the very bottom?
> >
> 
> Things get compiled in order.  All the stuff above was related to your inclusion 
> of stdio.  Everything after that is your code.
> 
> All the best,
> 
>      J
> 
> _______________________________________________
> Courses mailing list
> Courses at linuxchix.org
> http://mailman.linuxchix.org/mailman/listinfo/courses




More information about the Courses mailing list