cstorage.txt
来自「国外网站上的一些精典的C程序」· 文本 代码 · 共 259 行
TXT
259 行
A Brief Discussion of C Language Storage Modifiers -------------------------------------------------- (a public domain tutorial by Carey Bloodworth & Bob Stout)There are seven basic storage types: auto, const, extern, global,register, static, and volatile. Static and extern can also beapplied to functions. (Although global is a basic storage class, itis not a keyword, like the other six.)Put very simply:auto: a normal stack variable declared and used within a function.const: it tells the compiler that you are not going to change thisvariable (that it is 'const'ant) and allows the compiler to doadditional type checking and possibly put the variable in adifferent section of memory (such as ROM instead of RAM). When thevariable happens to be a pointer, the pointer itself, what thepointer points to, or both, can be declared constant.extern: it says the variable is 'extern'al to the current file.You can use it in this module, but you have to actually declare itas global somewhere else.global: it is declared outside of any function and the entireprogram can 'see' the variable and modify it.register: used with a local / auto variable, it suggests to thecompiler that it might be more efficient if it kept that variable ina CPU register. The compiler is under no requirement to follow yoursuggestion. If it doesn't follow your advice, the variable has thesame storage class as whatever it would normall have. Trying tomake a variable a 'register' variable also prevents you from takingits address and using a pointer to it, since there is obviously noway to have a memory pointer point to a CPU register.static: Static has two meanings. Inside a function, it means thevariable keeps its value between calls to that function. When usedwith a variable or function that would other wise be global, ittells the compiler that it is 'private' to that file. Although itis 'global' to everything within that same file / module, no otherfile / module knows about it.volatile: This tells the compiler not to keep this value in aregister, that the variable is 'volatile' and can change on it'sown, without the program itself doing it. The change could becaused by a multi-tasking program, or perhaps its the clock timer,or some other situation where the compiler must not make anyassumptions about what the value is.Here is an example program:int Global1;int Global2=10;const int CVar=13;const int *Ptr1;int * const Ptr2=&Global1;const int * const Ptr3=&Global2;long volatile * const Clock=some address;extern int errno;void Func1(void){ int Local1; int Local2=5; static int Local3=10;Local1=17;/* do stuff */if (errno != 0 ) {int Local4; Local4 = func2(); /* do something with Local4 */ }Local1=Local1-1; /* useless */Local2=Local2-1; /* useless */Local3=Local3-1; /* purposeful */}Auto class==========An 'auto' variable is just a normal variable declared within a pairof braces { }. Generally, that would be normal variable declarationat the beginning of a regular function, but it can also be donewithin the function itself, if a temp variable is needed in just oneplace, etc. The term 'auto' is rarely used these days, because it'sunderstood that a local variable will be 'auto' unless you say tomake it static.Examine the sample program above. The variables Local1 and Local2are local / auto variables and can be used anywhere in Func1().Local4 is also a local / auto variable, but it can only be usedwithin that inner set of brackets.Auto / local variables are put on the stack. They just 'suddenly'appear when you enter a function, and unless you explicitlyinitialize the variable, its contents will be pure random garbage.Above, Local1 is unitialized. Its value is unknown because itdepends on whatever value happens to already be on the stack at thatpoint. Unlike global variables, an auto variable is _not_automatically initialized to zero. Auto variables will have garbagein them unless you explicitly initialize them, either in thedeclaration itself (like with Local2) or explicitly in the program(like with Local1).Const class===========A constant variable is one that you are promising (and the compilershould be enforcing) that it will not change. This lets thecompiler make certain optimizations, and enforce a bit of typechecking, etc. CVar is being initially set to 13, and it will, forthe rest of the program, have that value. You may initialize itwhen you declare it, but that is the only time it may be set.When the variable is a pointer, things become a bit morecomplicated. For example, Ptr1 is a pointer to an integer constant.That means that although the pointer can change, you can not changethe value of what the pointer points to. That can be useful whenyou are using the pointer to reference a pre-calculated data tableand you want to be reasonably sure of not modifying it.On the other hand Ptr2 itself can not be modified, although what itpoints to can. It can only point to one address, although thecontents of that address can change. This has limited usefulness,although it does let you set up 'aliases' for another variable oraddress.The third type, Ptr3, is a combination of both. The value of thepointer can not be changed after being initialized when it'sdeclared, nor can what it points to be changed. As you can't doanything with a pointer like this, it's fairly useless.Note that using 'const' is just a compiler / language safety check.It does not actually prevent you from doing it with other methods,such as by type casting the 'const' away, or with some otherpointer, etc. As always, C will let you do anything you like,provided you are reasonably sure you want to do it.And finally, the 'const' is a bit different in C++. In that case, aconst variable can sometimes behave as if you had used a #define toset it at that value. In C, a 'const' value will always takestorage, but with C++, if the compiler notices you are only using ita certain way, it can just go ahead and use the value of constvariable, without ever really creating the variable.Extern class============Declaring something is 'extern' just means that you are not actuallydefining it at this point, that it's done somewhere else, usallysome other program module. The extern declaration does not actuallyconsume any storage (for a variable) or generate any function code(if it's a function), it just lets the compiler know that it reallydoes exist, but just not here.In the example above, we are declaring the variable 'errno' as anexternal integer. (This is rather bad form to do it with thisparticular variable, because that is C's error reporting variableand it's really declared in the standard library header <stdlib.h>,but I wanted to show something you might recognise.)This means that the actual declaration (which actually allocates thememory for the global variable) is in some other file (or even in alibrary that you will link in), but that we can _use_ it.Declaring functions as 'extern' is similar.If you look through your library header files, such as <stdlib.h> or<stdio.h> you will see many examples of extern functions andvariables. They are actually defined elsewhere, and put into theprecompiled libraries, but you can use them just as if they actuallyexisted in your file.Register class==============A register variable is just your hinting to the compiler that itmight be more efficient if the compiler kept that simple variable ina CPU register. It also prevents the compiler from being able totake the address of that variable, meaning you can't have anypointers to that variable, since it doesn't make sense to have amemory pointer trying to point to a CPU register, which doesn'texist in memory. Only local, auto variables can be 'register'.Static class============Static has two meanings. The first is towards local variables andthe second is towards external, non-local identifiers (variables andfunctions.) A local variable can also be declared as 'static', as well as theimplicit or explict declaring of 'auto'. This is a cross between aglobal variable and a local auto variable. Like all globalvariables, when the program is first run, it is automaticallyinitialized to 0 if you don't explicitly initialize it yourself.The only real difference is that a static local var is known onlywithin that function it is defined. Its value is not destroyedbetween calls to that function. The variable Local3 is initiallybeing set to 10; And what ever I do to that variable will beremembered between calls to it. For example, at the end of thefunction, right before I leave, I am decrementing Local1, Local2,and Local3. Because Local1 and Local2 are normal auto variables, itdoesn't matter because the next time I call Func1(), their valueswill be undetermined until they are explicitly initialized.However, the variable Local3 is declared as 'static'. That means it_will_ remember its contents between calls. The first time I call,it is initialized to what I set it (or initialized to 0 by default,like global variables are). The second time I call Func1(), thevalue will _not_ be reinitialized. It will retain the value it hadwhen I left the function before. In this case, it will bedecremented by one with each call.When you use 'static' outside of a function, it behaves a bitdifferently. It means that whatever you use it on (whether avariable or a function) will not be visible outside of that file /module you are using it in. This lets you enforce a bit of'locality of usage' in your programming. If you have a set ofrelated variables and functions, and you keep them in a single file,and feel that only the functions in that file itself should modifythose variables or call those functions, then you can declare themas 'static' to hide them from the rest of the program.Volatile class==============You can also declare a variable to be 'volatile'. That just letsthe compiler know that the value of the variable will change due tooutside influences. It might be the clock counter, or some hardwareport accessed via a fixed memory location, or whatever. It justtells the compiler not to take any short cuts and to not keep it ina register. Every time you use that variable, the compiler willactually reference that variable or location, rather than using anolder value from a previous access.In the program example above, I am declaring a pointer to be bothconst and volatile. The pointer itself is constant, it will notchange from that address of where the clock is located. Its alsodeclared as volatile, meaning that the value of what the pointer isalways point to will change outside of the program's operation. So,every time I do *clock, the compiler has to always generate codethat reads that memory address. If I did twoclock=*clock + *clock;the compiler would have to generate two seperate reads to the clock.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?