第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在 C 和 Go 中傳遞指針而不是返回新變量?

在 C 和 Go 中傳遞指針而不是返回新變量?

Go
哆啦的時光機 2022-10-17 16:49:14
為什么在 C 和 Go 中約定將指針傳遞給變量并更改它而不是返回帶有值的新變量?在 C 中:#include <stdio.h>int getValueUsingReturn() {    int value = 42;    return value;}void getValueUsingPointer(int* value ) {    *value = 42;}int main(void) {  int valueUsingReturn = getValueUsingReturn();  printf("%d\n", valueUsingReturn);  int valueUsingPointer;  getValueUsingPointer(&valueUsingPointer);  printf("%d\n", valueUsingPointer);  return 0;}在圍棋中:package mainimport "fmt"func getValueUsingReturn() int {    value := 42    return value}func getValueUsingPointer(value *int) {    *value = 42}func main() {    valueUsingReturn := getValueUsingReturn()    fmt.Printf("%d\n", valueUsingReturn)    var valueUsingPointer int    getValueUsingPointer(&valueUsingPointer)    fmt.Printf("%d\n", valueUsingPointer)}做其中一項是否有任何性能優(yōu)勢或限制?
查看完整描述

2 回答

?
富國滬深

TA貢獻1790條經驗 獲得超9個贊

首先,我對 Go 的了解不夠,無法對其做出判斷,但答案將適用于 C 的情況。


如果您只是在研究像ints 這樣的原始類型,那么我會說這兩種技術之間沒有性能差異。


當structs 發(fā)揮作用時,通過指針修改變量有一個非常小的優(yōu)勢(純粹基于您在代碼中所做的事情)


#include <stdio.h>


struct Person {

    int age;

    const char *name;

    const char *address;

    const char *occupation;

};


struct Person getReturnedPerson() {

    struct Person thePerson = {26, "Chad", "123 Someplace St.", "Software Engineer"};

    return thePerson;

}


void changeExistingPerson(struct Person *thePerson) {

    thePerson->age = 26;

    thePerson->name = "Chad";

    thePerson->address = "123 Someplace St.";

    thePerson->occupation = "Software Engineer";

}


int main(void) {

  struct Person someGuy = getReturnedPerson();

  


  struct Person theSameDude;

  changeExistingPerson(&theSameDude);

  

  

  return 0;

}

GCC x86-64 11.2


沒有優(yōu)化


通過函數的 return返回struct變量比較慢,因為必須通過分配所需的值來“構建”變量,然后將變量復制到返回值。


當您通過指針間接修改變量時,除了將所需的值寫入內存地址(基于您傳入的指針)之外,別無他法


.LC0:

        .string "Chad"

.LC1:

        .string "123 Someplace St."

.LC2:

        .string "Software Engineer"

getReturnedPerson:

        push    rbp

        mov     rbp, rsp

        mov     QWORD PTR [rbp-40], rdi

        mov     DWORD PTR [rbp-32], 26

        mov     QWORD PTR [rbp-24], OFFSET FLAT:.LC0

        mov     QWORD PTR [rbp-16], OFFSET FLAT:.LC1

        mov     QWORD PTR [rbp-8], OFFSET FLAT:.LC2

        mov     rcx, QWORD PTR [rbp-40]

        mov     rax, QWORD PTR [rbp-32]

        mov     rdx, QWORD PTR [rbp-24]

        mov     QWORD PTR [rcx], rax

        mov     QWORD PTR [rcx+8], rdx

        mov     rax, QWORD PTR [rbp-16]

        mov     rdx, QWORD PTR [rbp-8]

        mov     QWORD PTR [rcx+16], rax

        mov     QWORD PTR [rcx+24], rdx

        mov     rax, QWORD PTR [rbp-40]

        pop     rbp

        ret

changeExistingPerson:

        push    rbp

        mov     rbp, rsp

        mov     QWORD PTR [rbp-8], rdi

        mov     rax, QWORD PTR [rbp-8]

        mov     DWORD PTR [rax], 26

        mov     rax, QWORD PTR [rbp-8]

        mov     QWORD PTR [rax+8], OFFSET FLAT:.LC0

        mov     rax, QWORD PTR [rbp-8]

        mov     QWORD PTR [rax+16], OFFSET FLAT:.LC1

        mov     rax, QWORD PTR [rbp-8]

        mov     QWORD PTR [rax+24], OFFSET FLAT:.LC2

        nop

        pop     rbp

        ret

main:

        push    rbp

        mov     rbp, rsp

        sub     rsp, 64

        lea     rax, [rbp-32]

        mov     rdi, rax

        mov     eax, 0

        call    getReturnedPerson

        lea     rax, [rbp-64]

        mov     rdi, rax

        call    changeExistingPerson

        mov     eax, 0

        leave

        ret

輕微優(yōu)化


但是,今天的大多數編譯器都可以弄清楚您在這里嘗試做什么,并將平衡兩種技術之間的性能。


如果你想絕對小氣,傳遞指針仍然會稍微快幾個時鐘周期。


在從函數返回一個變量時,你至少還需要設置返回值的地址。


        mov     rax, rdi

但是在傳遞指針時,甚至沒有這樣做。


但除此之外,這兩種技術沒有性能差異。


.LC0:

        .string "Chad"

.LC1:

        .string "123 Someplace St."

.LC2:

        .string "Software Engineer"

getReturnedPerson:

        mov     rax, rdi

        mov     DWORD PTR [rdi], 26

        mov     QWORD PTR [rdi+8], OFFSET FLAT:.LC0

        mov     QWORD PTR [rdi+16], OFFSET FLAT:.LC1

        mov     QWORD PTR [rdi+24], OFFSET FLAT:.LC2

        ret

changeExistingPerson:

        mov     DWORD PTR [rdi], 26

        mov     QWORD PTR [rdi+8], OFFSET FLAT:.LC0

        mov     QWORD PTR [rdi+16], OFFSET FLAT:.LC1

        mov     QWORD PTR [rdi+24], OFFSET FLAT:.LC2

        ret

main:

        mov     eax, 0

        ret


查看完整回答
反對 回復 2022-10-17
?
繁華開滿天機

TA貢獻1816條經驗 獲得超4個贊

我認為對您的問題的簡短回答(至少對于 C,我不熟悉 GO 內部)是 C 函數是按值傳遞的,通常也按值返回,因此必須復制數據對象,人們擔心所有的性能復制。對于大型對象或深度復雜的對象(包含指向其他內容的指針),將被復制的值作為指針通常更有效或更合乎邏輯,因此函數可以“操作”數據而無需復制它. 話雖如此,現代編譯器在確定參數數據是否適合寄存器或有效復制返回的結構等內容方面非常聰明。底線是現代 C 代碼做最適合您的應用程序或對您來說最清楚的事情。如果至少在開始時會降低可讀性,請避免過早優(yōu)化。還有編譯器資源管理器(https://godbolt.org/)是你的朋友,如果你想檢查不同風格的效果,特別是在優(yōu)化方面。



查看完整回答
反對 回復 2022-10-17
  • 2 回答
  • 0 關注
  • 134 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號