Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.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++_C_Function_Static_Compilation - Fatal编程技术网

C++ 编译器将做什么

C++ 编译器将做什么,c++,c,function,static,compilation,C++,C,Function,Static,Compilation,我已经编程好几年了,但令人尴尬的是,有一两件事我还没有完全弄清楚 在下面刚刚用作示例的基本代码中,当编译器遇到myFunc()时,str1和str2将存储在哪里 它们是指向字符串文本的指针,所以我假设字符串文本将存储在只读内存中,但是在这种情况下,一个指针是静态本地的,另一个指针不是静态本地的,有什么区别呢? 此外,我认为局部变量将存储在堆栈上,并且在调用函数之前不会分配它们?这令人困惑 对于整数var1,它是非静态的,但是var2是静态的。编译器会在编译时将这个var2放在数据段中。我在另一篇

我已经编程好几年了,但令人尴尬的是,有一两件事我还没有完全弄清楚

在下面刚刚用作示例的基本代码中,当编译器遇到myFunc()时,str1和str2将存储在哪里

它们是指向字符串文本的指针,所以我假设字符串文本将存储在只读内存中,但是在这种情况下,一个指针是静态本地的,另一个指针不是静态本地的,有什么区别呢? 此外,我认为局部变量将存储在堆栈上,并且在调用函数之前不会分配它们?这令人困惑

对于整数var1,它是非静态的,但是var2是静态的。编译器会在编译时将这个var2放在数据段中。我在另一篇文章中读到,本地静态变量将在第一次使用时创建和初始化,而不是在编译期间。那么在这种情况下,如果函数从未被调用呢

提前感谢您有经验的知识

已编辑:从main()调用myFunc()。这是一个输入错误,因为myFunc()从未被调用过

int myFunc()
{
    static char* str1 = "Hello";
    char* str2 = "World";

    int var1 = 1;
    static int var2 = 8;

}

int main()
{

    return myFunc();
}

编译器将生成一个不接受输入、不执行任何操作、然后不输出的程序

所有这些声明都是完全无关的,因为它们对程序的[不存在的]结果没有任何贡献。您可能会说它们“得到了优化”,但事实是,它们实际上在生成的编译可执行文件中没有类似的内容

static const char* str1 = "Hello";
str1
是指向将存储在只读内存中的字符串文本的静态本地指针

const char* str2 = "World";
str2
是一个本地“堆栈分配”指针,指向将存储在只读内存中的字符串文本

const char* str2 = "World";
str1
str2
的值分别是它们所指向的字符串文本的地址

int var1 = 1;
static int var2 = 8;

如果从未达到这些代码行,
var2
将永远不会初始化。我不知道编译器是否在编译时在其他地方为它预留了一块内存。

静态变量,即使是函数范围内的变量,也将存储在全局范围内。函数或作用域内的
静态
变量将仅在输入该函数或作用域的第一次时初始化。在大多数编译器中,当输入函数作用域时,非
静态变量将被分配或存储在堆栈上,当输入作用域时,变量将被初始化。某些编译器将局部变量存储在其他地方。

编辑:

另一个答案和注释是正确的,因为你的变量没有被使用,所以你的变量会被优化。但是让我们玩一玩,用它们来看看会发生什么

我使用
gcc-s trial.c
编译了op的程序,尽管从未调用过myFunc,但这个答案的其他内容没有任何变化

我已经稍微修改了你的程序,让它实际使用这些变量,这样我们就可以了解更多关于编译器和链接器的功能。这是:

#include <stdio.h>

int myFunc()
{
    static const char* str1 = "Hello";
    const char* str2 = "World";

    int var1 = 1;
    static int var2 = 8;
    printf("%s %s %d %d\n", str1, str2, var1, var2);
    return 0;
}

int main()
{
    return myFunc();
}
在程序集文件中甚至找不到var1。它实际上只是一个加载到堆栈中的常量

在程序集文件的顶部,我们在.rdata部分看到“World”(str2)。在程序集文件的下方,字符串“Hello”位于.rdata部分,而str1的标签(包含“Hello”的标签或地址)位于.data部分。var2也在.data部分

下面是一个更深入地探究为什么会发生这种情况的例子

指出.rdata部分是.data的只读部分,并解释了不同部分

希望这有帮助


编辑:

我决定尝试使用-O3编译器标志(高优化)。这是我得到的汇编文件:

    .file   "trial.c"
    .section .rdata,"dr"
.LC0:
    .ascii "World\0"
.LC1:
    .ascii "Hello\0"
