首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >非静态可以遵循静态,但是静态不能遵循非静态?

问非静态可以遵循静态,但是静态不能遵循非静态?
EN

Stack Overflow用户
提问于 2020-09-10 06:53:11
回答 2查看 82关注 0票数 1

我有两个问题:

  1. 这是我的代码,正确地编译和链接。
代码语言:javascript
复制
//driver.c
#include <stdio.h>
#include <stdlib.h>
int lib_x = 1;
static void libc_func();

void libc_func(){
    lib_x += 11;
}

int main(){
    lib_x += 5;
    printf("%d\n",lib_x);
    libc_func();
    printf("%d\n",lib_x);
    return EXIT_SUCCESS;
}

输出如预期的那样

代码语言:javascript
复制
6
17

但是,当我切换时,代码是

代码语言:javascript
复制
//driver.c
#include <stdio.h>
#include <stdlib.h>
int lib_x = 1;
void libc_func();

static void libc_func(){
    lib_x += 11;
}

int main(){
    lib_x += 5;
    printf("%d\n",lib_x);
    libc_func();
    printf("%d\n",lib_x);
    return EXIT_SUCCESS;
}

我得到一个编译错误,其中声明

代码语言:javascript
复制
driver.c:7:13: error: static declaration of ‘libc_func’ follows non-static declaration
 static void libc_func(){
             ^~~~~~~~~
driver.c:5:6: note: previous declaration of ‘libc_func’ was here
 void libc_func();

我不明白为什么当一个非静态声明遵循一个静态声明()时没有出现错误,但是一个错误会反过来显示出来。有人能解释一下这种情况吗?

  1. 我注意到的另一件事是,在编译此代码时,当涉及到变量时,有一种不同的行为:
代码语言:javascript
复制
//driver.c
int lib_x;
static int lib_x = 2;

int main(){
    return 0;
}

错误是:

代码语言:javascript
复制
driver.c:3:12: error: static declaration of ‘lib_x’ follows non-static declaration
 static int lib_x = 2;
            ^~~~~
driver.c:2:5: note: previous declaration of ‘lib_x’ was here
 int lib_x;

在编译此代码时:

代码语言:javascript
复制
//driver.c
static int lib_x;
int lib_x = 2;

int main(){
    return 0;
}

错误是:

代码语言:javascript
复制
driver.c:3:5: error: non-static declaration of ‘lib_x’ follows static declaration
 int lib_x = 2;
     ^~~~~
driver.c:2:12: note: previous declaration of ‘lib_x’ was here
 static int lib_x;

因此,当非静态跟随静态&静态跟随非静态时,变量会显示错误。然而,函数只在静态跟随非静态时才显示错误.怎样才能解释变量和函数在处理上的差异呢?

EN

回答 2

Stack Overflow用户

发布于 2020-09-10 09:55:43

C的问题在于,当它在1989年标准化时,标准委员会必须注意编译器也将成功地编译许多在其约定中不同的现有代码。因此,关键字static和extern及其相互作用有点复杂。

  • 密码 int lib_x;静态int lib_x = 2; 不工作C11/18 6.2.2,因为第一个int lib_x;是一个带有外部链接的暂定定义,而static int lib_x = 2;是一个具有内部链接的定义。然后,按照6.2.2p7, 7如果在翻译单元中,同一标识符同时出现在内部和外部链接中,则行为未定义。

一些C编译器可能允许编译,但是编译器出错了。

至于

静态int lib_x;int lib_x = 2;

第一种是关于内部联系的初步定义,第二条规则比较复杂。

4对于在可见该标识符的先前声明的范围内用存储类说明符extern声明的标识符,31)如果先前的声明指定内部或外部链接,则后一声明中标识符的链接与先前声明中指定的链接相同。如果没有先前的声明可见,或者如果先前的声明指定没有链接,则标识符具有外部链接。

5如果函数的标识符声明没有存储类说明符,则其链接的确定与使用存储类说明符extern声明时完全相同。如果对象的标识符声明具有文件范围,且没有存储类说明符,则其链接是外部的。

因为它是,而不是,所以有一个存储说明符,它的链接将是外部。现在,令人困惑的是,如果确实使用了的extern存储类说明符,那么它就可以工作了!

静态int lib_x,extern int lib_x= 2;

  • 对于函数情况,同样的文本也适用;直到现在,6.2.2p5的第一部分才适用,它说,没有存储说明符的任何函数声明就好像它是用extern声明的,也就是说,后者正好对应于 libc_func();静态libc_func(){ lib_x += 11;} 而且它不起作用,因为在没有任何事先声明的情况下,第一种方法会指定外部链接,而第二种方法指定内部链接;但是切换这2将是可行的,因为 静态空洞libc_func(){ lib_x += 11;} extern libc_func(); 实际上,extern同样意味着“先前的链接,如果没有在*之前指定,则表示extern”。
票数 2
EN

Stack Overflow用户

发布于 2020-09-10 07:42:41

要知道的是:当您声明变量时,外部链接是默认的,而声明总是在定义之前。

函数案例

在第一个例子中,首先将lib_func()声明为静态,然后定义它,而不指定存储分类器(静态或外部分类器)。但是,编译器知道,因为您以前声明lib_func()具有静态链接,所以不必“猜测”lib_func()存储分类器。

在第二种情况下,首先声明一个具有外部链接的变量(因为您没有再次指定存储分类器),但是编译器在lib_func()的定义中看到了一个静态存储分类器。由于宣言先于定义,所以这些定义是矛盾的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63824248

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档