In depth analysis of how to program the C language under Linux

  • 2020-04-01 23:30:14
  • OfStack

1. Source program compilation
      Under Linux, to compile a C source program, we use the GNU GCC compiler. Here's an example of how to use the GCC compiler.
Suppose we have the following very simple source program (hello.c):
  Int main (int arg c, char * * argv)
  {
Printf (" Hello Linux/n ");
  }

To compile this program, we simply execute it from the command line:
GCC -o hello hello. C
The GCC compiler will generate a hello executable for us. If we execute./hello, we can see the output of the program.

GCC compiler has many options, generally we only know a few of them will be enough. -o option we already know, said we require the output of the executable file name. The -c option said we only request object code compiler output, output and unnecessary executable file. The -g option said we are asking the compiler when compiling information after we debug the program.

Knowing these three options, we can compile the simple source program we wrote ourselves. If you want to know more about the options, you can see the help documentation for GCC, where there are many detailed instructions for the other options.

2. Write a Makefile
      Suppose we have the following such a program, the source code is as follows:


  # include "mytool1. H"
  # include "mytool2. H"

  Int main (int arg c, char * * argv)
  {
  Mytool1_print (" hello ");
  Mytool2_print (" hello ");
  }


# # ifndef _MYTOOL_1_H
# define _MYTOOL_1_H

  Void mytool1_print print_str (char *);

# endif


  # include "mytool1. H"
  Void mytool1_print print_str (char *)
  {
    Printf ("This is mytool1 print %s/n",print_str);
  }


# # ifndef _MYTOOL_2_H
# define _MYTOOL_2_H

  Void mytool2_print print_str (char *);

# endif


  # include "mytool2. H"
  Void mytool2_print print_str (char *)
  {
    Printf ("This is mytool2 print %s/n",print_str);
  }


And of course since this program is so short we can compile it this way
GCC - the main c. C
GCC -c mytool1. C
GCC -c mytool2. C
Gcc-o main main. O mytool1. O mytool2. O
This way we can also generate the main program, which can be a hassle from time to time, but if we consider that if one day we modify one of the files (say, mytool1.c), why would we want to retype the command above? Maybe you will say, this is easy to solve, I write a SHELL script, let she help me to finish no. Yes for this program, can play a role. But when we think of things a bit more complicated, if we have hundreds of program source code, will also compiler to new one by one to compile?

Therefore, clever programmers came up with a good tool to do it, that's make. As long as we perform the following make, can to solve the above problem. Before we implement the make, we need to write a very important document. -- Makefile. For the above that program, likely a Makefile file is:
#     This is the Makefile for the program above
Main: the main o mytool1. O mytool2. O
Gcc-o main main. O mytool1. O mytool2. O
The main. O: main. C mytool1. H mytool2. H
GCC - the main c. C
Mytool1. O: mytool1. C mytool1. H
GCC -c mytool1. C
Mytool2. O: mytool2. C mytool2. H
GCC -c mytool2. C

With this Makefile, however, whenever we modify a file in the source program, we just execute the make command, and our compiler only compiles the files related to the file we modified.
Now let's learn how makefiles are written.

In a Makefile, the beginning line of # is the comment line.
Target: the components
TAB rule

The first line represents the dependencies. The second line is the rule.
For example, the second line of the Makefile above us
Main: the main o mytool1. O mytool2. O
Components that represent our target main are main.o mytool1.o mytool2.o when the dependent objects are modified after the target is modified, we execute the command specified on the rule line
Makefile has three very useful variables: $@,$^, and $ < Respectively mean:
$@-- target file,$^-- all dependent files,$ < The first dependency file.
If we use the above three variables, then we can simplify our Makefile file as:
This is the simplified Makefile
Main: the main o mytool1. O mytool2. O
GCC -o $@ $^
The main. O: main. C mytool1. H mytool2. H
GCC - c $ <
Mytool1. O: mytool1. C mytool1. H
GCC - c $ <
Mytool2. O: mytool2. C mytool2. H
GCC - c $ <

Our Makefile has been simplified a bit, but people sometimes want to keep it simple. Here we will learn the default rules for a Makefile
C.o:
GCC - c $ <

This rule means that all.o files are dependent on corresponding.c files. For example, mytool.o depends on mytool.c, so the Makefile can also be:
This is again a simplified Makefile
Main: the main o mytool1. O mytool2. O
GCC -o $@ $^
C.o:
GCC - c $ <

Okay, our Makefile is almost there, so if you want to know more about the Makefile rules, you can check the documentation.

3. Links to libraries
      Try compiling the following program


  # include

  Int main (int arg c, char * * argv)
    {
                A double value.
  Value: printf (" % f/n ", Value);
    }

The program is fairly simple, but when compiled with gcc-o temp temp.c, the following error occurs.
/ TMP/cc33Kydu. O: function In ` main ':
/ TMP/cc33kydu.o (.text+0xe): undefined reference to 'log'
Collect2: ld returned 1 exit status

The mistakes because the compiler can't find the realization of a log. Although we include the header file, right but we at compile time or to connect to determine library. Under Linux, in order to use the mathematical functions, we must and math library link, so we want to join - lm options. GCC -o temp temp. C - lm can correct this compilation. Maybe someone ask, how we are using the printf function not connected in front of the library? Is that for the realization of the function of some commonly used, the GCC compiler automatically to connect some commonly used library, so we don't need to specify. Sometimes we also specify when compiler library paths, this time we want to use the compiler the -l option to specify path. For example we have a library in/home/Hoyt/mylib, so that when we compile plus -l /home/ Hoyt/mylib.for some standard libraries, we do not need to specify the path. As long as they are under the path from the default library, we can.

Another problem is, sometimes we use a function, but we don't know the name of the library. What do we do? I'm sorry, I don't know the answer to this question, I only have a stupid way. First of all, I to the standard library path below to see if there are any and I use the function of library, so I found the thread (thread) functions of the library files (libpthreads. A). Of course, if you cannot find, just a stupid way. Such as sin I am looking for the function of the library. Had to use the nm - o/lib / *. So | grep sin > ~ / sin command and then watch the ~ / sin file, try it. In the midst of sin file, I will find such a line of libm - 2.1.2. So: 00009 fa0 W sin so I will know that sin in libm - 2.1.2. So the repository, I use - lm option is ok (the version of the logo, remove the lib in front of and behind the leaves m so is - lm). If you know how to find, please hurry up to tell me, I will very grateful. Thank you!

4. Program debugging
      The program we write is unlikely to be successful all at once. In our program, there will be a lot of unexpected errors, which is the time to debug our program.

The most common debugging software is GDB. If you want to debug the program in the graphical interface, then you can now choose XXGDB. Remember to add the -g option at compile time. . But I don't like to use GDB to track a program is very vexed, I usually use in the middle of the program of the output value of the variable to the debugger. Of course, you can choose their own way, it is not necessary to learn other people's. Now there are many IDE environment, it has been bring their own debugger. You can choose a few to try to find out their favorite one.

5. Header and system help
      Sometimes we only know the general form of a function, do not remember the exact expression, or do not remember the function in the header file to explain.

, for example, we want to know to fread the exact form of the function, as long as we perform the man fread system will output the function is explained in detail. And the function of the header file. If we want to write this function, when we perform man write, output the result is not what we need. Because we want to write this function, but it is write the command description. In order to get the write function that we need 2 write man. Two means that we use write, which is a system call function, and three means that we use C library function.

Remember that man is our best assistant at all times.


Related articles: