C language learning journey is relatively rough, when I think of that year at the university of c language class, is the first semester freshman year, when the more foolish, also don’t know what are learning c language, and at the beginning c language classes, I don’t know why he always arranged in the first and second class, often don’t come, ah, disappointed, and then think of c computer language for the first time, Since I don’t even know scanf and printf, face covering…

Later in the second semester of the freshman changed, began to learn 51 microcontroller, 51 microcontroller with C language, but with the more basic C, and then until the senior internship, was hit by the whole body, when even the structure will not be used, with no need to mention the file operation, ah, again melancholy.

After this time, I worked hard again and learned C language again. After this development, THE level of C language rose straight, pointer and file operation, not to mention, but I did not leave notes at that time.

Until recently, and want to collate the unity of knowledge before again to remember to write the c language project, this project, do not intend to introduce c language syntax, those things are now a lot of video, and I think I also write boring, so this time chose those who missed, and further to understand c as far as possible, the operating system, the level, I hope it sticks. Come on.

1.1 Hello World

To talk about the first section of C language, we will certainly think of the famous Hello World, here our first C language program is also Hello World, at this time reminds me of a joke, said that after a programmer retired, began to practice calligraphy, and then wrote the first calligraphy is Hello World. Of course, the meaning of ridicule is more.

#include <stdio.h>

int main(int argc, char **argv)
{
    printf("hello world\n");

    return 0;
}
Copy the code

That’s it. When we’ve written a program, how can it be running?

We know that the computer can only machine code, which is a binary, we write the code above, with the binary difference is very big, so we need to use the compiler, c language, c language compiler, we through the c language compiler, can put the above code into machine code, and then to the CPU to perform.

Here I choose to use Ubuntu system, because Linux system can play a lot, some system operation, certainly better than Windows.

1.2 One-Step Compilation

1.2.1 GCC

When I was in college, I used vc++6.0. I don’t know if anyone remembers this software now, but now I basically use vs2019. Directly on vc++6.0, I can directly compile and execute it. So I chose to do it on Linux, completely manually.

The compiler of choice is GCC, relatively famous GCC, how to install Ubuntu virtual machine, how to install GCC, here will not talk, this is speaking C language.

We can go directly to the code directory, check whether GCC is installed successfully, check the command, the old method GCC -v

The last line also tells me that MY GCC version is 5.4.0 and ubuntu version is 16.04.

1.2.2 compilation

The tools are in place. What are you waiting for? Start compiling directly, which is what we usually use when writing code:

-o is the GCC argument, meaning that the generated output file name is hello_world. If the output file name is not specified, GCC defines the output file name as a.out by default.

1.2.3 run

It’s all compiled, so let’s go ahead and run.

Is that the end of this article? Not really. It’s gonna be fun, everybody. It’s gonna be important.

1.3 Step-by-step Compilation

1.3.1 GCC Common parameters

Let’s start by looking at the common arguments to GCC

parameter meaning
-o file Specifies the output file name
-E Preprocessing only
-S Only preprocessing and compilation are performed
-c Only preprocessing, compilation, and assembly are performed

The arguments that we used when we compiled, of course GCC has a lot of arguments, so I won’t write them down here.

1.3.2 Compilation Process

Having said the parameters for GCC compilation, let’s take a quick look at the step-by-step compilation process.

  1. Preprocessing: processing header files, including header files, macro expansion, and often conditional compilation; Also remove the code comment, here does not check the code syntax error. (here the corresponding is gcc-e)
  2. Compile: Check for syntax errors and compile preprocessed files into assembler files. (this corresponds to gcc-s)
  3. Assembler: Assembler files into object files, also known as binary files (this corresponds to -c, can not be used)
  4. Linking: Code written in C also references other libraries, so you need to link functions that call other libraries so that they can be executed.

Here is the illustration:

1.3.3 pretreatment

Next, we will analyze these files respectively to see if they are the same as what we said above. (Actually it doesn’t take analysis to know the above is true, hahaha)

The hello_world. I file is quite long, so here are some snippets:

# 1 "hello_world.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "hello_world.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 27 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 367 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 1 3 4
# 410 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4
# 411 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4
# 368 "/usr/include/features.h" 2 3 4
# 391 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 1 3 4
# 10 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs-64.h" 1 3 4
# 11 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 2 3 4
# 392 "/usr/include/features.h" 2 3 4
# 28 "/usr/include/stdio.h" 2 3 4

// The flags above is to locate the file location and flags
// # linenum filename [flags]
// The following parameters mean:
// 1 This indicates the start of a new file.
// 2 This means to return to a file (after including another file).
// 3 This indicates that the text below is from the system header file, so some warnings should be suppressed.
// 4 This indicates that the text below should be treated as wrapped in an implicit extern "C" block.

// The preprocessing file is located in the header file.typedef unsigned char __u_char;
typedef unsigned short int __u_short;
typedef unsigned int __u_int;
typedef unsigned long int __u_long;


typedef signed char __int8_t;
typedef unsigned char __uint8_t;
typedef signed short int __int16_t;
typedef unsigned short int __uint16_t;
typedef signed int __int32_t;
typedef unsigned int __uint32_t;

typedef signed long int __int64_t;
typedef unsigned long int __uint64_t;

// These are the types defined by THE C language itself.extern int fprintf (FILE *__restrict __stream,
      const char *__restrict __format, ...);




extern int printf (const char *__restrict __format, ...);

extern int sprintf (char *__restrict __s,
      const char *__restrict __format, ...) __attribute__ ((__nothrow__));

// This is the printf function. Our main. C calls printf. #3 "hello_world.c"
int main(int argc, char **argv)
{
    printf("hello world\n");

    return 0;
}
// This is our code
Copy the code

After preprocessing, it turns out that stdio.h contains so many things. It’s a really powerful C language.

1.3.4 compilation

Next we need to compile the preprocessed files into assembler files:

.file "hello_world.c" .section .rodata .LC0: .string "hello world" .text .globl main .type main, @function main: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 subq $16, %rsp movl %edi, -4(%rbp) movq %rsi, -16(%rbp) movl $.LC0, %edi call puts movl $0, %eax leave .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE0: .size main, .-main .ident "GCC: (Ubuntu 5.4.0-6Ubuntu1 ~16.04.12) 5.4.0 20160609".section.note.GNU-stack,"",@progbitsCopy the code

Assembly files look familiar with a lot, but this section will not analyze assembly, save the next section analysis, preprocessing next class will not talk about, so just so detailed.

1.3.5 assembly

This generates the binary file directly:

The Linux object file format is. Elf, and then you can analyze the elf structure.

1.3.6 link

As long as the link is under multiple C files, because each C file is compiled into a.o file, which is a binary file, then the linker will link multiple.o files together to produce an executable file.

On a cursory look, this file is indeed about the same as the compiled.o, it seems to be a lot larger, you can link some libraries.

When it comes to linked libraries, there is an LDD command that allows you to see what libraries are linked to. This makes it obvious that you are linking to dynamic libraries.

1.4 summarize

Did not expect a relatively simple compilation link since also wrote so many words, the problem is to write so many words, there are a lot of things, said to keep the later analysis, think about the head, but have written, try to write well, and line and cherish.