24 c
就像我们使用宏一样:
#undef SOMEMACRO
Run Code Online (Sandbox Code Playgroud)
我们还可以取消声明或删除 C中的变量,以便我们可以节省大量内存吗?
我知道malloc()
和free()
,但我想完全删除变量,以便如果我使用printf("%d", a);
我应该得到错误
test.c:4:14: error: ‘a’ undeclared (first use in this function)
Run Code Online (Sandbox Code Playgroud)
tas*_*oor 38
不,但您可以创建小的最小范围来实现此目的,因为当范围退出时,所有范围的局部变量都会被销毁.像这样的东西:
void foo() {
// some codes
// ...
{ // create an extra minimum scope where a is needed
int a;
}
// a doesn't exist here
}
Run Code Online (Sandbox Code Playgroud)
imm*_*tal 23
这不是问题的直接答案,但它可能带来一些顺序和理解为什么这个问题没有正确的答案以及为什么在C中"删除"变量是不可能的.
点#1什么是变量?
变量是程序员为内存空间分配名称的一种方式.这很重要,因为这意味着变量不必占用任何实际空间!只要编译器有办法跟踪有问题的内存,定义的变量就可以通过多种方式进行转换,根本不占用任何空间.考虑:const int i = 10;
编译器可以轻松地选择将所有实例替换i
为立即值.i
在这种情况下会占用0个数据存储器(取决于架构,它可能会增加代码大小).或者,编译器可以将值存储在寄存器中,并且不再使用堆栈或堆空间."取消定义"主要存在于代码中的标签并不一定是在运行时中没有意义.
点#2变量存储在哪里?
在#1点之后你已经明白这不是一个容易回答的问题,因为编译器可以在不破坏逻辑的情况下做任何想做的事情,但一般来说,变量存储在堆栈中.堆栈的工作原理对您的问题非常重要.当一个函数被调用时,机器获取CPU指令指针和当前堆栈指针的当前位置,并将它们推入堆栈,将堆栈指针替换为堆栈上的下一个位置.然后它跳转到被调用函数的代码中.
该函数知道它有多少变量以及它们需要多少空间,因此它移动帧指针以捕获可占用所有函数变量的帧,然后只使用堆栈.为简化起见,函数从一开始就为其所有变量捕获足够的空间,并且每个变量都具有从函数堆栈帧*开头的明确定义的偏移量.变量也一个接一个地存储.虽然你可以在这个动作之后操纵帧指针,但是它太昂贵而且大多没有意义 - 运行代码只使用最后一个堆栈帧,并且如果需要可以占用所有剩余堆栈(堆栈在线程启动时分配)所以"释放"变量带来的好处很少.从堆栈帧的中间释放变量将需要碎片整理操作,这将非常耗费CPU并且无法恢复几个字节的存储器.
第3点:让编译器完成它的工作
这里的最后一个问题是一个简单的事实,即编译器可以在优化程序方面做得比你可能做得好得多.鉴于需要,编译器可以检测变量范围和重叠内存,这些内存无法同时访问以减少程序内存消耗(-O3编译标志).你不需要"释放"变量,因为无论如何编译器都可以在你不知情的情况下做到这一点.
这是为了补充我之前所说的关于变量太小而无关紧要的事实以及没有机制来实现你所要求的事实.
*支持动态大小的数组的语言可能会改变堆栈帧,以便仅在计算数组大小后为该数组分配空间.
Mik*_*kis 16
在C和绝大多数编程语言中都无法做到这一点,当然在我所知道的所有编程语言中都是如此.
你不会拯救"大量的记忆".如果你做了这样的事情你将节省的内存量将是微不足道的.小.不值得谈论.
以这种方式促进变量清除的机制可能比你要清除的变量占用更多的内存.
回收单个变量代码的代码调用也会占用比变量本身更多的空间.
因此,如果有一个魔术方法purge()
可以清除变量,那么不仅实现的purge()
内存大于你希望通过清除程序中的变量来回收的任何内存量,而且在int a; purge(a);
调用中purge()
会占用比a
自身更多的空间..
那是因为你所谈论的变量非常小.printf("%d", a);
您提供的示例显示您正在考虑以某种方式回收单个int
变量占用的内存.即使有办法做到这一点,你也可以保存4字节的顺序.这些变量占用的内存总量非常小,因为它是程序员通过手工输入声明声明的变量数量的直接函数.在你声明一些int
占据一定内存量的变量之前,在键盘上输入数字需要多年才能做任何事情,然后无意识地声明变量.
好吧,你可以使用blocks({ }
)并尽可能晚地定义一个变量来限制它存在的范围.
但除非该变量的地址被占用,这样做有没有对生成的代码影响的所有,因为它必须保持变量的值范围的编译器的确定并不显著影响.
如果采用变量的地址,则逃逸分析的失败(主要是由于内联障碍,如单独的编译或允许语义插入)可能使编译器认为它必须保持活着直到块中的后期而不是严格的必要.这很少有意义(不要担心少数几个int
s,而且通常只需要几行代码来保持它的存活时间是微不足道的),但最好还是记住它可能很重要的罕见情况.
归档时间: |
|
查看次数: |
12996 次 |
最近记录: |