我想知道,我们如何确保使用register说明符定义的变量是否存储在 CPU 寄存器中?
6 回答
基本上,你不能。C 标准中绝对没有任何内容可以让您控制。
使用register关键字给编译器一个提示,即变量可能存储到寄存器中(即,允许最快的访问)。编译器可以随意忽略它。每个编译器可以有不同的方式来接受/拒绝提示。
引用C11,第 §6.7.1 章,(强调我的)
使用存储类说明符为对象声明标识符
register建议尽可能快地访问该对象。此类建议的有效程度由实施定义。
FWIW,大多数现代编译器可以检测最常用的变量,并在需要时将它们分配到实际寄存器中。请记住,CPU 寄存器是一种稀缺资源。
反汇编代码并检查。那时可能还不清楚,因为变量并不真正存在,它们只是将生产者与消费者联系起来的名称。因此,不一定为该变量保留一个寄存器 - 也许它完全消失了,也许它在其生命周期中存在于多个寄存器中,也许以上都不是。
从历史上看,该register关键字是在几十年前作为对编译器的优化提示引入的。如今,当处理器有更多的通用寄存器时,编译器通常会在没有被告知的情况下将变量放在寄存器中(当使用优化编译代码时)。
作为一个提示而不是强制执行,你不能做任何事情来强迫它。但是,您可以在汇编程序中编写该部分代码。这样您就可以完全控制变量的存储位置。
如果变量存储在寄存器中,则意味着它不存储在内存中。因此,靶心是尝试使用 printf 访问变量的地址。如果输出给出了一些地址,则结论是它存储在内存中,因此它将充当自动存储类变量(并且它不存储在寄存器中)。但是如果它给出错误“内置函数'printf'的不兼容隐式声明”..这意味着变量存储在寄存器中并且将表现为寄存器存储类变量..
也许调用汇编指令会有所帮助:
/// Function must be something like this:
int check_register_storing()
{
__asm__ (
pushad // Save registers
and ebx, ebx // Set Zero
and eax, eax
and ecx, ecx
and edx, edx
);
// Set test number.
register int a = 8; // Initial value;
int from_register = 0;
asm(
add eax, ebx // If, 'a' variable set on CPU register,
add eax, ecx // Some of main usage registers must contain 8
add eax, edx // Others must contain 0
mov %from_register, eax
popad // Return default parameters to registers
}
/// Check result
printf( "Original saved number: %d, Returned number from main registers: %d\n", a, from_register );
}
我不知道我是对还是错,但是我们知道一个普通的变量存储在具有地址的内存中,但是我们知道如果我们写,register int a;那么可能会为该变量分配一个寄存器,但是我们知道寄存器有名称,而不是地址,所以我们不能分配指针指向寄存器,因为指针只存储地址,所以如果我们写如下: -
#include<stdio.h>
int main()
{
register int reg = 5;
int *p = ®
printf("%d",reg);
}
如果寄存器已成功分配给我们的变量,那么它应该给出错误:“请求寄存器变量'reg'的地址”,如果没有分配寄存器,则可以将内存地址分配给指针,因此不应该出现错误。 重要提示:-这是我在stackoverflow上的第一个答案,我可能错了,如果我错了,请纠正我,我还在学习。