C language basic knowledge finishing

Preface

This article organizes the basic knowledge of C language for daily reference in development.

C data type

Types of description
basic type They are arithmetic types, including two types: integer types and floating-point types
Enumerated type They are also arithmetic types and are used to define variables that can only be given a certain discrete integer value in the program
Derived type They include: pointer types, array types, structure types, union types, and function types.
void type The type specifier void indicates that no value is available.

printf

Code format description
%c character
%d Signed integer
%i Signed integer
%e Scientific notation, use lowercase e
%E Scientific notation, use capital E
%f Floating point
%g Use the shorter of %e or %f
%G Use the shorter of %E or %f
%O Octal
%s String of characters
% u Unsigned integer
%x Unsigned hexadecimal number, use lowercase letters
%p A pointer
%n The parameter should be a pointer to an integer pointing to the position where the number of characters is placed
%% A% sign

Character pointer and character array

    char *p = "hello"; // 字符串常量池地址赋值给p,即p指向了字符串常量池的hello
    char *p1 = "hello";
    char c[10] = "hello"; // 是把字符串常量池里的hello strcpy给了c

    printf("%p, %p, %p\n", p, p1, c); // p和p1指向同一个地方
    printf("%d, %d, %d, %d\n", (p == p1), (*p == *p1), (c == p), (*c == *p));
    printf("%c, %c\n", *c, *p);

    c[0] = 'H'; // 可以赋值,在栈空间上
//    p[0] = 'H'; // 会崩溃,在常量池里,不可写
    puts(c);

    char *p2 = malloc(10 * sizeof(char));
    strcpy(p2, "hello");
    p2[0] = 'H';
    puts(p2); // 可以修改,在堆上分配

    printf("===");

    char *p3 = malloc(10 * sizeof(char));
    p3 = "hello"; // 把常量池hello地址赋给p3,造成内存泄露,刚才在堆上分配的10个空间大小没法释放
//    p3[0] = 'H'; // 不能修改,因为是常量池的
    puts(p3); // 可以修改,在堆上分配

    p = "world";
    strcpy(c, "world"); // 重新给c赋值
    puts(p);
    puts(c);

Array pointer and pointer array

  • Array pointer (int pointer):
    Array pointer can be said to be "array pointer", pointing to the first address of an array.
    int (*p)[2]: Array pointer, pz points to an array containing 2 int type values
// 传递数组指针,列数为2;
void printArr(int (*p)[2], int row) {
    
    

    // *p指向行,*(*p)指向具体元素
    for (int i = 0; i < row; ++i) {
    
    
        for (int j = 0; j < sizeof(*p) / sizeof(int); ++j) {
    
    
            printf("%d,", *(*(p + i) + j));  // *p指向行,*(*p)指向具体元素
            printf("%d,", p[i][j]);  // 同样可以这么访问
        }
        printf("\n");
    }
}

void test() {
    
    

    int zippo[4][2] = {
    
    {
    
    2, 4},
                       {
    
    6, 8},
                       {
    
    1, 3},
                       {
    
    5, 7}};
    int (*pz)[2]; // 数组指针,pz指向一个内含2个int类型值的数组
    pz = zippo; // 该二维数组首地址就是一个数组指针

    printArr(zippo, 4); 
    printArr(pz, 4);
}

  • Pointer array (int array) The
    pointer array can be said to be an "array of pointers", that is, each element in this array is a pointer variable; in a 32-bit system, a pointer occupies four bytes.
    int *p[2]: Pointer array, an int pointer variable array of length 2.
    char *a = "1";
    char *b = "2";
    char *arrA[] = {
    
    a, b}; // 字符串数组,用指针数组来表达
    char *arrB[] = {
    
    "1", "2"}; // 字符串数组,用指针数组来表达
    printf("%s,%s\n", arrA[0], arrA[1]);
    printf("%s,%s\n", arrB[0], arrB[1]);

Function pointers and pointer functions

  • Function pointer (int pointer), the pointer points to a function
int (*pfun)(int, int)// pfun是一个指向返回值为int的函数的指针
  • Pointer function (int function), that is, the function that returns the pointer:
    type name * function name (function parameter list column);
int *pfun(int, int); // pfun是一个返回值为整型指针的函数

Pointer constant and constant pointer

    int a = 1;
    int b = 2;

    // 常量指针,指针指向的值不可用改,但指针的指向可以改
    const int *p = &a;
    // *p = b; 错误,指向的值不可用改
    p = &a; // 指针的指向可以改

    // 指针常量,指针的指向可以改,指针指向的值可以改
    int *const p2 = &a;
    *p2 = b; // 指针指向的值可以改
    // p2 = &b; 错误,指针的指向不可用改

    // const修饰指针和常量,都不可用改
    const int *const p3 = a;
    // *p3 = b;
    // p3 = &b;

