Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.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++ 编译器在cpu寄存器中将这样的结构传递给函数有意义吗?_C++_Function_Compiler Construction_Parameter Passing_Cpu Registers - Fatal编程技术网

C++ 编译器在cpu寄存器中将这样的结构传递给函数有意义吗?

C++ 编译器在cpu寄存器中将这样的结构传递给函数有意义吗?,c++,function,compiler-construction,parameter-passing,cpu-registers,C++,Function,Compiler Construction,Parameter Passing,Cpu Registers,我想知道某种结构是否包含多个原语,但其总大小小于或等于单个cpu寄存器(如4字节寄存器)的大小,当编译器通过值或引用向函数传递它时,而不是在被调用方堆栈上复制它或传递指向它的指针时,以及通常向函数(如数组或结构)传递多于一个原语的内容时,将它放入其中一个4字节寄存器,这有意义吗登记册有用吗 此类结构的示例: struct sample{ public: char char1; char char2; }; 将结构传递给函数的示例: void someFunc(const sample

我想知道某种结构是否包含多个原语,但其总大小小于或等于单个cpu寄存器(如4字节寄存器)的大小,当编译器通过值或引用向函数传递它时,而不是在被调用方堆栈上复制它或传递指向它的指针时,以及通常向函数(如数组或结构)传递多于一个原语的内容时,将它放入其中一个4字节寄存器,这有意义吗登记册有用吗

此类结构的示例:

struct sample{
 public:
  char char1;
  char char2;
};
将结构传递给函数的示例:

void someFunc(const sample input){
 //whatever
}
void someFunc(sample input){
 //whatever
}
void someFunc(sample & input){
 //whatever
}
void someFunc(const sample & input){
 //whatever
}
在某些体系结构上(比如i386,我知道它很古老,但我就是这样长大的;)在寄存器中传递它肯定是有意义的,因为从堆栈中推送和弹出需要比在寄存器中传递更多的CPU周期(比如3-6倍)。因此,编译器可以很好地对此进行优化

我可以想象,在其他架构中,这并不重要。或者,如果寄存器正在用于其他优化,从而产生更多的改进,那么将它们用于此目的是没有意义的

您正在使用/定位什么体系结构,或者您一般都在问什么?

这是在您的执行环境的应用程序二进制接口(ABI)中定义的。该标准在调用函数时没有提到处理器寄存器,因此创建一个将小结构打包到单个处理器寄存器中的环境是合法的


对于引用部分,它们很可能作为指针传递,因为在调用的函数中获取引用的地址时,它必须解析为引用对象的地址。

我认为有些编译器会在寄存器中传递POD,即使它们是
结构体

是的。许多编译器都有一个特殊的关键字或类型属性,可用于指定结构应在寄存器中传递,而不是在堆栈中传递。它在具有许多寄存器和深层管道的处理器上更为常见,如PowerPC,在将值写入内存然后立即重新读取会导致管道暂停的体系结构中,它可以极大地提高性能

通常,您只会将其用于与本机寄存器大小相同的结构。特别是,它在具有宽SIMD寄存器的处理器上非常有用,该寄存器一次可以传递16个字节或更多字节。这将允许您在一个寄存器上传递(例如)一个四维向量(四个浮点)。是允许此操作的x86 ABI的一个示例

另一个例子是GCC的d64_abi类型属性,它告诉PowerPC尽可能在寄存器上传递结构,而不是在堆栈上。(这是报告的一部分)

在上面的例子中,对Foo的调用将在一个浮点寄存器和两个int寄存器上传递Thingy,而不是将其写入堆栈并再次读取。返回值以相同的方式返回到寄存器


我从来没有见过一个编译器在你不告诉它的情况下自动完成这项工作,但它可能存在。

你可能想打破句子中的条虫。我很难消化它。我希望我知道它们是什么@Crashworks:事实上,我希望所有主流编译器(VC、GCC)都能做到这一点。恐怕没那么多。例如,MSVC变成:它通过将每个字符单独推送到堆栈上来传递一个双字符结构,即使是在“完全优化”时也是如此。当Foo()和Bar()同时出现时,它会做得更好静态是在同一个编译单元中,它可以忽略调用约定。@Crashworks\u但在一个int寄存器中放入两个字符是没有意义的,对吗?@Pooria:一点也不——这可能比在函数调用期间对堆栈进行两次往返快得多。@Crashworks\u我的意思是,因为最终的目的是对每个int寄存器执行一些操作在我所问的结构中的这两个字节中,它们应该在单独的寄存器中,如果它们位于一个int寄存器中,那么以后应该将它们分开,以便对每个字节执行操作。@Pooria:当然——这取决于编译器和ABI是否可以拥有“在连续寄存器中传递此结构”属性,即在一个芯片上,可能没有足够的备用寄存器来传递多个值;在另一个芯片上,您可能可以一次传递八个寄存器。
typedef struct {
    int          a;
    float        f;
    char         c;
} __attribute__ ((d64_abi)) Thingy;

Thingy foo( Thingy t );