C语言 C 中的静态、定义和常量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2611063/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Static, define, and const in C
提问by yCalleecharan
I've read that static variables are used inside function when one doesn't want the variable value to change/initialize each time the function is called. But what about defining a variable static in the main program before "main" e.g.
我已经读过,当人们不希望每次调用函数时都更改/初始化变量值时,会在函数内部使用静态变量。但是在“main”之前在主程序中定义一个变量 static 怎么样?
#include <stdio.h>
static double m = 30000;
int main(void)
{
value = m * 2 + 3;
}
Here the variable m has a constant value that won't get modified later in the main program. In the same line of thought what difference does it make to have these instead of using the static definition:
这里变量 m 有一个常量值,稍后在主程序中不会被修改。按照同样的思路,使用这些而不是使用静态定义有什么区别:
const double m = 30000;
or
或者
#define m 30000 //m or M
and then making sure here to use double operations in the main code so as to convert m to the right data type.
然后确保在主代码中使用双重操作,以便将 m 转换为正确的数据类型。
采纳答案by nategoose
static double m = 30000;
double foo(double x, double y) {
return x/m + y;
}
This doesn't win you anything. A copy of m has to be made to do the computation. Also if you do:
这不会为你赢得任何东西。必须制作 m 的副本才能进行计算。另外,如果你这样做:
double bar( double x, double y) {
m += x + y;
return m;
}
Then all calls to bar will change m. Static variables outside of functions (or classes) are really global variables with file scope. Other files can't get at them by extern
然后所有对 bar 的调用都会改变 m。函数(或类)之外的静态变量实际上是具有文件作用域的全局变量。其他文件无法通过 extern 获取它们
Static variables inside a function are still like global variables, except that even other functions in the same file can't see them directly.
一个函数内部的静态变量和全局变量还是一样的,只是同一个文件中的其他函数也不能直接看到它们。
const double m = 30000;
This is better and in many cases best. If the compiler sees this global const and then sees a reference to m then it knows that rather than generate code to load the value from where ever it is (which likely requires loading a literal address into a register first) to a register or stack position to do computations it can just make a register be 30000 or sometimes generate an instruction with 30000 encoded right in there.
这是更好的,在许多情况下是最好的。如果编译器看到这个全局常量,然后看到对 m 的引用,那么它就会知道,而不是生成代码将值从它所在的位置(这可能需要先将文字地址加载到寄存器中)加载到寄存器或堆栈位置要进行计算,它可以只使寄存器为 30000,或者有时生成一条在其中编码为 30000 的指令。
The down side to this is that the compiler has to assume that other souce files will want to read m and has to actually store a copy as a variable (but a constant variable) in the object file.
这样做的缺点是编译器必须假设其他源文件将要读取 m 并且必须将副本实际存储为目标文件中的变量(但常量变量)。
I'm not sure if it is standard but you can sometimes do extern const double m = 30000;and the compiler will use 30000 to optimize and assume that another file actually has a copy of m that will be stored in the executable. You can also do static const double m = 30000;and the compiler can assume that no one else will expect that a copy of m is stored in the object code generated from this source file.
我不确定它是否是标准的,但你有时可以这样做extern const double m = 30000;,编译器将使用 30000 来优化并假设另一个文件实际上有一个 m 的副本,该副本将存储在可执行文件中。您也可以这样做static const double m = 30000;并且编译器可以假设没有其他人会期望 m 的副本存储在从该源文件生成的目标代码中。
Doing
正在做
#define m 30000
is more risky. You will not get a warning or error if previously there was another m declared as a variable, constant, or function. Also, for preprocessor macros like this it is easy to mess up. For example:
风险更大。如果之前有另一个 m 声明为变量、常量或函数,您将不会收到警告或错误。此外,对于像这样的预处理器宏,很容易搞砸。例如:
#define BASE_ADDRESS 48
#define MY_OFFSET 9
#define MY_ADDRESS BASE_ADDRESS+MY_OFFSET
...
return MY_ADDRESS*4;
Yes, this is a stupid example, but what this looks like after the preprocessor gets done with it is
是的,这是一个愚蠢的例子,但是在预处理器完成之后看起来像
...
return 48+9*4;
Which is
这是
return 48+(9*4);
And that's not what you probably wanted.
这可能不是你想要的。
Another place where macros are bad is when you have large constants, such as strings. Strings require that they be addressable by pointer and are more difficult to optimize away than integers and floating point literal or constant numbers. You could easily make a very large program if you had lots of stuff like:
宏不好的另一个地方是当你有大常量时,比如字符串。字符串要求它们可以通过指针寻址,并且比整数和浮点文字或常数更难优化。如果你有很多东西,你可以很容易地制作一个非常大的程序,比如:
#define JIM "Jim"
#define JOHN "John"
and then used JIM and JOHN all over your programs because the compiler might not be able to see that you really only needed the strings "Jom" and "John" once in the program.
然后在整个程序中使用 JIM 和 JOHN,因为编译器可能无法看到您在程序中确实只需要一次字符串“Jom”和“John”。
That being said, it is not uncommon to see constants being declared like that, and often they are properly done that way by people who know what they are doing.
话虽如此,看到这样声明常量的情况并不少见,而且通常知道自己在做什么的人会正确地这样做。
回答by Jerry Coffin
staticmeans that the variable will have static storage duration, and local visibility. In this case, it's being used for the "local visibility" part of that -- i.e. it means that mis visible only within this translation unit (essentially this file after it's prepocessed).
static意味着变量将具有静态存储持续时间和局部可见性。在这种情况下,它被用于“本地可见性”部分——也就是说,m它只在这个翻译单元内可见(本质上是这个文件在预处理之后)。
回答by CB Bailey
staticfor an object declared outside a function merely makes the object local to the translation unit (i.e. it can't be accessed from other .cfiles). It doesn't make it constant. That it was constis for. They are orthogonal so you can have one or the other or both.
static对于在函数外部声明的对象,它只会使该对象成为翻译单元的本地对象(即不能从其他.c文件访问)。它不会使它恒定。那const是为了。它们是正交的,因此您可以拥有一个或另一个或两者。
e.g.
例如
static const double m = 5;
The #definedeclares a macro which (in this case) can be used as a constant value. There's no object, so constdoesn't apply as there's not object to be changed. As a consequence, you also can't take the address of a macro.
的#define声明了(在这种情况下)可以被用作一个恒定值的宏。没有对象,因此const不适用,因为没有要更改的对象。因此,您也无法获取宏的地址。
回答by Pascal Cuoq
When you write const double m=3000;you are telling the compiler to create a symbol min the object file that can be accessed from other files. The compiler may inline the value of min the file where it is defined, but the symbol still hasto be allocated for the purposes of separate compilation.
当您编写时,const double m=3000;您是在告诉编译器m在目标文件中创建一个可以从其他文件访问的符号。编译器可以内联的价值m在那里它被定义在文件中,但符号仍然有被分配单独编制的目的。
When you write #define m 3000you are just using a syntactic convenience for writing the same constant in several places in the source file.
当您编写代码时,#define m 3000您只是在使用语法便利,在源文件的多个位置编写相同的常量。
回答by AnT
If the value of mhas to stay the same forever, then of course you can either use
如果的值m必须永远保持不变,那么你当然可以使用
static const double m = 30000;
or
或者
#define m 30000
Just note that in C constobjects have external linkage by default, so to get the equivalent constdeclaration you have to use static const, not just const.
请注意,在 C 中const对象默认具有外部链接,因此要获得等效const声明,您必须使用static const,而不仅仅是const.
Also note that in C language constobjects are not constants, but rather "constant variables". If you need a true constant(i.e. an entity that forms constant expressions), you have to use either #defineor enum constant.
另请注意,在 C 语言中,const对象不是常量,而是“常量变量”。如果您需要一个真正的常量(即形成常量表达式的实体),您必须使用#define或枚举常量。
The latter is normally an issue with integral constants only. In your case of a doublethe approach with [static] constmight work best.
后者通常仅是积分常数的问题。在您的情况下,可能最有效double的方法[static] const。
回答by Johannes Schaub - litb
... change/initialize each time the function is called
...每次调用函数时更改/初始化
You use the words "change" and "initialize" as though they were the same, but they aren't
你使用“改变”和“初始化”这两个词就好像它们是一样的,但它们不是
void f(void) {
static int a = 0;
a++; // changed!
printf("%d\n", a);
}
int main(void) {
f(); f();
}
/*
# 1
# 2
*/
When at file-scope (outside functions) staticdoes not mean "const" as in "static value", but it means that the identifier can only be referred to in that translation unit.
在文件范围内(外部函数)static并不意味着像“静态值”中的“const”,而是意味着标识符只能在该翻译单元中引用。
So your first mwithout constcan still be changed. Only constguards against changes. But if you omit staticthen if you link in a library or another object file that has the same non-static identifier at file-scope you will get conflicts at link-time.
所以你的第一个m没有const仍然可以改变。只const防范变化。但是,如果您省略,static那么如果您在文件范围内链接具有相同非静态标识符的库或另一个目标文件,您将在链接时遇到冲突。
回答by fbrereto
#defineis a preprocessor operation and will cause all occurrences of mto be replaced by 30000before the compilation phase happens. The other two examples are bona fide variables. The staticvariable exists in the translation unit in which it is declared and can be modified. The constvariable is read-only.
#define是一个预处理器操作,将导致在编译阶段发生之前所有出现的m被替换30000。另外两个例子是真正的变量。的static变量存在于声明它和翻译单元可被修改。该const变量是只读的。
回答by rampion
In the toplevel scope staticmeans that the variable (or function) cannot be accessed outside this source file - it won't be made available to the linker, and won't cause any name conflicts when linked in. It has no effect on whether a variable is constant or not - in fact, such variables are often specifically non-constant so that initialization can be cached.
在顶级范围内static意味着不能在此源文件之外访问变量(或函数) - 它不会被链接器使用,并且在链接时不会导致任何名称冲突。它对是否变量是否为常量 - 事实上,此类变量通常是特别非常量的,以便可以缓存初始化。
The difference between using constand #defineis that the former allows the compiler to type-check your usage of a constant.
使用const和之间的区别在于#define,前者允许编译器对您对常量的使用进行类型检查。
回答by Péter T?r?k
The main difference is that with #define you leave the type system. The preprocessor has no notion of type safety, scope etc. So e.g. if you later try to write a loop like
主要区别在于,使用 #define 可以离开类型系统。预处理器没有类型安全、范围等概念。因此,例如,如果您稍后尝试编写一个循环,例如
for (int m = 0; m < size; m++) { ... }
for (int m = 0; m < size; m++) { ... }
you are up to a nasty surprise...
你有一个令人讨厌的惊喜......
Also if you use #defines, you will only see the value of 30000 when debugging your code, not the name m. Which does not seem to make a big difference in this case, but when using meaningful constant and variable names, it does indeed.
此外,如果您使用 #defines,则在调试代码时您只会看到 30000 的值,而不是 name m。在这种情况下,这似乎没有什么大的区别,但是当使用有意义的常量和变量名称时,确实如此。

