如何解决如果C函数被两次调用,它将创建两次在函数中声明的变量吗?
我有一个用C语言编写的函数,其中包含一个像这样的指针变量
#include<stdio.h>
void print()
{
char *hello="hello world";
fprintf(stdout,"%s",hello);
}
void main()
{
print();
print();
}
如果我两次调用print()函数,它将为 hello 变量分配两次内存吗?
解决方法
如果我两次调用print()函数,它将为hello变量分配两次内存吗?
不,它是字符串文字,并且只分配了一次。
您可以通过检查地址来确认:
fprintf(stdout,"%p: %s\n",hello,hello);
样本输出:
0x563b972277c4: hello world
0x563b972277c4: hello world
,
如果我两次调用print()函数,它将为 hello 变量分配两次内存吗?
是的。但是,hello
是指针,在64位计算机上占用8字节的堆栈空间。成本实际上无法衡量。此外,编译器不必全部分配变量 ,因为您从未尝试获取其地址。编译器可以自由有效地将您的代码转换为:
void print()
{
fprintf(stdout,"%s","hello world");
}
意味着hello
的声明在运行时不会导致任何内存分配。并非出于所有目的和目的,将hello
作为局部变量是免费的。
相反,在应用程序的数据段中,以零结尾的字符串文字“ hello world”仅分配一次。编译器可以执行此操作,因为它知道C字符串文字是只读的,因此不允许修改它。此外,在运行时不执行 dynamic 内存分配。字符串文字的内存是静态分配的,其生存期是应用程序的生存期。
因此,您的print
函数本质上尽可能便宜—它根本不执行任何实际分配。
您可以将代码粘贴到compiler explorer上以查看会发生什么。从您的代码中,这是生成的附生者:
print(): # @print()
mov rcx,qword ptr [rip + stdout]
mov edi,offset .L.str
mov esi,11
mov edx,1
jmp fwrite # TAILCALL
main: # @main
push rax
mov rcx,1
call fwrite
mov rcx,1
call fwrite
xor eax,eax
pop rcx
ret
.L.str:
.asciz "hello world"
重要的部分在最后:
.L.str:
.asciz "hello world"
"hello world"
仅像全局变量一样在此处声明,并在每次调用函数print
时使用。
就像您这样声明一样:
#include<stdio.h>
const char* hello = "hello world";
void print()
{
fprintf(stdout,hello);
}
void main()
{
print();
print();
}
在这种情况下,编译器看到了优化并完成了优化。但是,我不能肯定会一直这样,因为它不能依赖于编译器。
,-
<div class="alert alert-warning mt-2" id="mainArea"> {% for question in testing %} <div class="alert alert-secondary mt-2" id="questionArea{{ forloop.counter0 }}"> <form method="post" id='testForm' data-url="{% url 'test' %}"> {% csrf_token %} <table> <thead> <tr> <th>{{ forloop.counter }}. {{ question.1 }}</th> </tr> </thead> </table> {% if question.4 %} {% for images in img %} {% if images.picture == question.4 %} <img src="{{ images.picture.url }}" class="mainImg" alt=""><br> {% endif %} {% endfor %} {% endif %} {% if question.0 == '1' %} {% for el in question.2 %} <label> <input type="checkbox" class="checkbox" onclick="getCheckedCheckBoxes()" name="{{ question.1 }}" value="{{ el }}" id="{{ question.1 }}"/> {{ el }} </label><br> {% endfor %} {% else %} <label> {% for num in question.2 %} <h6>{{ forloop.counter }}. </h6> <select id="myselect" class="myselect" name="myselect" onchange="getSequence()"> <option disabled selected></option> {% for el in question.2 %} <option value="{{ el }}" id="{{ question.1 }}{{ forloop.counter0 }}" label="{{ el }}"> </option> {% endfor %} </select><br> {% endfor %} </label> {% endif %} </form> </div> {% endfor %} <button type="button" value="snd" id="sendAnsButton" onclick="sendAnswers()" class="button">Завершить тест</button> </div>
变量
当函数退出时,自动变量将终止其寿命。因此,仅当您位于函数内部时,才会在堆栈上分配内存。函数存在时将释放它。
- 字符串文字具有程序寿命,并且位于存储文字的位置(通常是.rodata段)。在程序构建过程中会填充此区域,它在内存中的实际表示方式取决于实现方式
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。