Pointers and references

&The address operator, through which the address value of a variable can be obtained; the
value operator is *also called dereference, through which the data corresponding to the location of an address can be obtained; “solution” is to correspond to the address The thing is unzipped and unzipped, just like opening a package, that is the value of the variable, so it is called "dereference". In other words, dereferencing is to return the corresponding object in the memory address.

Pointers and references are a concept, usually we say that a reference to a certain variable is a pointer to the variable.
But pointers and pointer variables are two concepts. That is, a variable stores the address of another variable, then the variable is called a pointer variable.
The pointer length is 4 bytes under 32 bits, and 8 bytes under 64 bits.

The essence of pointers is indirect access.

  • Pointer usage scenarios: transfer and offset
    Function call principle: value transfer; the value of the actual parameter is assigned to the formal parameter (compilation principle)

Pointer offset

    // 需要区分清楚指针++的操作
    int arr[3] = {
    
    1, 5, 9};
    int *p;
    int j;

    p = arr;
    j = *p++;
//    j = (*p)++;
//    j = *++p;
//    j = ++*p;
//    j = *p++;
    printf("arr[0]=%d, j=%d, *p=%d\n", arr[0], j, *p);

    j = p[0]++;
    printf("arr[0]=%d, j=%d, *p=%d, p[0]=%d", arr[0], j, *p, p[0]);

Dynamic storage and static storage

From the perspective of the scope of variables, it can be divided into global variables and local variables; from the perspective of the existence of variable values, it can be divided into static storage methods and dynamic storage methods;
static storage methods: refers to the fixed allocation by the system during program operation The storage space method;
Dynamic storage method: It is the method of dynamically allocating storage space according to the needs during the running of the program;

  • There are the following storage categories. According to the storage category of the variable, the scope and lifetime of the variable can be known
    auto: Local variables that are not declared as static are all dynamic storage methods, and the default repair symbol is auto. These storage spaces are automatically released at the end of the function.
    static: Allocate space in the static storage area, assign values ​​during compilation, and initialize only once.
    extern: Borrow a variable defined in another file to indicate that this is a declaration but not a definition. Let the compiler to query its definition elsewhere;:
    registerRegister variables, rarely used;

  • tips: The
    function is extern by default;
    static modified function means valid in this file;
    static modified variable means static variable and valid in this file;
    static local variable: although it is static, other functions cannot reference it.

Operator

image.png

Structure

The structure is aligned; the
structure is passed by value in the function, and all the contents are directly copied to the stack space, so the value of the caller will not be changed; it is necessary to use the pointer to pass the reference, and the reference pass can avoid this problem.

typedef struct student {
    
    
  int num;
  struct student *pNext; // 此时不能省略student结构体标签
} stu;

typedef和#define

  • typedefThe programmer is allowed to create aliases for existing types, and the code can be commented;
    usually, capital letters are used to indicate the defined name in the typedef definition to remind users that the type name is actually a symbol abbreviation.
    When using a typedef to name a structure type, you can omit the label of the structure:
    When using a typedef, remember that the typedef does not create any new types, it just adds a convenient label to an existing type.

  • #defineAlso known as macro definition, the identifier is the name of the defined macro, referred to as macro.
    Its characteristic is: the defined identifier does not occupy memory, but a temporary symbol, which does not exist after precompilation. Precompilation is also called preprocessing. Pre-compilation is not compilation, but processing before compilation. This operation is automatically completed by the system before the formal compilation.

    • In fact, the operation performed by pre-compilation is a simple "text" replacement.
      For macro definitions, when precompiled, all the places where the "identifier" appears in the program will be replaced with this "constant", which is called "macro replacement" or "macro expansion".
      After the replacement is completed, the formal compilation is performed. So when you click "Compile", two operations are actually performed, that is, pre-compile first, and then formally compile. #include<stdio.h> is the same, that is, in the preprocessing, first simply replace the line #include<stdio.h> in the program with all the "text" content in the header file stdio.h, and then proceed to the formal Compile.
  • typedefAnd #definethe difference between
    different from #define, typedef symbol name created is limited only by the type of value can not be used.
    Typedef is interpreted by the compiler, not the preprocessor.
    Within its limited scope, typedef is more flexible than #define.

#define PI 3.1415926 // 可以用于值

typedef int SOCKET; // 给int命个别名SOCKET,之后代码里可以使用SOCKET来表示socket的fd,做到了代码即注释,方便阅读
#define SOCKET int //等同于上句

typedef char* STRING;
STRING a,b; // 等同于 char *a, char *b

#define STRING char*
STRING a,b // 等同于char *a, b; 只有a是指针,文本替换而已;

