For some bad ideas about strong symbols, weak symbols, strong references, and weak references in C language, please correct them.
First of all, I am very tragic. I did not know that C has strong symbols, weak symbols, strong references, and weak references before I read "Programmer self-cultivation-links, loading and libraries. I felt a little confused when I saw weak and strong symbols in section 3.5.5. So I wrote this article, hoping to communicate with friends who felt the same and hope to give advice to others.
First, let's take a look at their definitions in the book.
Introduction scenario: (1) Define and initialize the variable I (int I = 1) in file A, define and initialize the variable I (int I = 2) in file B ). B. o :(. data + 0x0): multiple definition of 'I';. o :(. data + 0x0): multiple definition of 'I '. (2) Define and initialize two variables I (int I = 1; int I = 2) in file C. c. c: 2: 5: error: redefinition of 'I'; c. c: 1: 5: note: previous definition of 'I' was here.
Strong Symbol: a symbolic definition like this in a scenario is called a strong symbol. For C/C ++, the default function of the compiler and the initialized global variable are strong symbols.
Weak Symbol: link, which indicates that the initialized global variable is a weak symbol.
Compiler rules on strong and weak symbols: (1) strong symbols cannot be defined many times, but strong and weak symbols can coexist; (2) Strong coverage is weak when strong and weak symbols coexist; (3) when all are weak symbols, select the largest space occupied. For example, select double type instead of int type.
As defined above, there are scenarios that I did not think of before:
Code a. c:
1 int i = 2;
Code B. c:
#include<stdio.h>int i;int main(int argc, char** argv){ printf("i = %d\n", i); return 0; }
Compile the files a and B and link them. The output result is 2 instead of 0.
In addition, if two variables are defined in the same file but not initialized, no error is reported. Only when variables are used will an error be reported.
For the GCC compiler, _ attribute _ (weak) can also be used to define strong symbols as weak symbols. All existing
Code c. c
1 #include<stdio.h>2 3 __attribute__((weak)) int i = 1;4 5 int main(int argc, char** argv)6 {7 printf("i = %d\n", i);8 return 0; 9 }
The output of result I is still 2 rather than 1.
So is that true for functions? Instead of looking at the function, you should first look at the strong and weak references that are further introduced by the strong and weak symbols. The overview of strong and weak references in the book is that if a strong reference is not defined, the link will certainly report an error, and if it is weak reference, no error will be reported. The default value of the linker is 0 (this is a good understanding of the function, that is, the entry address represented by the function symbol is 0. You must pay attention to the variable. Since it is a reference, it is the address, so the address of the variable is 0 like that of the function, rather than the value of the variable is 0 ). Is there any clear concept for strong/weak references? What is reference? What is the relationship between references and symbols? Here I will talk about my understanding (please correct me). The function name and variable name specified in the definition and description are the corresponding symbols, when calling a function or using a variable elsewhere in the Code, the description of the letter and the variable name are considered as references. In this way, symbols and references are actually something at the code level, it's just different from the environment. Strong symbols correspond to strong references, and weak symbols correspond to weak references.
The above strong and weak references show that when a function is a weak reference, no matter whether the function is defined or not, no error will be reported during the link, in addition, we can determine whether to execute the function based on whether the function name is 0. In this way, libraries that contain these functions can be combined with our reference in the form of modules and plug-ins for ease of use and uninstallation, since strong symbols can overwrite weak symbols, strong and weak symbols, and strong and weak references, we can define a function to overwrite the functions in the library.
First, determine whether to execute the function based on the conditions:
Code d. c
1 #include<stdio.h>2 3 void func()4 {5 printf("func()#1\n");6 }
Code e. c
1 #include<stdio.h> 2 3 __attribute__((weak)) void func(); 4 5 int main(int argc, char** argv) 6 { 7 if (func) 8 func(); 9 return 0;10 }
Compile d. c, cc-c d. c Output d. o; compile e. c and link d. o, cc d. o e. c-o e outputs the executable file e and runs the function func normally. Compile e. c but do not link d. o. At this time, no error is reported, but func will not execute, because if (func) is false because it is not defined.
Look at function coverage again:
Code f. c
1 #include<stdio.h>2 3 __attribute__((weak)) void func()4 {5 printf("func()#1\n");6 }
Code g. c
1 #include<stdio.h> 2 3 void func() 4 { 5 printf("func()#2\n"); 6 } 7 8 int main(int argc, char** argv) 9 {10 func();11 return 0;12 }13 ~
Compile the link and output the structure "func () #2 ".
The above shows that the function and the variable are consistent. In fact, the corresponding variable can also be used before judgment as if using the function, but not to judge the value of the variable but the address of the variable, as shown in
Code v1.c
int i = 2;
Code v2.c
1 #include<stdio.h> 2 3 __attribute__((weak)) extern int i; 4 5 int main(int argc, char** argv) 6 { 7 if (&i) 8 printf("i = %d\n", i); 9 return 0;10 }11 ~
When compiling and linking v1, output 2; when compiling but not linking v1, no output. In this case, we need to distinguish between definitions and declarations. __attribute _ (weak) int I defines variables and converts them to weak symbols. In this way, I allocates space, the _ attribute _ (weak) extern int I converts the originally defined variable I from a strong symbol to a weak symbol, resulting in weak reference instead of a strong reference when I is used. However, although the variable can do this, it is not as meaningful as the function.
The above strong and weak references still use the _ attribute _ (weak) provided by GCC, and the book also mentions _ attribute _ (weakref )), the latter seems to better reflect the keyword "Reference. The reason why I use the former to introduce strong and weak references is that I understand the relationship between strong and weak symbols and strong references. For how to use _ attribute _ (weakref), here is a method (both of which have different usage methods ).
Code a. c
1 #include<stdio.h>2 3 void bar()4 {5 printf("foo()\n");6 }
Code B. c
1 #include<stdio.h> 2 3 static void foo() __attribute__((weakref("bar"))); 4 5 int main(int argc, char** argv) 6 { 7 if (foo) 8 foo(); 9 10 return 0;11 }
Note the static modifier of function foo. If it does not exist, an error will be reported, so that function foo can be used only in this file.
Well, the night is deep, and the writing is a bit messy, and I am also messy.
Symbol and reference in C Language
In qq (int * q), (int * q) is the form parameter table of the qq function. int * q indicates that q is a pointer to an int object (or data type, this function accepts an int pointer as a parameter;
As for qq (int & q), this seems to be available only in C ++, the meaning of this sentence is that function qq accepts an int type reference (reference is only available in C ++ and other languages) q.
Qq (int q) indicates that qq receives an integer q.
By default, C/C ++ is passed by value (for C, it is passed by value at any time), that is, when you call a function that accepts parameters, the form parameter of this function is a copy of the original parameter. For example:
Void qq (int a) // The parameter is a local variable
{
A ++; // only change the shape parameter without affecting B
} // A is automatically destroyed at this time
Int main ()
{
Int B = 1;
Qq (B );
Printf ("% d", B); // print 1
}
It can be seen that when the value is transferred to the qq function, a is only a copy of B. The storage space they are stationed in is different, so changing a will not affect B.
Of course, the pointer is also passed by value in C,
Void qq (int *)
{
* A = 1989; // a stores the address of B. * a is used to obtain the value of B stationed at the address.
} // Pointer a is also automatically destroyed at this time,
Int main ()
{
Int B = 1;
Qq (& B); // pass by value, which is the address of B
Printf ("% d", B); // print 1989
}
This time, qq's form parameter a is a pointer, so it accepts a copy of B's address (the address is a long integer data) rather than a copy of B, when * a = 1989 is used in function qq, * a changes the value stored in address B to 1989, therefore, the value of B in the external world (here it refers to B in main, and the value of external is relative to the function qq) also changes.
For function qq (int & a), this is a new type introduced in C ++: reference, resulting in a new function value passing method, that is, passing values by reference. Example:
Void qq (int & a) // a can be considered as the alias of B. a actually has the same memory address as B.
{
A = 1989;
} // Is a destroyed?
Int main ()
{
Int B = 1;
Qq (B); // It Looks Like passing by value
Printf ("% d", B); // The result is the same as the above one, which is also 1989
}
The reference refers to the original object itself and can also be understood as an alias. For example, if someone is assigned multiple external numbers, such as a, q, and silly X, he may be called w, but no matter how small a, Big q, silly X, or w, everyone else knows that they are the same person. Therefore, the input qq parameter a can be understood as the alias of B in main, which is equivalent to B in main. Therefore, any operation on a is actually an operation on B, therefore, the value of B in main also changes.
In a simple summary, function values are actually of the following two types:
1. Change the value of the real parameter.
For example, the value of the referenced object is changed when the pointer or reference is passed.
2. Do not change the value of the real parameter.
Generally, it is passed by value.
This should be easy to understand .... Remaining full text>
Strong, weak, strong, medium, weak, and weak symbols
Strong forte (f), weak piano (p ),
Mezzo-forte (mf), mezzo-piano (mp ),
Crescendo (cresc) (<) And diminuendo (dim) (>)
Abbreviation in parentheses