AMcoder - javascript, python, java, html, php, sql

Ի՞նչ է անում extern inline-ը:

Ես հասկանում եմ, որ inline-ն ինքնին առաջարկ է կոմպիլյատորին, և իր հայեցողությամբ այն կարող է կամ չներդնել ֆունկցիան, և այն նաև կարտադրի կապակցվող օբյեկտի կոդ:

Կարծում եմ, որ static inline-ն անում է նույնը (կարող է կամ ոչ ներդիր), բայց չի արտադրի կապվող օբյեկտի կոդը, երբ ներկառուցված է (քանի որ ոչ մի այլ մոդուլ չի կարող կապվել դրան):

Որտե՞ղ է extern inline-ը տեղավորվում նկարում:

Ենթադրենք, որ ես ուզում եմ փոխարինել նախապրոցեսորային մակրոն ներգծային ֆունկցիայով և պահանջել, որ այս ֆունկցիան ներկառուցվի (օրինակ, որովհետև այն օգտագործում է __FILE__ և __LINE__ մակրոները, որոնք պետք է լուծվեն զանգահարողի համար, բայց ոչ այս կոչվող ֆունկցիան): Այսինքն՝ ես ուզում եմ տեսնել կոմպիլյատորի կամ կապողի սխալ, եթե ֆունկցիան ներգծված չլինի։ Արդյո՞ք extern inline-ը դա անում է: (Ես ենթադրում եմ, որ եթե դա չլինի, ապա այս վարքագծին հասնելու այլ կերպ չկա, քան մակրոյով մնալը):

Կա՞ն տարբերություններ C++-ի և C-ի միջև:

Կա՞ն տարբերություններ տարբեր կոմպիլյատորների վաճառողների և տարբերակների միջև:


Պատասխանները:


1

K&R C-ում կամ C89-ում ներդիրը լեզվի մաս չէր: Շատ կոմպիլյատորներ այն իրականացրել են որպես ընդլայնում, սակայն դրա աշխատանքի վերաբերյալ հստակ իմաստաբանություն չկար: GCC-ն առաջիններից էր, ով ներդրեց ինլինինգը և ներկայացրեց inline, static inline և extern inline կառուցվածքները; C99-ից առաջ կոմպիլյատորների մեծ մասը հիմնականում հետևում է իր օրինակին:

GNU89:

  • inline. ֆունկցիան կարող է գծված լինել (թեև դա պարզապես հուշում է): Արտահերթ տարբերակը միշտ արտանետվում է և արտաքինից տեսանելի: Հետևաբար, դուք կարող եք ունենալ միայն մեկ կոմպիլյատորային միավորում սահմանված այդպիսի ներդիր, և յուրաքանչյուր մյուսը պետք է այն դիտի որպես գծից դուրս ֆունկցիա (կամ հղման ժամանակ դուք կստանաք կրկնօրինակ նշաններ):
  • extern inline-ը չի ստեղծի գծից դուրս տարբերակ, այլ կարող է կանչել այն (որը, հետևաբար, դուք պետք է սահմանեք որևէ այլ կոմպիլյատորական միավորում: Այնուամենայնիվ, կիրառվում է մեկ սահմանման կանոնը. գծից դուրս տարբերակը պետք է ունենա նույն կոդը, ինչ այստեղ առաջարկվող inline-ը, այն դեպքում, երբ կոմպիլյատորը դրա փոխարեն կանչի:
  • static inline-ը չի ստեղծի արտաքին տեսանելի գծից դուրս տարբերակ, թեև այն կարող է ստեղծել ստատիկ ֆայլ: Մեկ սահմանման կանոնը չի կիրառվում, քանի որ երբեք չի լինում արտանետվող արտաքին խորհրդանիշ կամ զանգ մեկին:

C99 (կամ GNU99):

  • inline՝ ինչպես GNU89 «արտաքին ներդիր»; ոչ մի արտաքին տեսանելի ֆունկցիա չի արտանետվում, բայց մեկը կարող է կանչվել և այդպես պետք է գոյություն ունենա
  • extern inline. ինչպես GNU89 «inline»-ը. արտանետվում է արտաքին տեսանելի կոդը, ուստի առավելագույնը մեկ թարգմանական միավոր կարող է օգտագործել սա:
  • static inline՝ ինչպես GNU89 «ստատիկ ներդիրում»: Սա միակ շարժականն է gnu89-ի և c99-ի միջև

C++:

Գործառույթը, որը ներգծված է ցանկացած վայրում, պետք է լինի ներդիր ամենուր՝ նույն սահմանմամբ: Կոմպիլյատորը/կցորդը կդասավորի խորհրդանիշի բազմաթիվ օրինակներ: static inline կամ extern inline-ի սահմանում չկա, չնայած շատ կոմպիլյատորներ ունեն դրանք (սովորաբար հետևում են gnu89 մոդելին):

19.10.2008
  • Դասական C-ում «inline»-ը հիմնաբառ չէր. այն հասանելի էր որպես փոփոխականի անուն օգտագործելու համար: Սա կվերաբերի C89-ին և նախնական (K&R) C-ին: 19.10.2008
  • Դուք ճիշտ եք, կարծես: Ամրագրված. Կարծում էի, որ այն վերապահված էր որպես բանալի բառ C89-ում (չնայած ոչ K&R-ում), բայց կարծես սխալ էի հիշում 19.10.2008
  • Ես կցանկանայի ավելացնել, որ Microsoft-ի Visual C++-ի համար կա __forceinline հիմնաբառ, որը կստիպի ձեր ֆունկցիան ներգծել: Սա ակնհայտորեն կոմպիլյատորին հատուկ ընդլայնում է միայն VC++-ի համար: 17.01.2014
  • Կա՞ որևէ տարբերություն C99 արտաքին ներգծային և ընդհանրապես ոչ մի սպեցիֆիկատորների միջև: 29.04.2017
  • Իմաստային առումով ոչ; ճիշտ այնպես, ինչպես ոչ ներգծային ֆունկցիան, extern inline-ը ենթակա է մեկ սահմանման կանոնին, և սա է սահմանումը: Բայց եթե իրականացման կողմից սահմանված օպտիմալացման էվրիստիկաները հետևում են inline հիմնաբառը որպես առաջարկություն, որ գործառույթի զանգերը հնարավորինս արագ լինեն (ISO 9899:1999 §6.7.4 (5), extern inline հաշվում 11.05.2017
  • @Noora Gcc-ի համարժեքը __attribute__((always_inline)) է: Այն ստիպում է ֆունկցիան ներգծվել, նույնիսկ եթե օպտիմալացումներն անջատված են: Այն օգտակար է չափազանց կարճ գործառույթների համար, որոնք կոչվում են չափազանց հաճախ, օրինակ, վեկտորային մաթեմատիկական գրադարաններում, որոնք թույլ են տալիս վրիպազերծումը դանդաղեցնել, երբ օպտիմիզացիան անջատված է, եթե դրանք ներգծված չեն: 18.10.2017
  • Դուք հաստատ սխալվում եք միակ շարժականի հարցում; տես իմ պատասխանը. 08.07.2018
  • Այսպիսով, եթե ես ճիշտ հասկացա, C++-ում, վերնագրի ֆայլում սահմանվում է inline (ոչ static inline) ֆունկցիա, ինչպես C99 inline-ում, այն տարբերությամբ, որ C++-ում ոչ մի աղբյուր (.cxx) ֆայլ դրա համար հայտարարագիր չի ունենա (in C99, ճիշտ մեկ աղբյուր (.c) ֆայլ պետք է նախատիպին տրամադրի extern inline, որը կունենա միակ և միակ սահմանումը համապատասխան օբյեկտի .o ֆայլում): Ճիշտ? 03.07.2021

  • 2

    Կարծում եմ, որ դուք սխալ եք հասկանում __FILE__-ը և __LINE__-ը՝ հիմնվելով այս հայտարարության վրա.

    քանի որ այն օգտագործում է __FILE__ և __LINE__ մակրոները, որոնք պետք է լուծվեն զանգահարողի համար, բայց ոչ այս կոչվող գործառույթը

    Կազմման մի քանի փուլ կա, և նախնական մշակումն առաջինն է: __FILE__-ը և __LINE__-ը փոխարինվում են այդ փուլում: Այսպիսով, մինչ կոմպիլյատորը կարող է դիտարկել ներկառուցման գործառույթը, դրանք արդեն փոխարինված են:

    19.10.2008

    3

    Թվում է, թե դուք փորձում եք գրել այսպիսի բան.

    inline void printLocation()
    {
      cout <<"You're at " __FILE__ ", line number" __LINE__;
    }
    
    {
    ...
      printLocation();
    ...
      printLocation();
    ...
      printLocation();
    

    և հուսալով, որ ամեն անգամ տարբեր արժեքներ կստանաք: Ինչպես ասում է Դոնը, դուք չեք անի, քանի որ __FILE__-ը և __LINE__-ն իրականացվում են նախապրոցեսորի կողմից, իսկ inline-ն իրականացվում է կոմպիլյատորի կողմից: Այսպիսով, որտեղից էլ զանգահարեք printLocation, դուք կստանաք նույն արդյունքը:

    միակ միջոցը, որով դուք կարող եք դա գործի դնել, printLocation-ը մակրո դարձնելն է: (Այո ես գիտեմ...)

    #define PRINT_LOCATION  {cout <<"You're at " __FILE__ ", line number" __LINE__}
    
    ...
      PRINT_LOCATION;
    ...
      PRINT_LOCATION;
    ...
    
    19.10.2008
  • Տարածված հնարքն այն է, որ PRINT_LOCATION մակրոները կանչում են printLocation ֆունկցիան՝ որպես պարամետրեր փոխանցելով FILE և LINE: Սա կարող է հանգեցնել ավելի լավ վրիպազերծիչի/խմբագրի/և այլնի վարքագծի, երբ ֆունկցիայի մարմինը աննշան է: 21.10.2008
  • @Roddy Նայեք իմ լուծմանը՝ ձեր ընդլայնումը, բայց ավելի ընդգրկուն և ընդարձակելի: 07.08.2012
  • @SteveJessop Ինչ-որ բան, ինչպիսին ես թվարկեցի ստորև ներկայացված լուծումում: 09.08.2012

  • 4

    Փոխանակ պատասխանելու, թե ինչ է դա անում, ես պատասխանում եմ, թե ինչպես անեմ այն, ինչ ուզում եմ: Գոյություն ունեն ներդիրների 5 տեսակ, բոլորը հասանելի են GNU C89-ում, ստանդարտ C99-ում և C++-ում: MSVC-ն ունի դրանցից որոշ (նշեք, որ ես չեմ փորձարկել MSVC կոդը)

    always inline, unless the address is taken

    Ցանկացած հայտարարության մեջ ավելացրեք __attribute__((always_inline)), այնուհետև օգտագործեք ստորև բերված դեպքերից մեկը՝ դրա հասցեի ընդունման հնարավորությունը կարգավորելու համար:

    Դուք, հավանաբար, երբեք չպետք է օգտագործեք սա, եթե դրա իմաստաբանությունը ձեզ հարկավոր չէ (օրինակ՝ որոշակի ձևով ազդելու ժողովի վրա կամ օգտագործել alloca): Կոմպիլյատորը սովորաբար ձեզնից լավ գիտի, արդյոք արժե այն:

    MSVC-ն ունի __forceinline, որը հիմնականում նույնն է թվում, բայց, ըստ երևույթին, այն հրաժարվում է ներդնել բավականին սովորական հանգամանքներում (օրինակ, երբ օպտիմիզացումն անջատված է), որտեղ մյուս կոմպիլյատորները լավ են աշխատում:

    inline and emit a weak symbol (like C++, aka "just make it work")

    __attribute__((weak))
    void foo(void);
    inline void foo(void) { ... }
    

    Նկատի ունեցեք, որ դա թողնում է նույն կոդի մի փունջ կրկնօրինակներ, և կապողն ընտրում է մեկը կամայականորեն:

    MSVC-ն, ըստ երևույթին, չունի ճշգրիտ համարժեք C ռեժիմում, չնայած կան մի քանի նմանատիպ բաներ: Թվում է, թե __declspec(selectany)-ը խոսում է միայն տվյալների մասին, ուստի մի՞թե չի կիրառվում գործառույթների վրա: Կա նաև կապող աջակցություն թույլ կեղծանունների համար, բայց արդյո՞ք դա աշխատում է այստեղ:

    inline, but never emit any symbol (leaving external references)

    __attribute__((gnu_inline))
    extern inline void foo(void) { ... }
    

    MSVC-ի __declspec(dllimport)-ը, զուգորդված փաստացի սահմանման հետ (այլապես անսովոր), ենթադրաբար դա անում է:

    emit always (for one TU, to resolve the preceding)

    Ակնարկվող տարբերակը թույլ նշան է հաղորդում C++-ում, բայց ուժեղ խորհրդանիշ C-ի երկու բարբառներում.

    void foo(void);
    inline void foo(void) { ... }
    

    Կամ դուք կարող եք դա անել առանց ակնարկի, որն արտահայտում է ուժեղ խորհրդանիշ երկու լեզուներով.

    void foo(void) { ... }
    

    Ընդհանրապես, դուք գիտեք, թե ինչ լեզվով է ձեր TU-ն, երբ տալիս եք սահմանումները, և, հավանաբար, շատ գծագրման կարիք չունեք:

    MSVC-ի __declspec(dllexport)-ն ենթադրաբար դա անում է:

    inline and emit in every TU

    static inline void foo(void) { ... }
    

    Այս բոլորի համար, բացի static-ից, կարող եք վերևում ավելացնել void foo(void) հայտարարություն: Սա օգնում է մաքուր վերնագրեր գրելու լավագույն պրակտիկային, այնուհետև #includeառանձին ֆայլ ստեղծելու ներկառուցված սահմանումներով: Այնուհետև, եթե օգտագործում եք C ոճի ներդիրներ, #define որոշ մակրո տարբեր կերպ մեկ հատուկ TU-ում՝ տրամադրելու գծից դուրս սահմանումներ:

    Մի մոռացեք extern "C"-ը, եթե վերնագիրը կարող է օգտագործվել ինչպես C-ից, այնպես էլ C++-ից:


    Կան նաև մի քանի հարակից բաներ.

    never inline

    Ֆունկցիայի ցանկացած հայտարարությանն ավելացրեք __attribute__((noinline)):

    MSVC-ն ունի __declspec(noinline), բայց այն փաստաթղթավորված է, որ աշխատում է միայն անդամի գործառույթների համար: Այնուամենայնիվ, ես տեսել եմ անվտանգության հատկանիշների հիշատակում, որոնք կարող են կանխել ներդիրումը:

    force other functions to be inlined into this one if possible.

    Ավելացնել __attribute__((flatten)) ֆունկցիայի ցանկացած հայտարարության:

    Նկատի ունեցեք, որ noinline-ն ավելի հզոր է, քան սա, ինչպես նաև գործառույթները, որոնց սահմանումը հայտնի չէ կոմպիլյացիայի ժամանակ:

    MSVC-ն, ըստ երևույթին, չունի համարժեք: Ես տեսել եմ [[msvc::forceinline_calls]]-ի մեկ հիշատակում (կիրառվել է հայտարարության կամ արգելափակման համար), բայց դա ռեկուրսիվ չէ:

    08.07.2018
  • Բացակայում է. ինչ վերաբերում է MSVC-ին: Այն ունի C89 բարբառային ընդլայնումներ, բայց ես երբեք չեմ օգտագործում MSVC և չգիտեմ, թե ինչպես գործարկել դրա nm համարժեքը: 08.07.2018
  • Գործի #4 void foo(void); inline void foo(void) { ... } վերնագիրը միշտ թողարկվում է (մեկ TU-ի համար՝ նախորդը լուծելու համար): Մյուս 4-ը սկսվում է ներգծով ..... 4-ի դեպքում՝ դա էլ է ներտող: 09.12.2020
  • @chux-ReinstateMonica Inlining-ը ավելի շատ սիմվոլների պահվածքի, քան կատարողականի մասին է: Կազմողին թույլատրվում է ներդնել կատարման համար՝ անկախ նրանից, թե հիմնաբառը առկա է, թե ոչ (ենթակա է միջդիրքային կանոնների): Թիվ 4 գործի կարևոր մասն այն է, թե ինչպես է այն առնչվում #3 գործի չլուծված նշաններին. հաճախ չկան (մ) զանգահարողներ այդ TU-ում, այնուամենայնիվ: 10.12.2020
  • Իմ մեկնաբանությունն ավելի շատ վերաբերում էր նրան, թե ինչու 1,2,3,5 դեպքերում այս պատասխանն իրենց վերնագրի նկարագրության մեջ inline ունեն, իսկ 4-ը՝ ոչ: Դուք առաջարկում եք, որ այն դեպքում, երբ 4 ծածկագիրը երբեք գծագրված չէ, միշտ գծագրված է, երբեմն գծագրված: Արդյո՞ք թիվ 4 գործի ներկառուցված հնարավորությունները տարբերվում են մյուս 4-ից: 10.12.2020

  • 5

    Ներքին, ստատիկ ներգծային և արտաքին ներգծի հետ կապված իրավիճակը բարդ է, հատկապես այն պատճառով, որ gcc-ն և C99-ը մի փոքր տարբեր իմաստներ են սահմանում իրենց վարքագծի համար (և, ենթադրաբար, նաև C++): Դուք կարող եք գտնել որոշ օգտակար և մանրամասն տեղեկություններ այն մասին, թե ինչ են նրանք անում C այստեղ< /ա>.

    19.10.2008

    6

    Այստեղ մակրոները ձեր ընտրությունն են, այլ ոչ թե ներդիրային գործառույթները: Հազվագյուտ դեպք, երբ մակրոները իշխում են ներկառուցված գործառույթների վրա: Փորձեք հետևյալը. ես գրել եմ այս «MACRO MAGIC» կոդը և այն պետք է աշխատի: Փորձարկվել է gcc/g++ Ubuntu 10.04-ի վրա

    //(c) 2012 enthusiasticgeek (LOGGING example for StackOverflow)
    
    #ifdef __cplusplus
    
    #include <cstdio>
    #include <cstring>
    
    #else
    
    #include <stdio.h>
    #include <string.h>
    
    #endif
    
    //=========== MACRO MAGIC BEGINS ============
    
    //Trim full file path
    #define __SFILE__ (strrchr(__FILE__,'/') ? strrchr(__FILE__,'/')+1 : __FILE__ )
    
    #define STRINGIFY_N(x) #x
    #define TOSTRING_N(x) STRINGIFY_N(x)
    #define _LINE (TOSTRING_N(__LINE__))
    
    #define LOG(x, s...) printf("(%s:%s:%s)"  x "\n" , __SFILE__, __func__, _LINE, ## s);
    
    //=========== MACRO MAGIC ENDS ============
    
    int main (int argc, char** argv) {
    
      LOG("Greetings StackOverflow! - from enthusiasticgeek\n");
    
      return 0;
    }
    

    Բազմաթիվ ֆայլերի համար սահմանեք այս մակրոները առանձին վերնագրի ֆայլում, ներառյալ նույնը յուրաքանչյուր c/cc/cxx/cpp ֆայլում: Խնդրում ենք նախապատվությունը տալ ներկառուցված գործառույթներին կամ կոնստի նույնացուցիչներին (ըստ գործի պահանջի) մակրոներից, որտեղ հնարավոր է:

    06.08.2012
    Նոր նյութեր

    Օգտագործելով Fetch Vs Axios.Js-ը՝ HTTP հարցումներ կատարելու համար
    JavaScript-ը կարող է ցանցային հարցումներ ուղարկել սերվեր և բեռնել նոր տեղեկատվություն, երբ դա անհրաժեշտ լինի: Օրինակ, մենք կարող ենք օգտագործել ցանցային հարցումը պատվեր ներկայացնելու,..

    Տիրապետել հանգստության արվեստին. մշակողի ուղեցույց՝ ճնշման տակ ծաղկելու համար
    Տիրապետել հանգստության արվեստին. մշակողի ուղեցույց՝ ճնշման տակ ծաղկելու համար Ինչպե՞ս հանգստացնել ձեր միտքը և աշխատեցնել ձեր պրոցեսորը: Ինչպես մնալ հանգիստ և զարգանալ ճնշման տակ...

    Մեքենայի ուսուցում բանկային և ֆինանսների ոլորտում
    Բարդ, խելացի անվտանգության համակարգերը և հաճախորդների սպասարկման պարզեցված ծառայությունները բիզնեսի հաջողության բանալին են: Ֆինանսական հաստատությունները, մասնավորապես, պետք է առաջ մնան կորի..

    Ես AI-ին հարցրի կյանքի իմաստը, այն ինչ ասում էր, ցնցող էր:
    Այն պահից ի վեր, երբ ես իմացա Արհեստական ​​ինտելեկտի մասին, ես հիացած էի այն բանով, թե ինչպես է այն կարողանում հասկանալ մարդկային նորմալ տեքստը, և այն կարող է առաջացնել իր սեփական արձագանքը դրա..

    Ինչպես սովորել կոդավորումը Python-ում վագրի պես:
    Սովորելու համար ծրագրավորման նոր լեզու ընտրելը բարդ է: Անկախ նրանից, թե դուք սկսնակ եք, թե առաջադեմ, դա օգնում է իմանալ, թե ինչ թեմաներ պետք է սովորել: Ծրագրավորման լեզվի հիմունքները, դրա..

    C++-ի օրական բիթ(ե) | Ամենաերկար պալինդրոմային ենթաշարը
    C++ #198-ի ամենօրյա բիթ(ե), Ընդհանուր հարցազրույցի խնդիր. Ամենաերկար պալինդրոմային ենթատող: Այսօր մենք կանդրադառնանք հարցազրույցի ընդհանուր խնդրին. Ամենաերկար palindromic substring...

    Kydavra ICAReducer՝ ձեր տվյալների ծավալայինությունը նվազեցնելու համար
    Ի՞նչ է ICAReducer-ը: ICAReducer-ն աշխատում է հետևյալ կերպ. այն նվազեցնում է նրանց միջև բարձր փոխկապակցված հատկանիշները մինչև մեկ սյունակ: Բավականին նման է PCAreducer-ին, չնայած այն..