.LC2:
    .ascii "%s %s %d %d\12\0"
    .section    .text.unlikely,"x"
.LCOLDB3:
    .text
.LHOTB3:
    .p2align 4,,15
    .globl  myFunc
    .def    myFunc; .scl    2;  .type   32; .endef
    .seh_proc   myFunc
myFunc:
    subq    $56, %rsp
    .seh_stackalloc 56
    .seh_endprologue
    leaq    .LC0(%rip), %r8
    leaq    .LC1(%rip), %rdx
    leaq    .LC2(%rip), %rcx
    movl    $8, 32(%rsp)
    movl    $1, %r9d
    call    printf
    nop
    addq    $56, %rsp
    ret
    .seh_endproc
    .section    .text.unlikely,"x"
.LCOLDE3:
    .text
.LHOTE3:
    .def    __main; .scl    2;  .type   32; .endef
    .section    .text.unlikely,"x"
.LCOLDB4:
    .section    .text.startup,"x"
.LHOTB4:
    .p2align 4,,15
    .globl  main
    .def    main;   .scl    2;  .type   32; .endef
    .seh_proc   main
main:
    subq    $40, %rsp
    .seh_stackalloc 40
    .seh_endprologue
    call    __main
    xorl    %eax, %eax
    addq    $40, %rsp
    ret
    .seh_endproc
    .section    .text.unlikely,"x"
.LCOLDE4:
    .section    .text.startup,"x"
.LHOTE4:
    .ident  "GCC: (Rev1, Built by MSYS2 project) 5.4.0"
    .def    printf; .scl    2;  .type   32; .endef
var1现在只是放在寄存器(r9d)中的常量1。var2也只是一个常量,但它被放在堆栈上。此外,字符串“Hello”和“World”以更直接(高效)的方式访问

所以,我决定尝试一些稍微不同的东西:

#include <stdio.h>

void myFunc()
{
    static const char* str1 = "Hello";
    const char* str2 = "World";

    int var1 = 1;
    static int var2 = 8;
    printf("%s %s %d %d\n", str1, str2, var1, var2);

    var1++;
    var2++;
    printf("%d %d", var1, var2);
}

int main()
{
    myFunc();
    myFunc();
    return 0;
}
这看起来更像原作。var1仍然优化为仅使用常量,但var2现在再次位于.data部分。“Hello”和“World”仍然在.rdata部分,因为它们是常量


其中一条评论指出,在使用不同编译器的不同平台上,这将是不同的。我鼓励您尝试一下。

您的代码在编译时至少会有一个警告,因为函数不会返回任何与返回类型规范相矛盾的内容

无论如何,在我的机器上,它会生成代码。如果您不使用任何优化代码,则会为分配本地
str2
的函数发出优化代码<代码>str1和
var2
在代码的数据部分分配,以指向各自的值。如果使用优化,显然会发出一个愚蠢的代码,而未指定的局部变量会作为未使用的全局变量消失

要观察这一点,您至少可以使用
nm
检查目标代码:

$ gcc -o p p.c
$ nm p
0000000100000f90 T _main
0000000100000f70 T _myFunc
0000000100001000 d _myFunc.str1
0000000100001008 d _myFunc.var2
$ gcc -O3 -o p2 p.c
$ nm p2
0000000100000fb0 T _main
0000000100000fa0 T _myFunc

如果您想了解更多详细信息,请使用
-S
生成汇编代码并观察发生的情况。

编译器所做的工作必须基于(假设编译器工作正常)代码的语义,因此我将讨论这一点

首先,一个相当次要的问题。通过使用
()
声明函数,可以指定它接受固定但未指定数量和类型的参数。这是一种过时的声明/定义形式,很少有好的理由使用它。(空括号在C++中有不同的含义,但你询问C.)指定函数没有参数,使用<代码>(空隙)< /C> >而不是<代码>()>代码>(特别是对于<代码>主< /代码>,因为它不是100%明确的,<代码> int()/<代码必须被一致的编译器接受)。 随着这一变化:

int myFunc(void)
{
    static char* str1 = "Hello";
    char* str2 = "World";
    int var1 = 1;
    static int var2 = 8;
}

int main(void)
{
    return myFunc();
}
这个节目
int myFunc(void)
{
    static char* str1 = "Hello";
    char* str2 = "World";
    int var1 = 1;
    static int var2 = 8;
}

int main(void)
{
    return myFunc();
}
static char* str1 = "Hello";
static const char *str1 = "hello";
char* str2 = "World";
int var1 = 1;
static int var2 = 8;