head File

#Indicates that this is a preprocessing command. Anything starting with "#" is a preprocessing command.

A header file is a file, usually in the form of source code, which is automatically included by the compiler when processing another source file.
The header file generally puts the declarations of variables, macros, system global variables, and function prototypes defined in the .c file with the same name, and declarations that need to be used outside the .c.

  • Header file function:
    1. Convenient development: Contains common constants, structures, type definitions, functions, and variable declarations required by some files;
    2. Make the scope of the function start from the position of the function declaration, rather than the position of the function definition (practice summary)
    3. Provide interface: A software package can provide an interface to the outside world (for example: stdio.h).

Two syntaxes of #include

  • #include <file>
    This form is used to reference system header files. It searches for a file named file in the standard list of system directories. When compiling the source code, you can use the -I option to put the directory before the list.

  • #include "file"
    This form is used to reference user header files. It searches for a file named file in the directory containing the current file. When compiling the source code, you can use the -I option to put the directory before the list.

Only quote the header file once

  • The #ifndef/#define/#endif is added to the header file to prevent the header file from being repeatedly quoted.

  • Duplicate reference
    means that a header file is included multiple times in the same cpp file. This error is often caused by nested include.
    For example: there is an ah file #include "ch" and the b.cpp file imports #include "ah" and #include "ch" at this time, it will cause ch to be repeatedly quoted.

  • Consequences caused by repeated references to header files:

    1. Duplicate references in some header files only increase the workload of the compilation work and will not cause too much problem. It is just that the compilation efficiency is lower, but for large projects, the low compilation efficiency will be a painful thing.
    2. Some header files are repeatedly included, which can cause errors, such as defining global variables in the header file (although this method is not recommended, but it is indeed allowed by the C specification), which can cause repeated definitions.
  • #ifndef HEADER_FILEMeans "if not define HEADER_FILE" if HEADER_FILE does not exist

#ifndef HEADER_FILE
#define HEADER_FILE

the entire header file file

#endif

This structure is commonly referred to as a wrapper #ifndef. When the header file is referenced again, the condition is false because HEADER_FILE is already defined. At this point, the preprocessor will skip the entire content of the file, and the compiler will ignore it.

#define  定义一个预处理宏
#undef   取消宏的定义
#if      编译预处理中的条件命令, 相当于C语法中的if语句
#ifdef   判断某个宏是否被定义(#define过), 若已定义, 执行随后的语句
#ifndef  与#ifdef相反, 判断某个宏是否未被定义
#elif    若#if, #ifdef, #ifndef或前面的#elif条件不满足, 则执行#elif之后的语句, 相当于C语法中的else-ifelse    与#if, #ifdef, #ifndef对应, 若这些条件不满足, 则执行#else之后的语句, 相当于C语法中的else
#endif   #if, #ifdef, #ifndef这些条件命令的结束标志.
defined   与#if, #elif配合使用, 判断某个宏是否被定义
ifdef的使用和#if defined()的用法是一样的。
ifndef又和#if !defined()的用法一样。
#pragma  说明编译器信息
#warning 显示编译警告信息
#error   显示编译错误信息

Integer constant

/*
 * 符号常量,简单替换,使用时要注意。
 */
#define PI 3 + 2
// #define PI (3 + 2),这样就对了

void test(void) {
    
    
    int i = PI;
    int j = PI;
    printf("i = %d, j = %d\n", i, j);

    int k = PI * PI; // 3 + 2 * 3 + 2 = 11
    printf("k = %d", k);
}

Complement

Complement code is to express negative numbers
Complement code = original code inverted + 1

0000 0000 0000 0000 0000 0000 0000 0101  5
1111 1111 1111 1111 1111 1111 1111 1011 -5  // 取反+1

Integer variable

The highest bit of the signed number represents the sign;
image.png

void test() {
    
    
    int i = 0x80fb0000; // 首位为符号位
    unsigned int ui = 0x80fb0000;
    short j = 32767; // 0111 1111 1111 1111
    long k = 0;

    printf("%d, %d, %d\n", sizeof(j), sizeof(i), sizeof(k));
    printf("%d, %u\n", i, ui); // 使用%u输出unsiged

    printf("%d\n", j);
    ++j;
    printf("%d", j); // 溢出,使用时防止溢出
}

Floating point type

Character type

    char c = 'c'; // 1字节
    printf("%c\n", c);

    printf("abc\rd\n"); // \r回到行首,只输出d

    printf("abc\b\b"); // 退格

    char a = '\0'; // 空字符,用于标示字符串结尾,不是空格,打印不出
    printf("%c", a);

Guess you like

Origin blog.csdn.net/u014099894/article/details/111842231