Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 函数中静态变量的使用_C_Design Patterns_Variables_Static - Fatal编程技术网

C 函数中静态变量的使用

C 函数中静态变量的使用,c,design-patterns,variables,static,C,Design Patterns,Variables,Static,我写C代码已经很多年了,但最近我遇到了一个我从未使用过的特性:函数中的静态变量。因此,我想知道您使用此功能的一些方式是什么,这是正确的设计决策 例如 这是一个糟糕的设计决策。为什么?因为稍后您可能希望减少计数,这将涉及更改函数参数、更改所有调用代码 希望这足够清楚, 谢谢 我在测试代码中使用了静态变量来延迟初始化状态。在生产代码中使用静态局部变量充满了危险,可能会导致微妙的错误。看起来(至少在我通常处理的代码中)几乎任何一段代码一开始只是一个单线程的代码块都有一个坏习惯,最终会在并发情况下工作。

我写C代码已经很多年了,但最近我遇到了一个我从未使用过的特性:函数中的静态变量。因此,我想知道您使用此功能的一些方式是什么,这是正确的设计决策

例如

这是一个糟糕的设计决策。为什么?因为稍后您可能希望减少计数,这将涉及更改函数参数、更改所有调用代码

希望这足够清楚,
谢谢

我在测试代码中使用了静态变量来延迟初始化状态。在生产代码中使用静态局部变量充满了危险,可能会导致微妙的错误。看起来(至少在我通常处理的代码中)几乎任何一段代码一开始只是一个单线程的代码块都有一个坏习惯,最终会在并发情况下工作。在并发环境中使用静态变量可能会导致难以调试的问题。这是因为由此产生的状态更改本质上是一个隐藏的副作用

我使用静态变量作为控制另一个线程执行的一种方式

例如,线程#1(主线程)首先声明并初始化一个控制变量,例如:

/* on thread #1 */
static bool run_thread = true;
// then initialize the worker thread
然后它开始执行线程#2,它将执行一些工作,直到线程#1决定停止它:

/* thread #2 */
while (run_thread)
{
  // work until thread #1 stops me
}

有一个突出的例子,您非常需要
静态
来保护关键部分,即互斥。作为POSIX线程的示例:

static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&mut);
/* critical code comes here */
pthread_mutex_unlock(&mut);
这不适用于
auto
变量


POSIX为互斥体、条件和once变量提供了这样的
静态
初始化器。

这是我使用此功能的主要原因。不过要小心;代码既不是可重入的,也不是线程安全的,因此如果有多个调用方能够发出第一个调用,则不要期望它修复争用问题。请注意,
pthread\u once
接口以线程安全的方式提供了等效的功能。如果调用初始化函数的线程在初始化完成之前被取消,这甚至是安全的。(并且没有理由
pthread_once
不能在从不希望使用线程的单线程程序中使用。)@R。。谢谢很高兴您能对此有所了解。这在奇怪且难以诊断的情况下显然不起作用,因为静态变量不能保证线程安全。您必须使用类似于
pthread\u互斥体的东西来确保读写一致。在我的示例中,只允许第一个线程更改run\u线程的状态。您仍然存在可能无序的内存写入错误。如果没有实现或C1x
\u原子
类型的特殊保证,获得必要内存屏障的唯一可移植方法是使用
pthread\u mutex.*
函数。@R。。请原谅我的无知,当你只写1个字节时,内存不是在写原子吗?我知道在字节之间可以中断多个字节(例如c短),但我一直认为一个字节本身是原子的。@chacham15:不,一个字节原子是没有用的。我怀疑许多系统甚至没有,尽管x86有。大多数系统至少有32位和指针大小的原子操作,通常也有双指针大小的原子操作。不知道为什么会被否决。我认为这是到目前为止最好的答案。@Justin,谢谢-在我的第一个例子中,答案是用“总是”这样的词,并且可能太坚持认为这是个坏主意。。。我确实有这种感觉,但通常(总是?:)有例外。
/* thread #2 */
while (run_thread)
{
  // work until thread #1 stops me
}
static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&mut);
/* critical code comes here */
pthread_mutex_unlock(&mut);