我是初学者c。我知道使用单词“ static”会使c函数和变量在声明它的源文件中位于本地。但是请考虑以下内容...
test.h
static int n = 2;
static void f(){
printf("%d", n);
}
main.c
#include <stdio.h>
#include "test.h"
int main()
{
printf("%d", n);
f();
return 0;
}
我的预期结果是将抛出错误消息,因为函数f和变量n仅在test.h本地?谢谢。
但是,输出是
2
2
编辑: 如果它仅适用于编译单元,那是什么意思?以及如何按照我的意图使用静态方法?
答案 0 :(得分:7)
static
使函数/变量位于编译单元的本地,即编译单个.c
文件时读取的整个源代码集。>
#include
插入.h
文件有点像在您的.c
文件中复制/粘贴此头文件的内容。因此,您的示例中的n
和f
被认为是main.c
编译单元的本地变量。
module.h
#ifndef MODULE_H
#define MODULE_H
int fnct(void);
#endif /* MODULE_H */
module.c
#include "module.h"
static
int
detail(void)
{
return 2;
}
int
fnct(void)
{
return 3+detail();
}
main.c
#include <stdio.h>
#include "module.h"
int
main(void)
{
printf("fnct() gives %d\n", fnct());
/* printf("detail() gives %d\n", detail()); */
/* detail cannot be called because:
. it was not declared
(rejected at compilation, or at least a warning)
. even if it were, it is static to the module.c compilation unit
(rejected at link)
*/
return 0;
}
构建(编译每个.c
然后链接)
gcc -c module.c
gcc -c main.c
gcc -o prog module.o main.o
答案 1 :(得分:1)
您已将put()
包含在public class DoubleLockArrayBlockingQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable {
private static final long serialVersionUID = 3414217016077849776L;
final Object[] items;
int takeIndex;
int putIndex;
AtomicInteger count;
final ReentrantLock putLock;
final Condition notFull;
final ReentrantLock takeLock;
final Condition notEmpty;
public DoubleLockArrayBlockingQueue(int capacity) {
if (capacity < 0) {
throw new IllegalArgumentException();
}
this.items = new Object[capacity];
count = new AtomicInteger(0);
putLock = new ReentrantLock();
notFull = putLock.newCondition();
takeLock = new ReentrantLock();
notEmpty = takeLock.newCondition();
}
@Override
public void put(E e) throws InterruptedException {
if (e == null) {
throw new NullPointerException();
}
int c = -1;
putLock.lockInterruptibly();
try {
while (count.get() == items.length) {
notFull.await();
}
// 入队
items[putIndex] = e;
if (++putIndex == items.length) {
putIndex = 0;
}
c = count.getAndIncrement();
// 入队结束
// 如果还有位置可以生产,那么通知被阻塞的生产者,putLock上锁期间,takeLock可以拿到,进行消费,可能还有位置
if (c + 1 < items.length) {
notFull.signal();
}
} finally {
putLock.unlock();
}
// 如果原来队列中为0,说明有可能有消费者被阻塞了,那么通知一下消费者
if (c == 0) {
takeLock.lock();
try {
notEmpty.signal();
} finally {
takeLock.unlock();
}
}
}
@Override
public E take() throws InterruptedException {
int c = -1;
E r = null;
takeLock.lock();
try {
while (count.get() == 0) {
notEmpty.await();
}
// 出队
r = (E) items[takeIndex];
items[takeIndex] = null;
if (++takeIndex == items.length) {
takeIndex = 0;
}
c = count.getAndDecrement();
if (c > 1) {
notEmpty.signal();
}
} finally {
takeLock.unlock();
}
if (c == items.length) {
putLock.lock();
try {
notFull.signal();
} finally {
putLock.unlock();
}
}
return r;
}
}
中。
因此test.h
和main.c
在static int n
内部也将可见。
答案 2 :(得分:1)
如果在文件作用域中声明了变量或函数(不在其他{ }
大括号对中),并且将它们声明为static
,则它们对于<他们所在的em>翻译单位。
翻译单元是C语言中的正式术语,与文件略有不同。转换单元是单个c文件,包括它的所有h文件。
因此,在您的情况下,static
变量是由test.h
和main.c
组成的翻译单元的局部变量。您将可以在main.c中访问它,但不能在foo.c中访问它。
这意味着,如果您有另一个包含test.h
的.c文件,则将获得两个具有相同名称的相同变量的实例。这又可能导致各种疯狂的错误。
这是我们从不 定义头文件中的变量的众多原因之一。
(为避免意大利面条程序的设计,我们也不应在标头中声明变量,除非它们是const
限定的。)