මම malloc හි ප්‍රති result ලය දමන්නේද?


2418

දී මේ ප්රශ්නය , යමෙකු යෝජනා අදහස් මම කළ යුතු බව නොවේ ප්රතිඵලයක් ප්රකාශ mallocඑනම්,

int *sieve = malloc(sizeof(int) * length);

ඊට වඩා:

int *sieve = (int *) malloc(sizeof(int) * length);

මෙය එසේ වන්නේ ඇයි?


224
එසේම, sieve = malloc (sizeof * sieve * length) ලිවීම වඩා නඩත්තු කළ හැකිය;
විලියම් පර්සෙල්


5
මෙහි පිළිතුරු ඒක පාර්ශවීයත්වයේ බිම් බෝම්බයකි. පිළිතුර "එය රඳා පවතී" යන්නයි. වැඩසටහන ක්‍රියාත්මක කිරීම සඳහා එය අත්‍යවශ්‍ය දෙයක් නොවේ. කෙසේ වෙතත් සමහර කේතීකරණ ප්‍රමිතීන්ට එය අවශ්‍ය වේ ... නිදසුනක් ලෙස, CERT C
වෛද්‍ය පුද්ගලයා II

පුදුමයට කරුණක් නම්, ඔබ දමන්නේ නැති බවට සියලු දෙනා එකඟ NULLවෙති. (C ++ හඳුන්වා දුන්නේ ඒ නිසා විය හැකිය nullptr: C ++ කිසිදු ඇඟවුම් දර්ශකයකට ඉඩ නොදේ)
Sapphire_Brick

ඔබට පුළුවන්, නමුත් ඔබට අවශ්‍ය නැහැ. නමුත් ඔබට C ++ අවශ්‍ය වේ.
ඔස්කාර් මහතා

Answers:


2227

නැත ; ඔබ ප්‍රති result ලය දමන්නේ නැත ,

  • void *මෙම නඩුවේ වෙනත් ඕනෑම දර්ශක වර්ගයකට ස්වයංක්‍රීයව හා ආරක්ෂිතව ප්‍රවර්ධනය වන පරිදි එය අනවශ්‍යය .
  • එය කේතයට කැළඹීමක් එක් කරයි, වාත්තු කියවීම එතරම් පහසු නැත (විශේෂයෙන් දර්ශක වර්ගය දිගු නම්).
  • එය ඔබව නැවත නැවත කිරීමට සලස්වයි, එය සාමාන්‍යයෙන් නරක ය.
  • ඔබට ඇතුළත් කිරීමට අමතක වූවා නම් එය දෝෂයක් සැඟවිය හැක <stdlib.h>. මෙය බිඳවැටීම් වලට හේතු විය හැක (හෝ, වඩාත් නරක නම්, පසුව කේතයේ සම්පූර්ණයෙන්ම වෙනස් කොටසක බිඳ වැටීමක් ඇති නොකරන්න ). දර්ශක සහ නිඛිල ප්‍රමාණයෙන් වෙනස් නම් කුමක් සිදුවේදැයි සලකා බලන්න; එවිට ඔබ වාත්තු කිරීමෙන් අනතුරු ඇඟවීමක් සඟවන අතර ඔබගේ ආපසු එවූ ලිපිනයෙන් ටිකක් අහිමි විය හැකිය. සටහන: C99 වන විට ව්‍යංග ශ්‍රිත C වෙතින් ඉවත් වී ඇති අතර, ප්‍රකාශයට පත් නොකළ ශ්‍රිත නැවත පැමිණෙන බවට ස්වයංක්‍රීය උපකල්පනයක් නොමැති බැවින් මෙම කරුණ තවදුරටත් අදාළ නොවේ int.

පැහැදිලි කිරීමක් ලෙස, මා කීවේ “ඔබ වාත්තු නොකරන්න”, “ඔබට වාත්තු කිරීමට අවශ්‍ය නැත ” යන්නයි. මගේ මතය අනුව, ඔබ එය නිවැරදිව තේරුම් ගත්තද, නළු නිළියන් ඇතුළත් කිරීමට අපොහොසත් වේ. එය කිරීමෙන් කිසිදු ප්‍රතිලාභයක් නොමැත, නමුත් විභව අවදානම් සමූහයක් සහ නළු නිළියන් ඇතුළත් කිරීමෙන් පෙන්නුම් කරන්නේ ඔබ අවදානම් ගැන නොදන්නා බවයි.

විචාරකයින් පෙන්වා දෙන පරිදි, ඉහත සඳහන් වන්නේ C ++ නොව සෘජු C ගැන ය. සී සහ සී ++ වෙනම භාෂාවන් ලෙස මම තරයේ විශ්වාස කරමි.

තව දුරටත් එකතු කිරීම සඳහා, ඔබේ කේතය අනවශ්‍ය ලෙස intදෝෂ ඇති විය හැකි තොරතුරු ( ) නැවත නැවත කරයි . ප්‍රතිලාභ අගය ගබඩා කිරීම සඳහා භාවිතා කරන දර්ශකය අවලංගු කිරීම වඩා හොඳය, දෙක එකට "අගුළු දැමීම":

int *sieve = malloc(length * sizeof *sieve);

lengthදෘශ්‍යතාව වැඩි කිරීම සඳහා මෙය ඉදිරිපස දෙසට ගමන් කරන අතර අතිරික්ත වරහන් සමඟ පහත වැටේ sizeof; ඒවා අවශ්‍ය වන්නේ තර්කය වර්ග නාමයක් වූ විට පමණි . බොහෝ අය මෙය නොදන්නා බව පෙනේ (හෝ නොසලකා හැරේ), එමඟින් ඔවුන්ගේ කේතය වඩාත් වාචික වේ. මතක තබා ගන්න: sizeofශ්‍රිතයක් නොවේ! :)


ගමන් කරමින් lengthඉදිරියට හැක : සමහර දුර්ලභ අවස්ථාවල දී පමාණය වැඩි, එක් ද සාමාන්ය අවස්ථාවක, එය ප්රකාශ කිරීම ලිවීමට වඩා හොඳ විය යුතු බව අවධානය යොමු කළ යුතුයි

int *sieve = malloc(sizeof *sieve * length);

sizeofපළමුවැන්න තබා ගැනීමෙන් , මේ අවස්ථාවේ දී, අවම වශයෙන් size_tගණිතය සමඟ ගුණ කිරීම සිදු කරන බව සහතික කරයි .

සංසන්දනය: malloc(sizeof *sieve * length * width)එදිරිව malloc(length * width * sizeof *sieve), දෙවන ඉතිරී හැක length * widthවිට widthහා lengthවඩා කුඩා වර්ග size_t.


24
කරුණාකර පිළිතුර යාවත්කාලීන කිරීම සලකා බලන්න. වාත්තු කිරීම තවදුරටත් භයානක නොවන අතර, නැවත නැවත කියවීම නරක දෙයක් නොවේ (අතිරික්තය දෝෂ හඳුනා ගැනීමට උපකාරී වේ).
n. 'සර්වනාම' එම්.

12
සම්පාදකයින් වෙනස් වී ඇත. යාවත්කාලීන සම්පාදකයෙකු විසින් malloc පිළිබඳ අස්ථානගත වූ ප්‍රකාශයක් ගැන ඔබට අනතුරු අඟවනු ඇත.
n. 'සර්වනාම' එම්.

56
හරි. මෙහි කියවන ඕනෑම කෙනෙකුට විශේෂිත සම්පාදකයෙකු ඇතැයි උපකල්පනය කිරීම නරක යැයි මම සිතමි. එසේම, C11 සමස්ත "ව්‍යංග ශ්‍රිතය" සංකල්පය නැති වී ඇති හෙයින් මම එය දැන සිටියේ නැත. තවමත්, අර්ථ විරහිත වාත්තු එකතු කිරීමේ කාරණය මට නොපෙනේ. ඔබත් int x = (int) 12;දේවල් පැහැදිලි කිරීමට පමණක් කරනවාද?
ලිහිල්

23
mnm පැහැදිලිවම අවලංගු දර්ශකයක් වාත්තු කිරීම දෝෂයක් විසඳීමට “උදව්” කළහොත්, ඔබට බොහෝ විට නිර්වචනය නොකළ හැසිරීම් වලට මුහුණ දීමට සිදුවනු ඇත, එයින් අදහස් කෙරෙනුයේ ප්‍රශ්නයට ලක්වූ වැඩසටහනට වඩා නරක, සොයා නොගත් දෝෂයක් ඔබ තවමත් ක්‍රියාත්මක කර නොමැති බවයි. එක් දිනක්, සීතල ශීත සවස් වරුවක, ඔබ වැඩ ඇරී ගෙදර එනු ඇත, ඔබගේ GitHub පිටුව ජලයෙන් යටවී ඇති බව සොයා ගැනීම, පරිශීලකයන්ගේ නාසයෙන් යක්ෂයන් පියාසර කිරීම ගැන පැමිණිලි කිරීම
බ්‍රැඩන් බෙස්ට්

14
මම ඔබ සමඟ එකඟ වුවත් (int)12එය සැසඳිය නොහැක. 12 යනු int, වාත්තු හුදෙක් කිසිවක් කර නැත. නැවත ලබා ගැනීම malloc()යනු void *දර්ශක වර්ගය නොවේ. (එය එසේ නොවේ නම් void *. ඒ නිසා ප්ලේටෝ කිරීමට (int)12වනු ඇත (void*)malloc(…)කිසිවෙක් සාකච්ඡා දේ.)
අමීන් Negm-Awad

378

C හි, ඔබට ප්‍රතිලාභ අගය දැමිය යුතු නැත malloc. ආපසු ලබා දුන් අවලංගු කිරීමේ දර්ශකය mallocස්වයංක්‍රීයව නිවැරදි වර්ගයට පරිවර්තනය වේ. කෙසේ වෙතත්, ඔබේ කේතය C ++ සම්පාදකයෙකු සමඟ සම්පාදනය කිරීමට ඔබට අවශ්‍ය නම්, වාත්තු කිරීමක් අවශ්‍ය වේ. ප්‍රජාව අතර වඩාත් කැමති විකල්පයක් වන්නේ පහත සඳහන් දෑ භාවිතා කිරීමයි:

int *sieve = malloc(sizeof *sieve * length);

එමඟින් ඔබ වර්ගය වෙනස් කරන්නේ නම් ප්‍රකාශනයේ දකුණු පස වෙනස් කිරීම ගැන කරදර වීමට ඉඩ නොදේ sieve.

මිනිසුන් පෙන්වා දී ඇති පරිදි, වාත්තු නරක ය. විශේෂයෙන් දර්ශක කැස්ට්.


73
@MAKZ මම තර්ක malloc(length * sizeof *sieve)කරන්නේ එය sizeofවිචල්‍යයක් ලෙස පෙනේ - එබැවින් malloc(length * sizeof(*sieve))වඩා කියවිය හැකි යැයි සිතමි .
මයිකල් ඇන්ඩර්සන්

22
හා malloc(length * (sizeof *sieve))වඩා පහසුවෙන් කියවිය හැකි තවමත්. IMHO.
ටෝබි ස්පයිට්

20
Ic මයිකල් ඇන්ඩර්සන් ()නිකුතුව පසෙකට දමන්න, ඔබ යෝජනා කළ ශෛලිය අනුපිළිවෙල වෙනස් කළ බව සලකන්න., මූලද්‍රව්‍ය ගණන ගණනය කරන විට සලකා බලන්න, මෙම නඩුවේ පළමුවැන්න length*widthතබා ගැනීම sizeofඅවම වශයෙන් ගණිතයකින් ගුණ කිරීම සිදු කරන බව සහතික size_tකරයි. malloc(sizeof( *ptr) * length * width)එදිරිව සසඳන්න malloc(length * width * sizeof (*ptr))- දෙවැන්න කුඩා වර්ග වන length*widthවිට පිරී ඉතිරී යයි . width,lengthsize_t
chux - මොනිකා

3
uxchux එය පැහැදිලිව පෙනෙන්නට නැත, නමුත් පිළිතුර සංස්කරණය කර ඇති බැවින් මගේ අදහස එතරම් අදාළ නොවේ - මුල් යෝජනාව වූයේmalloc(sizeof *sieve * length)
මයිකල් ඇන්ඩර්සන්

12
C යනු C ++ නොවේ. ඔවුන් බව මවා පෑම අවසානයේ ව්‍යාකූලත්වයට හා දුකට හේතු වේ. ඔබ C ++ භාවිතා කරන්නේ නම්, C- විලාසිතාවේ වාත්තු කිරීම ද නරක ය (ඔබ ඉතා පැරණි C ++ සම්පාදකයක් භාවිතා නොකරන්නේ නම්). හා static_cast>()(හෝ reinterpret_cast<>()) සී ඕනෑම භාෂාව සමඟ අනුකූල නොවේ
ඩේවිඩ් සී

351

ඔබ කරන්නේ නිසා, ප්රකාශ:

  • එය ඔබේ කේතය සී සහ සී ++ අතර වඩා අතේ ගෙන යා හැකි අතර, SO අත්දැකීම් වලින් පෙන්නුම් කරන පරිදි, බොහෝ ක්‍රමලේඛකයින් කියා සිටින්නේ ඔවුන් ඇත්ත වශයෙන්ම සී ++ (හෝ සී ප්ලස් දේශීය සම්පාදක දිගු) වලින් ලියන විට ඔවුන් සී හි ලියන බවයි.
  • එසේ කිරීමට අපොහොසත් වීමෙන් දෝෂයක් සැඟවිය හැක : type *එදිරිව ලිවිය යුත්තේ කවදාද යන්න ව්‍යාකූල කිරීමේ සියලු SO උදාහරණ සටහන් කරන්නtype ** .
  • #includeසුදුසු ශීර්ෂ ගොනුවකට ඔබ අසමත් වීම නොදැනීමෙන් එය ඔබව වළක්වයි යන අදහස ගස් සඳහා වනාන්තරය මග හැරේ . එය සමාන වන්නේ "මූලාකෘති නොදැකීම ගැන පැමිණිලි කිරීමට ඔබ සම්පාදකයාගෙන් ඉල්ලා සිටීමට අපොහොසත් වූ කාරණය ගැන කරදර නොවන්න - කරදරකාරී stdlib.h යනු මතක තබා ගත යුතු වැදගත්ම දෙයයි!"
  • එය අතිරේක සංජානන හරස් පරීක්ෂාවකට බල කරයි. එමඟින් එම විචල්‍යයේ අමු ප්‍රමාණය සඳහා ඔබ කරන ගණිතයට යාබදව (චෝදනා කරන ලද) අපේක්ෂිත වර්ගය තබයි. malloc()වාත්තු කිරීමක් ඇති විට දෝෂ වඩාත් වේගයෙන් හසු වන බව පෙන්වන SO අධ්‍යයනයක් ඔබට කළ හැකි යැයි මම සිතමි . ප්‍රකාශයන් මෙන්ම, අභිප්‍රාය හෙළි කරන විවරණයන් දෝෂ අඩු කරයි.
  • යන්ත්‍රයට පරීක්ෂා කළ හැකි ආකාරයකින් ඔබම පුනරාවර්තනය කිරීම බොහෝ විට හොඳ අදහසකි. ඇත්ත වශයෙන්ම, එය ප්‍රකාශයක් වන අතර, වාත්තු කිරීම මෙම ප්‍රකාශය තහවුරු කිරීමකි. මීට වසර ගණනාවකට පෙර ටියුරින් විසින් මෙම අදහස ඉදිරිපත් කළ බැවින්, කේත නිවැරදිව ලබා ගැනීම සඳහා අප සතුව ඇති සාමාන්‍ය තාක්‍ෂණය තවමත් ප්‍රකාශයන්ය.

39
@ulidtko ඔබ නොදැන සිටියේ නම්, C සහ C ++ ලෙස සම්පාදනය කරන කේත ලිවිය හැකිය. ඇත්ත වශයෙන්ම බොහෝ ශීර්ෂ ලිපිගොනු මේ හා සමාන වන අතර ඒවා බොහෝ විට කේත (මැක්‍රෝස් සහ පේළිගත කිරීමේ කාර්යයන්) අඩංගු වේ. දෙකම සම්පාදනය කිරීමට .c/ .cppගොනුවක් තිබීම බොහෝ විට ප්‍රයෝජනවත් නොවේ, නමුත් එක් අවස්ථාවක් වන්නේ throwC ++ සම්පාදකයා සමඟ සම්පාදනය කරන විට C ++ සහාය එකතු කිරීමයි (නමුත් return -1;C සම්පාදකයා සමඟ සම්පාදනය කරන විට හෝ වෙනත් ඕනෑම දෙයක්).
හයිඩ්

37
යමෙකුට ශීර්ෂ පා in යක් තුළ අනිෂ්ට ඇමතුම් තිබේ නම්, මා පුදුමයට පත් නොවනු ඇත, #ifdef __cplusplus සහ බාහිර "C" {this මෙම කාර්යය සඳහා මිස අමතර වාත්තු එකතු නොකරයි.
පෝල්ම්

15
හොඳයි, ඔබේ ඇමතුමේ විචල්‍යය භාවිතා කරන්නේ නම්, සී! = සී ++ බැවින් අනෙක් කරුණු ද සුළුපටු නොවේ malloc: char **foo = malloc(3*sizeof(*foo));තරමක් පූර්ණ-සාධනය නම්: වර්‍ග දර්ශකයන්ට ලකුණු 3 ක්. ඉන්පසු ලූප් කර කරන්න foo[i] = calloc(101, sizeof(*(foo[i])));. අක්ෂර 101 කින් යුත් අරාව, ශුන්‍යයට පිළිවෙලින් ආරම්භ කරන්න. වාත්තු කිරීම අවශ්‍ය නොවේ. unsigned charඑම කාරණය සඳහා ප්‍රකාශය හෝ වෙනත් වර්ගයකට වෙනස් කරන්න, ඔබ තවමත් හොඳයි
එලියාස් වැන් ඔටෙගෙම්

35
මම එය ලබා ගත් විට, එය පැමිණේ! අපූරු පිළිතුර. ස්ටැක් ඕවර්ෆ්ලෝ හි දී මම ප්‍රතිවිරුද්ධ පිළිතුරු දෙකක් +1 කළ පළමු අවස්ථාව මෙයයි! +1 නැත, ඔබ දමන්නේ නැත, +1 ඔව්, ඔබ දමන්න! LOL. ඔයාලා හරිම භයානකයි. මට සහ මගේ ශිෂ්‍යයන් සඳහා, මම මගේ මනස යොමු කළෙමි: මම වාත්තු කරමි. වාත්තු කිරීමේදී සිසුන් කරන ආකාරයේ දෝෂ වඩාත් පහසුවෙන් හඳුනාගත හැකිය.
ආචාර්ය බෙකෝ

15
E ලුෂෙන්කෝ: යන්ත්‍රයකින් හෝ දේශීය පරීක්ෂාවකින් වලංගු කළ නොහැකි ආකාරයකින් ඔබ නැවත නැවත කිරීම නරක ය. එවැනි මාර්ගයකින් වලංගු කළ හැකි ආකාරවලින් ඔබම නැවත නැවත කියවීම අඩු නරක ය. ලබා struct Zebra *p; ... p=malloc(sizeof struct Zebra);දී ඇති පරිදි , p වර්ගයේ තොරතුරු අනුපිටපත් කිරීම වළක්වා ගැනීමට malloc හට නොහැක, නමුත් එක් වර්ගයක් වෙනස් වූ නමුත් අනෙකා එසේ නොකළේ නම් සම්පාදකයාට හෝ ප්‍රාදේශීය කේත පරීක්ෂාවට කිසිදු ගැටළුවක් හඳුනාගත නොහැක. කේතය වෙනස් කරන්න, p=(struct Zebra*)malloc(sizeof struct Zebra);වාත්තු වර්ගය නොගැලපේ නම් සම්පාදකයා p
දඟලනු

171

අනෙක් අය සඳහන් කළ පරිදි, එය C සඳහා අවශ්‍ය නොවේ, නමුත් C ++ සඳහා අවශ්‍ය වේ. ඔබ ඔබේ C කේතය C ++ සම්පාදකයෙකු සමඟ සම්පාදනය කිරීමට යන්නේ යැයි ඔබ සිතන්නේ නම්, කුමන හේතුවක් නිසා හෝ ඔබට ඒ වෙනුවට සාර්ව භාවිතා කළ හැකිය:

#ifdef __cplusplus
# define NEW(type, count) ((type *)calloc(count, sizeof(type)))
#else
# define NEW(type, count) (calloc(count, sizeof(type)))
#endif

ඒ ආකාරයෙන් ඔබට එය තවමත් ඉතා සංයුක්ත ආකාරයකින් ලිවිය හැකිය:

int *sieve = NEW(int, 1);

එය C සහ C ++ සඳහා සම්පාදනය කරනු ඇත.


17
ඔබ කෙසේ හෝ සාර්වයක් භාවිතා කරන බැවින්, ඔබ newC ++ අර්ථ දැක්වීමේදී භාවිතා නොකරන්නේ ඇයි ?
හොසම් අලි

64
එසේ කිරීමට හේතුවක් නොමැති නිසා. එය ප්‍රධාන වශයෙන් C ++ සම්පාදකයෙකු සමඟ සම්පාදනය කරන ලද C වැඩසටහන් සඳහා ය. ඔබ 'නව' භාවිතා කිරීමට යන්නේ නම්, ඔබට ලැබෙන එකම දෙය ගැටළු පමණි. එවිට ඔබට නොමිලේ සාර්වයක් ද අවශ්‍ය වේ. අරාව නිදහස් කිරීමට ඔබට
සාර්වයක් අවශ්‍යය,

8
මතකය නිදහස් කරන්නේ ඔබ නොව ඔබ භාවිතා කරන සී පුස්තකාලය යනාදිය ගැන සඳහන් නොකල යුතුය.
quinmars

87
Os හොසම්: ඔව්, එය අනිවාර්යයෙන්ම. ඔබ භාවිතා කරන්නේ නම් ඔබ භාවිතා newකළ යුතු deleteඅතර ඔබ භාවිතා කරන්නේ නම් malloc()ඔබ අනිවාර්යයෙන්ම සිටිය යුතුය free(). ඒවා කිසි විටෙකත් මිශ්‍ර නොකරන්න.
ග්‍රේම් පෙරෝ

18
යමෙක් මෙම ප්‍රවේශය ගැනීමට යන්නේ නම්, සාර්ව ඇමතීම NEWබොහෝ විට නරක අදහසක් විය හැකි බැවින් සම්පත කිසි විටෙකත් delete(හෝ DELETE) භාවිතා කර ආපසු නොඑන බැවින් ඔබ ඔබේ වචන මාලාව මිශ්‍ර කරයි. ඒ වෙනුවට, එය නම් කිරීම MALLOC, හෝ CALLOCමේ අවස්ථාවේ දී, වඩාත් අර්ථවත් වනු ඇත.
mah

142

සිට විකිපීඩියා, නිදහස් විශ්වකෝෂය :

වාත්තු කිරීමෙන් ලැබෙන වාසි

  • වාත්තු කිරීම ඇතුළුව C වැඩසටහනක් හෝ ශ්‍රිතයක් C ++ ලෙස සම්පාදනය කිරීමට ඉඩ දෙනු ඇත.

  • වාත්තු මඟින් 1989 ට පෙර මාලොක් අනුවාදයක් ලබා දී ඇත.

  • ගමනාන්ත දර්ශක වර්ගය වෙනස් වුවහොත්, විශේෂයෙන් දර්ශකය malloc () ඇමතුමට වඩා දුරින් ප්‍රකාශයට පත් කළ හොත් (නවීන සම්පාදකයින්ට සහ ස්ථිතික විශ්ලේෂකයන්ට වාත්තු අවශ්‍යතාවයකින් තොරව එවැනි හැසිරීම් ගැන අනතුරු ඇඟවිය හැකි වුවද) වර්ගය ප්‍රමාණයේ නොගැලපීම් හඳුනා ගැනීමට වාත්තු කරන්නාට උදව් කළ හැකිය.

වාත්තු කිරීමේ අවාසි

  • ANSI C ප්‍රමිතිය යටතේ, වාත්තු අතිරික්ත වේ.

  • වාත්තු එකතු කිරීම stdlib.h ශීර්ෂය ඇතුළත් කිරීමට අපොහොසත් විය හැක, malloc සඳහා වන මූලාකෘතිය සොයාගත්. Malloc සඳහා මූලාකෘතියක් නොමැති විට, ප්‍රමිතියට C සම්පාදකයා විසින් malloc විසින් int එකක් ලබා දෙන බව උපකල්පනය කළ යුතුය. වාත්තු කිරීමක් නොමැති නම්, මෙම නිඛිලය දර්ශකයට පවරා ඇති විට අනතුරු ඇඟවීමක් කරනු ලැබේ; කෙසේ වෙතත්, වාත්තු සමඟ, මෙම අනතුරු ඇඟවීම නිපදවන්නේ නැත, එය දෝෂයක් සඟවයි. සමහර ගෘහ නිර්මාණ ශිල්පය සහ දත්ත ආකෘති මත (දිගු හා දර්ශක 64-බිට් සහ int 32-bit වන 64-බිට් පද්ධතිවල LP64 වැනි), මෙම දෝෂය ඇත්ත වශයෙන්ම නිර්වචනය නොකළ හැසිරීමට හේතු විය හැක, ව්‍යංගයෙන් ප්‍රකාශිත malloc 32- බිට් අගය වන අතර සත්‍ය වශයෙන්ම අර්ථ දක්වා ඇති ශ්‍රිතය බිට් 64 අගයක් ලබා දෙයි. ඇමතුම් සම්මුතීන් සහ මතක සැකැස්ම මත පදනම්ව, මෙය තොග කුඩු කිරීමට හේතු විය හැක. නවීන සම්පාදකයින්ගේ අවධානයට ලක් නොවීමට ඇති ඉඩකඩ අඩුය, ප්‍රකාශයට පත් නොකළ ශ්‍රිතයක් භාවිතා කර ඇති බවට අනතුරු ඇඟවීම් ඔවුන් ඒකාකාරව ඉදිරිපත් කරන බැවින් අනතුරු ඇඟවීමක් තවමත් දිස්වනු ඇත. නිදසුනක් ලෙස, GCC හි පෙරනිමි හැසිරීම නම්, වාත්තු කිරීම තිබේද නැද්ද යන්න නොසලකා "ගොඩනංවන ලද ශ්‍රිතයේ නොගැලපෙන ව්‍යංග ප්‍රකාශය" කියවන අනතුරු ඇඟවීමකි.

  • දර්ශකයේ වර්ගය එහි ප්‍රකාශනයේදී වෙනස් කර ඇත්නම්, කෙනෙකුට malloc ලෙස හඳුන්වන හා වාත්තු කරන සියලුම රේඛා වෙනස් කිරීමට අවශ්‍ය විය හැකිය.

නමුත් වාත්තු තොරව malloc කැමති ක්රමය වන අතර, වඩාත්ම පළපුරුදු වැඩසටහන්කරුවන් එය තෝරා , ඔබ ප්රශ්න දැනුවත් සහිත මෙන් ඔබ යන දෙකෙන් භාවිතා කළ යුතු වේ.

එනම්: ඔබට C වැඩසටහන C ++ ලෙස සම්පාදනය කිරීමට අවශ්‍ය නම් (එය වෙනම භාෂාවක් වුවද) ඔබ භාවිතයේ ප්‍රති result ලය දැමිය යුතුය malloc.


1
කුමක්ද "නැහැ පුංචි සංවර්ධක වර්ගය sizing දී නොගැලපීම් හඳුනා ගැනීමට උපකාර කළ හැකි පෙන්නුම් කරන්නක් දුර සිට ප්රකාශයට පත් කරන්නේ, විශේෂයෙන් නම්, ගමනාන්තය පහිටුම් දක්වනය වර්ගය වෙනස් විය යුතු malloc()ඇමතුමක් " අදහස්? ඔබට උදාහරණයක් දිය හැකිද?
ස්පිකැට්‍රික්ස්

3
O කූල්ගුයි: වෙනත් පිළිතුරක් සඳහා කලින් අදහස් දැක්වීමක් බලන්න . නමුත් p = malloc(sizeof(*p) * count)මෝඩය ස්වයංක්‍රීයව වර්ගයෙහි වෙනස්කම් ඇති කරන බව සලකන්න , එබැවින් ඔබට අනතුරු ඇඟවීම් ලබාගෙන කිසිවක් වෙනස් කිරීමට අවශ්‍ය නැත. එබැවින් මෙය වාත්තු නොකිරීමට හොඳම විකල්පයට එදිරිව සැබෑ වාසියක් නොවේ.
පීටර් කෝඩ්ස්

8
මෙය නිසි පිළිතුරයි: වාසි සහ අවාසි ඇත, එය රසයට තම්බා ගනී (කේතය C ++ ලෙස සම්පාදනය කළ යුතු නම් මිස - වාත්තු කිරීම අනිවාර්ය වේ).
පීටර් - මොනිකා

3
3 වන ලක්ෂ්‍යය වැදගත් වේ, මන්ද යත්, දර්ශකයේ වර්ගය එහි ප්‍රකාශනයේ දී වෙනස් කර ඇත්නම්, යමෙකු එම වර්ගයේ malloc, realloc සහ නොමිලේ ඇතුල් වන සෑම අවස්ථාවක්ම පරීක්ෂා කළ යුතුය. වාත්තු කිරීම ඔබට එය කිරීමට බල කරනු ඇත.
මයිකල් රෝයි

106

C හි ඔබට voidවෙනත් ඕනෑම ආකාරයක දර්ශකයක් වෙත ව්‍යංගයෙන් පරිවර්තනය කළ හැකිය , එබැවින් වාත්තු කිරීම අවශ්‍ය නොවේ. එකක් භාවිතා කිරීම අනියම් නිරීක්ෂකයාට යෝජනා කිරීමට අවශ්‍ය වන්නේ යම් හේතුවක් අවශ්‍ය බව, එය නොමඟ යවන සුළු විය හැකිය.


102

ඔබ malloc හි ප්‍රති result ලය නොදක්වයි, මන්ද එසේ කිරීමෙන් ඔබේ කේතයට තේරුමක් නැති කැළඹීමක් ඇති වේ.

මිනිසුන් malloc හි ප්‍රති result ල ලබා දීමට වඩාත්ම පොදු හේතුව වන්නේ C භාෂාව ක්‍රියා කරන ආකාරය පිළිබඳව ඔවුන් නොදන්නා බැවිනි. එය අනතුරු ඇඟවීමේ ලකුණකි: විශේෂිත භාෂා යාන්ත්‍රණයක් ක්‍රියාත්මක වන්නේ කෙසේදැයි ඔබ නොදන්නේ නම්, අනුමාන නොකරන්න . එය සොයා බලන්න හෝ Stack Overflow වෙතින් විමසන්න.

සමහර අදහස්:

  • අවලංගු දර්ශකයක් පැහැදිලි වාත්තු කිරීමකින් තොරව වෙනත් ඕනෑම දර්ශක වර්ගයකට / සිට පරිවර්තනය කළ හැකිය (C11 6.3.2.3 සහ 6.5.16.1).

  • කෙසේ වෙතත්, C ++ void*සහ වෙනත් දර්ශක වර්ගයක් අතර ව්‍යංග වාත්තු කිරීමට ඉඩ නොදේ . එබැවින් C ++ හි වාත්තු කිරීම නිවැරදි වනු ඇත. නමුත් ඔබ C ++ හි වැඩසටහන් කරන්නේ නම්, ඔබ භාවිතා කළ යුත්තේ newmalloc () නොවේ. ඔබ කිසි විටෙකත් C ++ සම්පාදකයක් භාවිතා කර C කේතය සම්පාදනය නොකළ යුතුය.

    ඔබට එකම ප්‍රභව කේතයක් සමඟ C සහ C ++ යන දෙකටම සහාය වීමට අවශ්‍ය නම්, වෙනස්කම් සලකුණු කිරීමට සම්පාදක ස්විච භාවිතා කරන්න. භාෂා ප්‍රමිතීන් දෙකම එකම කේතයකින් සැකසීමට උත්සාහ නොකරන්න, මන්ද ඒවා අනුකූල නොවේ.

  • ඔබට ශීර්ෂකය ඇතුළත් කිරීමට අමතක වූ නිසා සී සම්පාදකයෙකුට ශ්‍රිතයක් සොයාගත නොහැකි නම්, ඔබට ඒ පිළිබඳ සම්පාදක / සම්බන්ධක දෝෂයක් ලැබෙනු ඇත. එබැවින් එය <stdlib.h>ලොකු දෙයක් නොවන බව ඇතුළත් කිරීමට ඔබට අමතක වූවා නම් , ඔබේ වැඩසටහන ගොඩනගා ගැනීමට ඔබට නොහැකි වනු ඇත.

  • අවුරුදු 25 ට වඩා පැරණි සම්මතයේ අනුවාදයක් අනුගමනය කරන පුරාණ සම්පාදකයින් මත, ඇතුළත් <stdlib.h>කිරීමට අමතක කිරීමෙන් භයානක හැසිරීමක් ඇති වේ. මන්ද එම පුරාණ ප්‍රමිතියේ, දෘශ්‍ය මූලාකෘතියක් නොමැතිව ක්‍රියා කිරීමෙන් ඇඟවුම් කරන්නේ ආපසු එන වර්ගය බවට පරිවර්තනය වීමයි int. Malloc වෙතින් ප්‍රති result ලය පැහැදිලිවම වාත්තු කිරීමෙන් පසුව මෙම දෝෂය සැඟවිය හැක.

    නමුත් එය සැබවින්ම ගැටළුවක් නොවේ. ඔබ අවුරුදු 25 ක් පැරණි පරිගණකයක් භාවිතා නොකරයි, එබැවින් ඔබ අවුරුදු 25 ක් පැරණි සම්පාදකයක් භාවිතා කරන්නේ ඇයි?


12
“අර්ථ විරහිත කැළඹීම” යනු ඔබ සමඟ දැනටමත් එකඟ නොවන ඕනෑම කෙනෙකුට ඒත්තු ගැන්වීමේ හැකියාව අඩාල කරන නැඹුරු හයිපර්බෝල් ය. රංගනය නිසැකවම අර්ථ විරහිත නොවේ; රොන් බර්ක්ගේ සහ කාස්ගේ පිළිතුරු මා බොහෝ සෙයින් එකඟ වන වාත්තු කිරීමට පක්ෂව තර්ක ඉදිරිපත් කරයි. ඔබ සඳහන් කරන උත්සුකයන්ට වඩා එම උත්සුකයන් බරද යන්න විමසීමට සාධාරණ ප්‍රශ්නයකි. මට නම්, ඔබගේ උත්සුකයන් ඒවාට සාපේක්ෂව සුළු වශයෙන් පෙනේ.
දොන් හැච්

“අවලංගු දර්ශකයක් පැහැදිලි වාත්තු කිරීමකින් තොරව වෙනත් ඕනෑම දර්ශක වර්ගයකට / සිට පරිවර්තනය කළ හැකිය” 6.3.2.3 සහය නොදක්වයි. සමහර විට ඔබ "ඕනෑම වස්තු වර්ගයකට යොමු කිරීම" ගැන සිතනවාද? “අවලංගු දර්ශකය” සහ “ශ්‍රිතයක් සඳහා දර්ශකය” එතරම් පහසුවෙන් පරිවර්තනය කළ නොහැක.
chux - මොනිකා නැවත ස්ථාපනය කරන්න

ඇත්ත වශයෙන්ම යොමු කිරීම අසම්පූර්ණ විය. “ව්‍යංගාර්ථය” සඳහා අදාළ කොටස සරල පැවරුමේ නියමය 6.5.16.1. "එක් ඔපෙරන්ඩ් එකක් යනු වස්තු වර්ගයක් සඳහා වන දර්ශකයක් වන අතර අනෙක සුදුසුකම් ලත් හෝ නුසුදුසු අනුවාදයක් සඳහා වන දර්ශකයකි". මම මෙම සඳහන සම්පූර්ණත්වය සඳහා පිළිතුරට එකතු කර ඇත්තෙමි.
ලුන්ඩින්

93

C හි ඔබට void *වෙනත් (දත්ත) දර්ශකයකට ව්‍යංග පරිවර්තනයක් ලැබේ .


6
En ජෙන්ස්: හරි, සමහර විට වඩාත් සුදුසු වචන “ව්‍යංග පරිවර්තනය” විය හැකිය. පාවෙන ලක්ෂ්‍ය ප්‍රකාශනයේ සමෝධානික විචල්‍යය භාවිතා කිරීම වැනි.
EFraim

FEFraim ඇත්ත වශයෙන්ම එහි ප්‍රති cast ලය වනුයේ වාත්තු කිරීමක් වන අතර එයින් ගම්‍ය වේ.
පිස්සු භෞතික විද්‍යා

71

ආපසු ලබා දුන් අගය සටහන් malloc()කිරීම දැන් අවශ්‍ය නොවේ, නමුත් කිසිවෙකු පෙන්වා නැති බව පෙනෙන එක් කරුණක් එක් කිරීමට මම කැමතියි:

පුරාණ දිනවල, එනම්, ANSI C මඟින් void *සාමාන්‍ය වර්ගයේ දර්ශකයන් char *සැපයීමට පෙර, එවැනි භාවිතය සඳහා වර්ගය වේ. එවැනි අවස්ථාවකදී, නළුවන්ට සම්පාදක අනතුරු ඇඟවීම් වසා දැමිය හැකිය.

යොමුව: සී නිති අසන ප්‍රශ්න


3
සම්පාදක අනතුරු ඇඟවීම් වසා දැමීම නරක අදහසකි.
ඇල්බට් වැන් ඩර් හෝස්ට්

9
L ඇල්බට්වන්ඩර්හෝර්ස්ට් ඔබ එසේ කරන්නේ නම් නිශ්චිත ගැටළුව විසඳා ගැනීමෙන් අනතුරු ඇඟවීමක් තිබේ.
ඩෑන් බෙචර්ඩ්

An ඩෑන්. නිශ්චිත ගැටළුව විසඳීම මගින් චාර් * වෙනුවට නවීන ANSI C වර්ග නැවත ලබා දීම සඳහා සබ්මැරීනයක් නැවත ලිවීම අදහස් කරන්නේ නම්, මම එකඟ වෙමි. සම්පාදකය වසා දැමීම මම නොකියමි. සම්පාදක අනතුරු ඇඟවීම් නොමැති බව අවධාරනය කරන කළමනාකරුවන්ට ඉඩ නොදෙන්න, හැකි සෑම ගැටලුවක්ම සොයා ගැනීම සඳහා එක් එක් නැවත සකස් කිරීම මඟින් ඒවා භාවිතා කිරීම වෙනුවට. ග්‍රොට්ජස් ඇල්බට්
ඇල්බට් වැන් ඩර් හෝස්ට්

53

මගේ අත්දැකීම් එකතු කරමින්, පරිගණක ඉංජිනේරු විද්‍යාව හැදෑරූ විට, සී හි ලිවීම මා දුටු මහාචාර්යවරුන් දෙදෙනා හෝ තිදෙනා සෑම විටම මල්ලෝක් වාදනය කරන බව මට පෙනේ, කෙසේ වෙතත් මා ඇසූ තැනැත්තා (සී පිළිබඳ විශාල අවබෝධයක් සහ සී පිළිබඳ අවබෝධයක් සහිතව) මට කීවේ එය අනවශ්‍ය නමුත් භාවිතා කරනුයේ නියත වශයෙන්ම නිශ්චිත වන අතර, ශිෂ්‍යයන් නියත වශයෙන්ම නිශ්චිත වීමේ මානසිකත්වයට ඇතුළත් කර ගැනීම සඳහා ය. අත්යවශ්යයෙන්ම වාත්තු කිරීම එය ක්රියා කරන ආකාරයෙහි කිසිවක් වෙනස් නොකරනු ඇත, එය පවසන දේ හරියටම කරයි, මතකය වෙන් කරයි, සහ වාත්තු කිරීම එය බලපාන්නේ නැත, ඔබට එකම මතකය ලැබෙනු ඇත, සහ ඔබ එය වැරදීමකින් වෙනත් දෙයකට දැමුවද (සහ කෙසේ හෝ සම්පාදකයා මග හැරේ) දෝෂ) C එයට එකම ආකාරයකින් ප්‍රවේශ වේ.

සංස්කරණය කරන්න: වාත්තු කිරීම නිශ්චිත කරුණක් ඇත. ඔබ අරාව අංකනය භාවිතා කරන විට, ජනනය කරන ලද කේතයට ඊළඟ මූලද්‍රව්‍යයේ ආරම්භය කරා ළඟා වීමට මතක ස්ථාන කීයක් තිබිය යුතු දැයි දැනගත යුතුය, මෙය වාත්තු කිරීමෙන් ලබා ගත හැකිය. මේ ආකාරයෙන් ඔබ දන්නවා දෙගුණයක් සඳහා ඔබ බයිට් 8 ක් ඉදිරියට යන අතර ඉන්ටර් එකක් සඳහා ඔබ 4 ක් යනවා. මේ අනුව ඔබ දර්ශක අංකනය භාවිතා කරන්නේ නම් එය කිසිදු බලපෑමක් ඇති නොකරයි, අරාව අංකනය කිරීමේදී එය අවශ්‍ය වේ.


3
දැනටමත් සඳහන් කර ඇති ඒවා හැරුණු විට, වාත්තු මඟින් දෝෂ සැඟවිය හැකි අතර සම්පාදක හෝ ස්ථිතික විශ්ලේෂකය සඳහා කේතය විශ්ලේෂණය කිරීම දුෂ්කර කරයි.
ලුන්ඩින්

2
"අත්‍යවශ්‍යයෙන්ම වාත්තු කිරීම එය ක්‍රියා කරන ආකාරයෙහි කිසිවක් වෙනස් නොකරනු ඇත". ගැලපෙන වර්ගයට වාත්තු කිරීම කිසිවක් වෙනස් නොකළ යුතුය, නමුත් var වර්ගය වෙනස් වීම සහ වාත්තු කිරීම තවදුරටත් නොගැලපේ නම් ගැටළු මතු විය හැකිද? IWOs, වාත්තු සහ var වර්ගය සමමුහුර්තව තබා ගත යුතුය - නඩත්තු කටයුතු මෙන් දෙගුණයක්.
chux - මොනිකා නැවත ස්ථාපනය කරන්න

1
මහාචාර්යවරු වාත්තු කිරීමට කැමති ඇයිදැයි මට පෙනේ. උපදේශක තොරතුරු වෙත යොමු කරන අධ්‍යාපනික දෘෂ්ටි කෝණයකින් වාත්තු කිරීම ප්‍රයෝජනවත් විය හැකි අතර ශිෂ්‍ය කේතය නඩත්තු කිරීම අවශ්‍ය නොවේ - එය විසි කිරීමේ කේතය. කේතීකරණයෙන්, සම-සමාලෝචන සහ නඩත්තු දෘෂ්ටිකෝණයකින්, p = malloc(sizeof *p * n);එය ඉතා සරල හා වඩා හොඳය.
chux - මොනිකා නැවත ස්ථාපනය කරන්න

53

එය එසේ නොවේ අනිවාර්ය ප්රතිඵල ප්රකාශ කිරීම සඳහා වන mallocඑය නැවත පටන් void*, සහ void*ඕනෑම datatype පෙන්වා ගත හැක.


36

මේ මොකක්ද මේ ග්නූ සී පුස්තකාලය විමර්ශන අත්පොත පවසයි:

mallocඅයිඑස්ඕ සී ස්වයංක්‍රීයව වර්ගය void *වෙනත් ආකාරයක දර්ශකයක් බවට පරිවර්තනය කරන හෙයින් ඔබට අවශ්‍ය විටදී ඕනෑම දර්ශක විචල්‍යයකට වාත්තු කිරීමකින් තොරව ගබඩා කළ හැකිය . පැවරුම් ක්‍රියාකරුවන් හැරුණු විට හෝ ඔබේ කේතය සාම්ප්‍රදායික සී තුළ ක්‍රියාත්මක වීමට අවශ්‍ය නම් වාත්තු කිරීම අවශ්‍ය වේ.

ඇත්ත වශයෙන්ම ISO C11 ප්‍රමිතිය (p347) මෙසේ පවසයි:

වෙන් කිරීම සාර්ථක වුවහොත් ආපසු හරවන ලද දර්ශකය සුදුසු ලෙස පෙළගස්වා ඇති අතර එමඟින් මූලික පෙළගැස්වීමේ අවශ්‍යතාවයක් ඇති ඕනෑම වර්ගයක වස්තුවකට දර්ශකය වෙත පැවරිය හැකි අතර පසුව වෙන් කරන ලද අවකාශයේ එවැනි වස්තුවකට හෝ එවැනි වස්තු සමූහයකට ප්‍රවේශ වීමට භාවිතා කරයි ( අවකාශය පැහැදිලිවම වෙන් කර ඇත)


35

අවලංගු දර්ශකයක් යනු සාමාන්‍ය වස්තු දර්ශකයක් වන අතර, සී අවලංගු දර්ශක වර්ගයක සිට වෙනත් වර්ගවලට ව්‍යංග පරිවර්තනයට සහය දක්වයි, එබැවින් එය පැහැදිලිව යතුරු ලියනය කිරීමේ අවශ්‍යතාවයක් නොමැත.

කෙසේ වෙතත්, එකම කේතය සී ++ වේදිකාවක් මත පරිපූර්ණ ලෙස අනුකූල වීමට අවශ්‍ය නම්, එය ව්‍යංග පරිවර්තනයට සහාය නොදක්වයි, ඔබ යතුරු ලියනය කිරීම කළ යුතුය, එබැවින් ඒ සියල්ල භාවිතාව මත රඳා පවතී.


2
තනි ප්‍රභවයක් C සහ C ++ ලෙස සම්පාදනය කිරීම සාමාන්‍ය භාවිත අවස්ථාවක් නොවේ (ඊට ප්‍රතිවිරුද්ධව, C සහ C ++ කේත එකට සම්බන්ධ කිරීම සඳහා ප්‍රකාශන අඩංගු ශීර්ෂ ගොනුවක් භාවිතා කිරීම). mallocC ++ හි භාවිතා කිරීම සහ මිතුරන් විශේෂ අවධානයක් ලැබිය යුතු බවට හොඳ අනතුරු ඇඟවීමේ ලකුණකි (හෝ C හි නැවත ලිවීම).
ටෝබි ස්පයිට්

1
"අවලංගු දර්ශකයක් යනු සාමාන්‍ය දර්ශකයකි" -> "අවලංගු දර්ශකය යනු සාමාන්‍ය වස්තු දර්ශකයකි". ශ්‍රිත දර්ශක ප්‍රමාණයන් ඉක්මවා යා හැකි void *බැවින් void *ශ්‍රිත දර්ශකය හොඳින් ගබඩා කිරීමට එය ප්‍රමාණවත් නොවේ.
chux - මොනිකා නැවත ස්ථාපනය කරන්න

එම රේඛාව පිළිබඳ මගේ අභිප්‍රාය එක හා සමාන වුවත් කෙසේ හෝ යෝජනාවට ස්තූතියි @chux.
උත්සාහ

31

ආපසු ලබා දුන් වර්ගය අවලංගු වේ *, එය අවලංගු කිරීම සඳහා අපේක්ෂිත දත්ත දර්ශකයට දැමිය හැකිය.


1
void* අපේක්ෂිත වර්ගයට දැමිය හැකිය, නමුත් එය ස්වයංක්‍රීයව පරිවර්තනය වන බැවින් එසේ කිරීමට අවශ්‍ය නොවේ. එබැවින් වාත්තු කිරීම අවශ්‍ය නොවන අතර ඇත්ත වශයෙන්ම ඉහළ ලකුණු ලබා ගත් පිළිතුරු වල සඳහන් හේතු සඳහා නුසුදුසු ය.
ටෝබි ස්පයිට්

නමුත් ඔබට එය "මැස්ස මත" අවලංගු කිරීමට අවශ්‍ය නම් පමණක්, ඔබ ඒ වෙනුවට විචල්‍යයක් නිර්මාණය කරන්නේ නම් (C හි) වාත්තු නොකර එය ආරක්ෂිතව සහ ස්වයංක්‍රීයව විචල්‍යයේ type ලදායී වර්ගයට පරිවර්තනය වේ.
ෆෙරරෙසි

30

එය ක්‍රමලේඛන භාෂාව සහ සම්පාදකයා මත රඳා පවතී. ඔබ mallocC හි භාවිතා කරන්නේ නම් , එය වාත්තු කිරීම ටයිප් කිරීමට අවශ්‍ය නොවේ, මන්ද එය ස්වයංක්‍රීයව වාත්තු ටයිප් කරයි. කෙසේ වෙතත්, ඔබ C ++ භාවිතා කරන්නේ නම්, ඔබ වාත්තු යතුරු ලියනය කළ යුත්තේ mallocඑය නැවත void*වර්ගයක් ලබා දෙන බැවිනි.


1
Malloc ශ්‍රිතය C හි ද ශුන්‍ය දර්ශකයක් ලබා දෙයි, නමුත් භාෂාවේ නීති C ++ ට වඩා වෙනස් වේ.
අගෝස්තු කාල්ස්ට්‍රෝම්

28

සී භාෂාවෙන්, ඕනෑම දර්ශකයකට අවලංගු දර්ශකයක් පැවරිය හැකි අතර, ඒ නිසා ඔබ වර්ග වාත්තු භාවිතා නොකළ යුතුය. ඔබට "ටයිප් ආරක්ෂිත" වෙන් කිරීමක් අවශ්‍ය නම්, මගේ සී ව්‍යාපෘතිවල මම නිතරම භාවිතා කරන පහත සඳහන් සාර්ව ක්‍රියාකාරකම් නිර්දේශ කළ හැකිය:

#include <stdlib.h>
#define NEW_ARRAY(ptr, n) (ptr) = malloc((n) * sizeof *(ptr))
#define NEW(ptr) NEW_ARRAY((ptr), 1)

මේවා ක්‍රියාත්මක වීමෙන් ඔබට සරලව කිව හැකිය

NEW_ARRAY(sieve, length);

ගතික නොවන අරා සඳහා, තෙවනුව තිබිය යුතු ශ්‍රිත සාර්ව වේ

#define LEN(arr) (sizeof (arr) / sizeof (arr)[0])

එමඟින් අරාව ලූප ආරක්ෂිත සහ වඩාත් පහසු කරයි:

int i, a[100];

for (i = 0; i < LEN(a); i++) {
   ...
}

"ඕනෑම වස්තු දර්ශකයකට අවලංගු දර්ශකයක් පැවරිය හැකිය " ක්‍රියාකාරී දර්ශකයන් තවත් කාරණයක් වන අතර එය malloc()එකක් නොවේ .
chux - මොනිකා නැවත ස්ථාපනය කරන්න

void*ශ්‍රිත දර්ශකයකට / සිට පැවරීම මඟින් තොරතුරු අහිමි විය හැකි බැවින් “ඕනෑම දර්ශකයකට අවලංගු දර්ශකයක් පැවරිය හැකිය” යනු එවැනි අවස්ථාවන්හි ගැටළුවකි. එය පවරා void*සිට, malloc() ඕනෑම වස්තුවක් පහිටුම් දක්වනය නමුත් ප්රශ්නයක් නැහැ.
chux - මොනිකා නැවත ස්ථාපනය කරන්න

මෙම doඉවත් මාතෘකාව ප්රශ්නය පුදුම වන බව තවමත් පුඩුවක් සම්බන්ධ මැක්රෝස් සම්බන්ධ පුඩුවක් අදහස්. එම අදහස ඉවත් කිරීම. මෙයද පසුව පහලට ගෙන යනු ඇත.
chux - මොනිකා

17

GCC සහ Clang වලට පුරුදු වූ අය නරක් වී ඇත. එතන එතරම් හොඳ නැහැ.

මා භාවිතා කිරීමට අවශ්‍ය වී ඇති වයස්ගත සම්පාදකයින් විසින් වසර ගණනාවක් තිස්සේ මම භීතියට පත්ව සිටිමි. බොහෝ විට සමාගම් සහ කළමනාකරුවන් සම්පාදකයින් වෙනස් කිරීම සඳහා අතිශය ගතානුගතික ප්‍රවේශයක් අනුගමනය කරන අතර ඒවා පරීක්‍ෂා නොකරනු ඇත (වඩා හොඳ තත්ත්වයක් අනුකූලතා හා කේතය ප්රශස්තිකරණය සමග) නව සම්පාදක විසින් ඔවුන්ගේ පද්ධතිය වැඩ කටයුතු කරනු ඇත නම්. වැඩ කරන සංවර්ධකයින් සඳහා ප්‍රායෝගික යථාර්ථය නම්, ඔබ කේත කරන විට ඔබේ පදනම් ආවරණය කළ යුතු අතර, අවාසනාවකට මෙන්, ඔබේ කේතයට කුමන සම්පාදකය යෙදිය හැකිද යන්න පාලනය කිරීමට ඔබට නොහැකි නම්, mallocs වාත්තු කිරීම හොඳ පුරුද්දකි.

බොහෝ සංවිධාන තමන්ගේම කේතීකරණ ප්‍රමිතියක් අනුගමනය කරන ලෙස මම යෝජනා කරමි අනුගමනය කරන ලෙසත් එය අර්ථ දක්වන්නේ නම් මිනිසුන් අනුගමනය කරන ක්‍රමය එය විය යුතු බවත් . පැහැදිලි මග පෙන්වීමක් නොමැති විට, ප්‍රමිතියකට වහල් ලෙස අනුගත වීම වෙනුවට සෑම තැනකම සම්පාදනය කිරීමට මම නැඹුරු වෙමි.

වර්තමාන ප්‍රමිතීන් යටතේ එය අවශ්‍ය නොවේ යන තර්කය තරමක් වලංගු වේ. නමුත් එම තර්කය සැබෑ ලෝකයේ ප්‍රායෝගිකත්වය මඟ හැරේ. අප කේත කරන්නේ දවසේ ප්‍රමිතිය අනුව පමණක් නොව, “ප්‍රාදේශීය කළමනාකරණයේ යථාර්ථය ක්ෂේත්‍රය” ලෙස හැඳින්වීමට මා කැමති දේවල ප්‍රායෝගිකත්වය අනුව ය. එය වෙන කවරදාටත් වඩා නැමී විකෘති වී ඇත. :-)

වයි.එම්.එම්.වී.

මම මැලොක් වාත්තු කිරීම ආරක්ෂක මෙහෙයුමක් ලෙස සිතීමට නැඹුරු වෙමි. ලස්සන නැත, පරිපූර්ණ නොවේ, නමුත් සාමාන්‍යයෙන් ආරක්ෂිතයි. (අවංකවම කිව්වොත්, ඔබ stdlib.h ඇතුළත් කර නැත්නම් ඔබ එක හොදයි මාර්ගය malloc වාත්තු වඩා ප්රශ්න!).


15

නරක පරිවර්තනයක් ගෙන ඒමට කිසිදු අක්ෂර වින්‍යාසයක් භාවිතා නොකලද, පහත දැක්වෙන ස්නිපටය වැනි කේතයන් රෝග නිර්ණයකින් තොරව සම්පාදනය කිරීමට ඉඩ සලසන ආකාරයේ පද්ධතියේ කැත කුහරය ප්‍රතික්ෂේප කිරීම පෙන්වීමට මම වාත්තු කරමි.

double d;
void *p = &d;
int *q = p;

එය නොපවතින බව මම ප්‍රාර්ථනා කරමි (එය C ++ හි නොමැත) එබැවින් මම දමමි. එය මගේ රසය සහ වැඩසටහන්කරණ දේශපාලනය නියෝජනය කරයි. මම දර්ශකයක් දැමීම පමණක් නොව, effectively ලදායි ලෙස, ඡන්ද පත්‍රිකාවක් දැමීම සහ මෝඩකම පිළිබඳ භූතයන් දුරු කරමි . මට ඇත්තටම මෝඩකම දුරු කරන්න බැරි නම් නම්, අවම වශයෙන් විරෝධතා දැක්වීමේ ඉරියව්වකින් එසේ කිරීමට කැමැත්ත ප්‍රකාශ කිරීමට මට ඉඩ දෙන්න.

ඇත්ත වශයෙන්ම, හොඳ පුරුද්දක් වන්නේ mallocනැවත පැමිණෙන කාර්යයන් සමඟ (සහ මිතුරන්) ඔතා ගැනීම unsigned char *සහ මූලික වශයෙන් void *ඔබේ කේතය තුළ කිසි විටෙකත් භාවිතා නොකිරීමයි. ඔබට ඕනෑම වස්තුවකට සාමාන්‍ය දර්ශකයක් අවශ්‍ය නම්, char *හෝ භාවිතා කරන්න unsigned char *, සහ දෙපැත්තටම වාත්තු කරන්න. යෙදිය හැකි එක් ලිහිල් කිරීමක් නම්, සමහර විට, වාත්තු වැනි memsetහා memcpyරහිත කාර්යයන් භාවිතා කිරීමයි .

වාත්තු යන මාතෘකාව හා C ++ ගැළපුම, එය C සහ C ++ (ඔබ කුමන අවස්ථාවකදී ලෙස ද සම්පාදනය වන ලෙස ඔබ ඔබේ කේතය ලියන්න නම් කිරීමට නැවත අගය ප්රකාශ mallocහැර වෙනත් දෙයක් කිරීමට එය පවරා විට void *), ඔබ ඉතා ප්රයෝජනවත් කරන්න පුළුවන් ඔබ වෙනුවෙන්ම: වාත්තු කිරීම සඳහා ඔබට මැක්‍රෝස් භාවිතා කළ හැකි අතර එය C ++ ලෙස සම්පාදනය කිරීමේදී C ++ විලාසිතාවන්ට පරිවර්තනය වේ, නමුත් C ලෙස සම්පාදනය කිරීමේදී C කාස්ට් දක්වා අඩු කරන්න:

/* In a header somewhere */
#ifdef __cplusplus
#define strip_qual(TYPE, EXPR) (const_cast<TYPE>(EXPR))
#define convert(TYPE, EXPR) (static_cast<TYPE>(EXPR))
#define coerce(TYPE, EXPR) (reinterpret_cast<TYPE>(EXPR))
#else
#define strip_qual(TYPE, EXPR) ((TYPE) (EXPR))
#define convert(TYPE, EXPR) ((TYPE) (EXPR))
#define coerce(TYPE, EXPR) ((TYPE) (EXPR))
#endif

ඔබ මෙම මැක්‍රෝස් පිළිපදින්නේ නම්, grepමෙම හඳුනාගැනීම් සඳහා ඔබේ කේත පදනම පිළිබඳ සරල සෙවුමක් මඟින් ඔබගේ සියලු කාස්ට් කොතැනදැයි පෙන්වනු ඇත, එවිට ඔබට ඒවා කිසිවක් වැරදියිද යන්න සමාලෝචනය කළ හැකිය.

ඉන්පසු, ඉදිරියට යමින්, ඔබ නිතිපතා කේ ++ සමඟ කේතය සම්පාදනය කරන්නේ නම්, එය සුදුසු වාත්තු කිරීමක් භාවිතා කරනු ඇත. උදාහරණයක් ලෙස, ඔබ strip_qualඉවත් කිරීමට භාවිතා කරන්නේ නම් constහෝvolatile , නමුත් ක්‍රමලේඛය දැන් පරිවර්තනයක් සිදු වන ආකාරයට වෙනස් වුවහොත්, ඔබට රෝග විනිශ්චයක් ලැබෙනු ඇති අතර, අපේක්ෂිත පරිවර්තනය ලබා ගැනීම සඳහා ඔබට සංයෝග එකතුවක් භාවිතා කිරීමට සිදුවේ.

මෙම මැක්‍රෝස් පිළිපැදීමට ඔබට උපකාර කිරීම සඳහා, GNU C ++ (C නොවේ!) සම්පාදකයාට සුන්දර අංගයක් ඇත: C විලාසිතාවේ සෑම සිදුවීමක් සඳහාම නිපදවන විකල්ප රෝග විනිශ්චය.

     -වෝල්ඩ්-ස්ටයිල්-කාස්ට් (සී ++ සහ පරමාර්ථ-සී ++ පමණි)
         අවලංගු නොවන වර්ගයකට පැරණි ශෛලියක් (සී-ස්ටයිල්) භාවිතා කරන්නේ නම් අනතුරු අඟවන්න
         C ++ වැඩසටහනක් තුළ. නව විලාසිතාවේ කාස්ට් (ගතික_ විකාශනය,
         static_cast, නැවත අර්ථකථනය_ විකාශනය සහ const_cast) අඩු අවදානමක් ඇත
         අනපේක්ෂිත බලපෑම් වලට සහ සෙවීමට වඩා පහසුය.

ඔබේ සී කේතය සී ++ ලෙස සම්පාදනය කරන්නේ නම්, කේතයට රිංගා ගත හැකි වාත්තු වාක්‍ය ඛණ්ඩයේ -Wold-style-castසියලු සිදුවීම් සොයා ගැනීමට ඔබට මෙම විකල්පය භාවිතා කළ හැකි (type)අතර, ඉහත සඳහන් මැක්‍රෝස් අතරින් සුදුසු තේරීමක් වෙනුවට මෙම රෝග නිර්ණයන් අනුගමනය කරන්න. සංයෝජනය, අවශ්ය නම්).

පරිවර්තන සඳහා මෙම ප්‍රතිකාරය “පිරිසිදු සී” හි වැඩ කිරීම සඳහා ඇති විශාලතම තනි තාක්‍ෂණික සාධාරණීකරණයයි: ඒකාබද්ධ සී සහ සී ++ උපභාෂාව, එමඟින් ප්‍රතිලාභ වටිනාකම වාත්තු කිරීම තාක්‍ෂණිකව යුක්ති සහගත කරයි malloc.


අනෙක් පෙන්වා දුන් පරිදි, මම සාමාන්‍යයෙන් නිර්දේශ කරන්නේ සී සහ සී ++ කේත මිශ්‍ර නොකිරීමටයි. කෙසේ වෙතත්, ඔබට එය කිරීමට හොඳ හේතු තිබේ නම්, එවිට මැක්‍රෝස් ප්‍රයෝජනවත් විය හැකිය.
Phil1970

@ Phil1970 මේ සියල්ල එක් සංයුක්ත උපභාෂාවකින් ලියා ඇති අතර එය C සහ C ++ සම්පාදකයින්ට අතේ ගෙන යා හැකි අතර C ++ හි සමහර හැකියාවන්ගෙන් ප්‍රයෝජන ගනී. ඒ සියල්ල C ++ ලෙස සම්පාදනය කළ යුතුය, නැතහොත් සියල්ල C ලෙස සම්පාදනය කළ යුතුය
Kaz

මම කලින් අදහස් දැක්වීමට උත්සාහ කළ දෙය නම් සී සහ සී ++ මිශ්‍ර කිරීමක් නොමැති බවයි. අභිප්‍රාය වන්නේ කේතය සියල්ලම C ලෙස සම්පාදනය කිරීම හෝ සියල්ල C ++ ලෙස සම්පාදනය කිරීමයි.
Kaz

15

හැකි සෑම විටම C හි ක්‍රමලේඛනය කිරීමේදී කළ හැකි හොඳම දේ:

  1. සියලු අනතුරු ඇඟවීම් සක්‍රිය කර ඔබේ වැඩසටහන සී සම්පාදකයෙකු හරහා සම්පාදනය කර -Wallසියලු දෝෂ සහ අනතුරු ඇඟවීම් නිවැරදි කරන්න
  2. ලෙස ප්‍රකාශිත විචල්‍යයන් නොමැති බවට වග බලා ගන්න auto
  3. එවිට සමග C ++ compiler භාවිතා එය සකස් -Wallහා -std=c++11. සියලු දෝෂ සහ අනතුරු ඇඟවීම් නිවැරදි කරන්න.
  4. දැන් නැවත සී සම්පාදකය භාවිතා කර සම්පාදනය කරන්න. ඔබගේ වැඩසටහන දැන් කිසිදු අනතුරු ඇඟවීමකින් තොරව සම්පාදනය කළ යුතු අතර අඩු දෝෂ අඩංගු විය යුතුය.

මෙම ක්‍රියාපටිපාටිය මඟින් ඔබට C ++ දැඩි ආකාරයේ පරීක්ෂාවෙන් ප්‍රයෝජන ගැනීමට ඉඩ සලසයි, එමඟින් දෝෂ ගණන අඩු කරයි. විශේෂයෙන්, මෙම ක්‍රියා පටිපාටිය ඔබට ඇතුළත් කිරීමට බල කරයි stdlib.hහෝ ඔබට ලැබෙනු ඇත

malloc මෙම විෂය පථය තුළ ප්‍රකාශයට පත් කර නොමැත

තවද එහි ප්‍රති result ලය ඉදිරිපත් කිරීමට ඔබට බල කරයි mallocහෝ ඔබට ලැබෙනු ඇත

සිට අවලංගු පරිවර්තනය void*කිරීමටT*

හෝ ඔබේ ඉලක්ක වර්ගය කුමක් ද?

මට සොයාගත හැකි C ++ වෙනුවට C හි ලිවීමෙන් ඇති එකම ප්‍රතිලාභයයි

  1. C හි මනාව නිශ්චිතව දක්වා ඇති ABI ඇත
  2. C ++ මඟින් තවත් කේත ජනනය කළ හැකිය [ව්‍යතිරේක, RTTI, සැකිලි, ධාවන කාල බහුමාපකය]

ස්ථිතික බහුමාමක ලක්ෂණය සමඟ C ට පොදු උප කුලකය භාවිතා කරන විට පරමාදර්ශී අවස්ථාවෙහිදී දෙවන අවාසි අතුරුදහන් විය යුතු බව සලකන්න .

C ++ දැඩි නීති රීති අපහසු බව සොයා ගන්නා අයට, අපට අනුමාන වර්ගය සහිත C ++ 11 අංගය භාවිතා කළ හැකිය

auto memblock=static_cast<T*>(malloc(n*sizeof(T))); //Mult may overflow...

20
සී කේතය සඳහා සී සම්පාදකයක් භාවිතා කරන්න. C ++ කේතය සඳහා C ++ සම්පාදකයක් භාවිතා කරන්න. නැත, නැත. ඔබේ C කේතය C ++ හි නැවත ලිවීම මුළුමනින්ම වෙනත් දෙයක් වන අතර කාලය හා අවදානම් වටිනවා විය හැකිය.
ටෝබි ස්පයිට්

2
@TobySpeight උපදෙස් වලට එක් කිරීමට මම කැමතියි: ඔබට C ++ ව්‍යාපෘතියක C කේතය භාවිතා කිරීමට අවශ්‍ය නම්, ඔබට සාමාන්‍යයෙන් C කේතය C (උදා gcc -c c_code.c) ලෙසත්, C ++ කේතය C ++ (උදා g++ -c cpp_code.cpp) ලෙසත්, ඉන්පසු ඒවා එකට සම්බන්ධ කළ හැකිය. (උදා: gcc c_code.o cpp_code.oව්‍යාපෘති පරායත්තතාවයන් මත පදනම්ව හෝ අනෙක් අතට). දැන් ඕනෑම භාෂාවක හොඳ ලක්ෂණ අහිමි කිරීමට කිසිදු හේතුවක් තිබිය යුතු නැත ...
ඔටිසම්

1
@ user877329 එය කේතයේ නිරවද්‍යතාවය අඩු කරන කේතයට වෙහෙස මහන්සි වී එකතු කිරීම වඩා සංවේදී විකල්පයකි, එය "C ++ අනුකූල" වීම සඳහා පමණි.
ඔටිසම්

1
මෙම සන්දර්භය තුළ ඇති ප්‍රධාන වාසිය නම් සී ඔබට ලිවීමට ඉඩ දීමයි, වෙනත් වර්ගයක නමකට වෙනස් p = malloc(sizeof(*p));වුවහොත් එය මුලින් වෙනස් කිරීම අවශ්‍ය නොවේ p. වාත්තු කිරීමේ යෝජිත "වාසිය" නම් pවැරදි වර්ගයක් නම් ඔබට සම්පාදක දෝෂයක් ලැබෙනු ඇත , නමුත් එය නිකම්ම ක්‍රියාත්මක වන්නේ නම් ඊටත් වඩා හොඳය.
පීටර් කෝර්ඩ්ස්

1
නිසි C ++ සම්පාදකයින් නොමැති වේදිකා ඉලක්ක කිරීමේදී C හි ලිවීම අවශ්‍ය විය හැකි බව සඳහන් කිරීමට කැමැත්තෙමි. ව්‍යතිරේක සහ සැකිලි යනු සාමාන්‍යයෙන් කුඩා හා / හෝ වඩා කාර්යක්ෂම කේත ජනනය කිරීමට c ++ ට උදව් වන අතර C ++ හි ධාවන
බහුඅවයවිකතාව

15

නැත, ඔබ එහි ප්‍රති result ලය නොදක්වයි malloc().

පොදුවේ ගත් කල, ඔබ වෙතට හෝ එන්නේ නැතvoid * .

එසේ නොකිරීමට ලබා දී ඇති සාමාන්‍ය හේතුවක් නම් අසමත් වීම #include <stdlib.h>නොදැනීමයි. C99 ව්‍යංග ශ්‍රිත ප්‍රකාශයන් කළ බැවින් මෙය දිගු කලක් තිස්සේ ගැටළුවක් නොවේ නීති විරෝධී බැවින් , එබැවින් ඔබේ සම්පාදකයා අවම වශයෙන් C99 ට අනුකූල වන්නේ නම්, ඔබට රෝග විනිශ්චය පණිවිඩයක් ලැබෙනු ඇත.

නමුත් අනවශ්‍ය පොයින්ටර් කැස්ට් හඳුන්වා නොදීමට වඩා ප්‍රබල හේතුවක් තිබේ:

C හි, දර්ශක වාත්තු කිරීම සෑම විටම පාහේ දෝෂයකි . මෙයට හේතුව පහත දැක්වෙන රීතියයි ( C15 සඳහා නවතම කෙටුම්පත N1570 හි §6.5 p7 ):

වස්තුවකට එහි ගබඩා කළ අගය ප්‍රවේශ විය හැක්කේ පහත දැක්වෙන වර්ග වලින් එකක් සහිත ලාවුල් ප්‍රකාශනයකින් පමණි:
- වස්තුවේ
type ලදායී වර්ගයට අනුකූල වන වර්ගයක්,
- වස්තුවේ type ලදායී වර්ගයට අනුකූල වන සුදුසුකම් ලත් අනුවාදයක්, - වස්තුවේ type ලදායී වර්ගයට අනුරූපව අත්සන් කරන ලද හෝ අත්සන් නොකළ වර්ගයකි,
- type ලදායී වස්තුවක සුදුසුකම් ලත් අනුවාදයකට අනුරූපව අත්සන් කරන ලද හෝ අත්සන් නොකළ වර්ගයකි,
- එකක් ඇතුළත් වන සමස්ත හෝ යුනියන් වර්ගයකි එහි සාමාජිකයන් අතර ඉහත සඳහන් වර්ගවල (පුනරාවර්තන ලෙස, උප සමූහයක හෝ අඩංගු සංගමයක සාමාජිකයෙකු ඇතුළුව), හෝ
- චරිත වර්ගයකි.

මෙය දැඩි අන්වර්ථකරණ රීතිය ලෙසද හැඳින්වේ . එබැවින් පහත කේතය නිර්වචනය නොකළ හැසිරීමකි :

long x = 5;
double *p = (double *)&x;
double y = *p;

සමහර විට පුදුමයට කරුණක් නම්, පහත දැක්වෙන දේ ද වේ:

struct foo { int x; };
struct bar { int x; int y; };
struct bar b = { 1, 2};
struct foo *p = (struct foo *)&b;
int z = p->x;

සමහර විට, ඔබ කරන්නේ කාස්ට් සූචක කිරීමට අවශ්ය, නමුත් ලබා දැඩි අනුවර්ත නාමකරණයට පාලනය , ඔබ එය සමග ඉතා ප්රවේසම් විය යුතුයි. එබැවින්, ඔබේ කේතයේ දර්ශකයේ ඕනෑම සිදුවීමක් සිදුවුවහොත් එහි වලංගුභාවය පිළිබඳව ඔබ දෙවරක් පරීක්ෂා කළ යුතුය . එමනිසා, ඔබ කිසි විටෙකත් අනවශ්‍ය පොයින්ටරයක් ​​ලියන්නේ නැත.

tl; dr

ඉතා කෙටියෙන් කියනවා නම්: සී, නිසා ඕනෑම වූ සිදුවීම පිළිබඳව අවධානය යොමුකළ කාස්ට් විශේෂ අවධානය අවශ්ය කේතය සඳහා රතු ධජය බිහි කළ යුතුයි, ඔබ ලිවීමට නොකළ යුතු අනවශ්ය පහිටුම් දක්වනය නීති ක්රීයාත්මක වන.


පැති සටහන්:

  • ඔබට ඇත්ත වශයෙන්ම වාත්තු කිරීම අවශ්‍ය වන අවස්ථා තිබේ void *, උදා: ඔබට දර්ශකයක් මුද්‍රණය කිරීමට අවශ්‍ය නම්:

    int x = 5;
    printf("%p\n", (void *)&x);

    මෙහි වාත්තු කිරීම අත්‍යවශ්‍ය වේ, මන්ද printf()එය විචල්‍ය ශ්‍රිතයක් වන බැවින් ව්‍යංග පරිවර්තනයන් ක්‍රියා නොකරයි.

  • C ++ හි තත්වය වෙනස් වේ. ව්‍යුත්පන්න පංතිවල වස්තු සමඟ කටයුතු කිරීමේදී දර්ශක වර්ග වාත්තු කිරීම තරමක් පොදු වේ (සහ නිවැරදි). එමනිසා, C ++ හි, සහ ඉන් හැරීම void *යන්නෙන් ගම්‍ය නොවන බව හැඟේ. C ++ හි විවිධ රසයන් සමූහයක් ඇත.


1
ඔබගේ උදාහරණ වල ඔබ අවලංගු කිරීමෙන් වළකින්න *. වාත්තු කිරීම ද්විත්ව * සිට int * දක්වා සහ අනෙක් අතට අතර වෙනසක් ඇත. malloc return pointel එක විශාලතම සම්මත වර්ගයට පෙලගැසී ඇත, එබැවින් යමෙකු මෙම පෙළගැස්වූ දර්ශකය වෙනත් වර්ගයකට සාදනු ලැබුවද අන්වර්ථ නීති රීති නොමැත.
P__J__

අනුවර්ත නාමකරණයට ඇත කිසිවක් යැම සහ ඔබේ අදහස් ඉතිරි කරන්න සියලු දී - ඔබ පැහැදිලිවම කාරණය වුණේ නැත.

EtPeterJ: කාරණය වන්නේ අනවශ්‍ය පොයින්ටර් වාත්තු කිරීමෙන් වැළකී සිටීමයි , එබැවින් එය ඔබ විශේෂ අවධානයක් යොමු කළ යුතු කේත කැබැල්ලක් මෙන් නොපෙනේ .

දැඩි අන්වර්ථකරණ ගැටලුවට අවලංගු දර්ශකයන් සමඟ කිසිදු සම්බන්ධයක් නැත. දැඩි අන්වර්ථ උල්ලං by නය කිරීම් හේතුවෙන් ඇති වන දෝෂ ලබා ගැනීම සඳහා, ඔබ පෙන්වා ඇති දත්ත විග්‍රහ කළ යුතුය. ඔබට අවලංගු දර්ශකයක් අවලංගු කළ නොහැකි බැවින්, එවැනි දෝෂ අර්ථ දැක්වීමකට අනුව අවලංගු දර්ශකයට නොව වෙනත් දෙයකට සම්බන්ධ වේ.
ලුන්ඩින්

ඒ වෙනුවට, ඔබට සියලු පොයින්ටර් කැස්ට් තහනම් කිරීමට රීතියක් කළ යුතුය. නමුත් ඔබ අනුක්‍රමිකකරණ ක්‍රම සහ දෘඩාංග ආශ්‍රිත වැඩසටහන් වැනි දේ ලියන්නේ කෙසේද? සීගේ ශක්තිය වන දේවල්. ඔබ කරන්නේ කුමක්දැයි ඔබ දන්නේ නම් එවැනි විග්‍රහයන් හොඳයි.
ලුන්ඩින්

15

මම කැමතියි රංගනය කරන්න, නමුත් අතින් නොවේ. මගේ ප්රියතම භාවිතා g_newසහ g_new0glib සිට මැක්රෝස්. ග්ලිබ් භාවිතා නොකරන්නේ නම්, මම සමාන මැක්‍රෝස් එකතු කරමි. එම මැක්‍රෝස් වර්ගවල ආරක්ෂාව අඩාල නොකර කේත අනුපිටපත් අඩු කරයි. ඔබ වර්ගය වැරදියි නම්, ඔබට අවලංගු නොවන දර්ශකයන් අතර ව්‍යංග වාත්තු ලැබෙනු ඇත, එය අනතුරු ඇඟවීමක් ඇති කරයි (C ++ හි දෝෂයකි). ඔබ කුහකකමක් බව ශීර්ෂ ඇතුළත් කිරීමට අමතක වුවහොත් g_newහා g_new0, ඔබ දෝෂයක් ලබා ඇත. g_newහා g_new0මෙන් නොව, එම තර්ක මත දෙකම mallocවඩා අඩු තර්ක ගනී calloc. 0ශුන්‍ය ආරම්භක මතකය ලබා ගැනීම සඳහා එක් කරන්න . කේතය වෙනස් කිරීමකින් තොරව C ++ සම්පාදකයෙකු සමඟ සම්පාදනය කළ හැකිය.


12

වාත්තු කිරීම සී ++ නොව සී සඳහා පමණි. ඔබ සී ++ සම්පාදකයක් භාවිතා කරන්නේ නම් එය සී සම්පාදකයා ලෙස වෙනස් කිරීම හොඳය.


9

අවලංගු දර්ශකය පිටුපස ඇති සංකල්පය නම්, එය ඕනෑම දත්ත වර්ගයකට දැමිය හැකි වීමයි. ස්වයංක්‍රීය යතුරුලියනය පිළිබඳව ඔබ දැනුවත් විය යුතුය. එබැවින් ඔබ එය කළ යුතු වුවද දර්ශකය දැමීම අනිවාර්ය නොවේ. එය කේතය පිරිසිදුව තබා ගැනීමට සහ නිදොස්කරණය කිරීමට උපකාරී වේ


11
" එය අනිවාර්ය නොවේ - ඔබ එය කළ යුතු වුවත් " - එහි පරස්පරතාවයක් ඇතැයි මම සිතමි!
ටෝබි ස්පයිට්

5
මම හිතන්නේ ඔබ මෙම ලිපිය යමෙකුට කියවිය යුතු අතර, ඔබ කීමට උත්සාහ කරන දේ ඔවුන් තේරුම් ගන්නේ දැයි බලන්න. ඔබට එය පැවසීමට අවශ්‍ය දේ පැහැදිලි කරමින් එය නැවත ලියන්න. මට ඇත්තටම තේරුම් ගන්න බැහැ ඔයාගේ පිළිතුර මොකක්ද කියලා.
බිල් වුඩ්ජර්

9

අවලංගු දර්ශකයක් යනු සාමාන්‍ය දර්ශකයක් වන අතර, සී අවලංගු දර්ශක වර්ගයක සිට වෙනත් වර්ග වලට ව්‍යංග පරිවර්තනයට සහය දක්වයි, එබැවින් එය පැහැදිලිව යතුරු ලියනය කිරීමේ අවශ්‍යතාවයක් නොමැත.

කෙසේ වෙතත්, එකම කේතය සී ++ වේදිකාවක් මත පරිපූර්ණ ලෙස අනුකූල වීමට අවශ්‍ය නම්, එය ව්‍යංග පරිවර්තනයට සහාය නොදක්වයි, ඔබ යතුරු ලියනය කිරීම කළ යුතුය, එබැවින් ඒ සියල්ල භාවිතාව මත රඳා පවතී.


9
  1. වෙනත් ප්‍රකාශ කළ පරිදි, එය C සඳහා අවශ්‍ය නොවේ, නමුත් C ++ සඳහා.

  2. වාත්තු කිරීම ඇතුළුව C වැඩසටහනක් හෝ ශ්‍රිතයක් C ++ ලෙස සම්පාදනය කිරීමට ඉඩ දෙනු ඇත.

  3. C හි එය අනවශ්‍යය, අවලංගු * ස්වයංක්‍රීයව සහ ආරක්ෂිතව වෙනත් ඕනෑම දර්ශක වර්ගයකට උසස් කරනු ලැබේ.

  4. නමුත් ඔබ එසේ දැමුවහොත්, ඔබට stdlib.h ඇතුළත් කිරීමට අමතක වුවහොත් එය දෝෂයක් සැඟවිය හැක . මෙය බිඳවැටීම් වලට හේතු විය හැක (හෝ, වඩාත් නරක නම්, පසුව කේතයේ සම්පූර්ණයෙන්ම වෙනස් කොටසක බිඳ වැටීමක් ඇති නොකරන්න).

    මන්ද stdlib.h හි malloc සඳහා වන මූලාකෘතිය සොයාගෙන ඇත. Malloc සඳහා මූලාකෘතියක් නොමැති විට, ප්‍රමිතියට C සම්පාදකයා විසින් malloc විසින් int එකක් ලබා දෙන බව උපකල්පනය කළ යුතුය. වාත්තු කිරීමක් නොමැති නම්, මෙම නිඛිලය දර්ශකයට පවරා ඇති විට අනතුරු ඇඟවීමක් කරනු ලැබේ; කෙසේ වෙතත්, වාත්තු සමඟ, මෙම අනතුරු ඇඟවීම ඉදිරිපත් නොකෙරේ, එය දෝෂයක් සඟවයි.


9

Malloc වාත්තු කිරීම C හි අනවශ්‍ය නමුත් C ++ හි අනිවාර්ය වේ.

C හි වාත්තු කිරීම අනවශ්‍ය නිසා:

  • void * සී සම්බන්ධයෙන් ස්වයංක්‍රීයව සහ ආරක්ෂිතව වෙනත් ඕනෑම දර්ශක වර්ගයකට උසස් කරනු ලැබේ.
  • ඔබට ඇතුළත් කිරීමට අමතක වූවා නම් එය දෝෂයක් සැඟවිය හැක <stdlib.h>. මෙය බිඳ වැටීම් වලට හේතු විය හැක.
  • දර්ශකයන් සහ නිඛිල ප්‍රමාණයන් වෙනස් නම්, ඔබ වාත්තු කිරීමෙන් අනතුරු ඇඟවීමක් සඟවන අතර ඔබගේ ආපසු එවූ ලිපිනයේ බිටු නැති විය හැකිය.
  • දර්ශකයේ වර්ගය එහි ප්‍රකාශනයේ දී වෙනස් කර ඇත්නම්, යමෙකුට සියලු රේඛා වෙනස් කිරීමට අවශ්‍ය විය හැකිය malloc.

අනෙක් අතට, වාත්තු කිරීම ඔබේ වැඩසටහනේ අතේ ගෙන යා හැකි හැකියාව වැඩි කරයි. එනම්, එය C වැඩසටහනක් හෝ ශ්‍රිතයක් C ++ ලෙස සම්පාදනය කිරීමට ඉඩ දෙයි.


2

මෙම ප්‍රශ්නය මතය පදනම් කරගත් අපයෝජනයට යටත් වේ.

සමහර විට මම එවැනි අදහස් දැක්කා:

Malloc හි ප්‍රති result ලය දමන්න එපා

හෝ

ඇයි ඔබ malloc හි ප්‍රති result ලය නොදක්වන්නේ

OP වාත්තු කිරීම භාවිතා කරන ප්‍රශ්න මත. අදහස් දැක්වීමේදී මෙම ප්‍රශ්නයට අධි-සබැඳියක් අඩංගු වේ.

බව ය ඕනෑම මෙන්ම නුසුදුසු සහ වැරදි විය හැකි ආකාරය. එය සැබවින්ම තමන්ගේම කේතීකරණ ශෛලියක් වන විට හරි සහ වැරදි නැත.


මෙය සිදුවන්නේ ඇයි?

එය හේතු දෙකක් මත පදනම් වේ:

  1. මෙම ප්‍රශ්නය ඇත්ත වශයෙන්ම මතය මත පදනම් වූවකි. තාක්ෂණික වශයෙන්, ප්‍රශ්නය මීට වසර ගණනාවකට පෙර මතය පදනම් කරගත් පරිදි වසා තිබිය යුතුය.

  2. බොහෝ පිළිතුරු (වඩාත්ම පැහැදිලිව පෙනෙන සහ පිළිගත් ඒවා ඇතුළුව පිළිතුර@unwind ) වේ එක්කෝ සම්පූර්ණයෙන්ම හෝ මුළුමනින්ම වාගේ මතය මත පදනම් (Fe ඔබ වාත්තු හෝ නැවත නැවත නම් ඔබගේ කේතය එකතු කරන බව අද්භූත "ගොඩගැසීම" නරක වනු ඇත) හා ප්රදර්ශන රංගනය මඟ හැරීමේ පැහැදිලි හා අවධානය යොමු වූ ප්‍රවණතාවක්. ඔවුන් එක් පැත්තක නළු නිළියන්ගේ අතිරික්තය ගැන තර්ක කරන නමුත් ඊටත් වඩා දරුණු ලෙස තර්ක කරන්නේ වැඩසටහන්කරණයේ දෝෂයක් / අසමත් වීමක් නිසා ඇති වූ දෝෂයක් විසඳීමට ය - #include <stdlib.h>යමෙකුට භාවිතා කිරීමට අවශ්‍ය නම් නොවේ malloc().


මගේ පෞද්ගලික මතය අඩුවෙන් සාකච්ඡා කර ඇති කරුණු කිහිපයක් පිළිබඳ සත්‍ය දෘෂ්ටියක් ගෙන ඒමට මට අවශ්‍යය. කරුණු කිහිපයක් විශේෂයෙන් සඳහන් කළ යුතුය:

  1. තමන්ගේ මතයට වැටීමට මෙතරම් අවදානමට ලක්විය හැකි ප්‍රශ්නයකට මධ්‍යස්ථ වාසි සහ අවාසි සහිත පිළිතුරක් අවශ්‍ය වේ. අවාසි හෝ වාසි පමණක් නොවේ.

    වාසි සහ අවාසි පිළිබඳ හොඳ දළ විශ්ලේෂණයක් මෙම පිළිතුරෙහි ලැයිස්තුගත කර ඇත:

    https://stackoverflow.com/a/33047365/12139179

    (මම පෞද්ගලිකව මෙය සලකන්නේ එම හේතුව නිසා මෙතෙක් ඇති හොඳම පිළිතුරයි.)


  1. නළු නිළියන් මඟ හැරීම හේතු කොට ගෙන බොහෝ විට හමු වන එක් හේතුවක් නම්, නළුවන් දෝෂයක් සැඟවිය හැකි වීමයි.

    යමෙකු ව්‍යාජ අර්ථ දැක්වීමක් භාවිතා කරන්නේ නම් malloc()එය නැවත පැමිණේint (C99 ප්රමිතියේ දී සිට ගම්ය කාර්යයන් සම්මත සිට ගොස් ඇත) සහ sizeof(int) != sizeof(int*)මේ ප්රශ්නය පෙන්වා ඇති පරිදි,

    මෙම කේතය 64-බිට් ගෘහ නිර්මාණ ශිල්පය මත segfault නමුත් 32-bit මත හොඳින් ක්‍රියා කරන්නේ ඇයි?

    වාත්තු කිරීම දෝෂයක් සඟවයි.

    මෙය සත්‍යයක් වුවද එය කතාවෙන් අඩක් පමණක් පෙන්වන බැවින් නළු නිළියන් මඟ හැරීම ඊටත් වඩා විශාල දෝෂයකට ඉදිරි විසඳුමක් වනු ඇත - stdlib.hභාවිතා කිරීමට ඇතුළත් නොවේmalloc() .

    මෙය කිසි විටෙකත් බැරෑරුම් කාරණයක් නොවනු ඇත, ඔබ නම්,

    1. C99 හෝ ඊට ඉහළින් සම්පාදකයෙකු භාවිතා කරන්න (එය නිර්දේශ කර ඇති අතර එය අනිවාර්ය විය යුතුය), සහ

    2. ඔබේ කේතය තුළ stdlib.hභාවිතා කිරීමට අවශ්‍ය වූ විට එය ඇතුළත් කිරීමට අමතක වී ඇති අතර malloc()එය විශාල දෝෂයකි.


  1. සමහර අය C ++ හි C ++ අනුකූලතාවය ගැන තර්ක කරති.

    මුලින්ම පොදුවේ කිව යුත්තේ: C ++ සම්පාදකයෙකු සමඟ C කේතය සම්පාදනය කිරීම හොඳ පුරුද්දක් නොවේ.

    සී සහ සී ++ ඇත්ත වශයෙන්ම විවිධ අර්ථකථන සහිත සම්පූර්ණයෙන්ම වෙනස් භාෂා දෙකකි.

    නමුත් ඔබට ඇත්ත වශයෙන්ම අවශ්‍ය නම් / අවශ්‍ය නම් C කේතය C ++ ට අනුකූල වන අතර අනෙක් අතට ඕනෑම වාත්තු කිරීමක් වෙනුවට සම්පාදක ස්විච භාවිතා කරන්න.

    නළු නිළියන් අතිරික්ත හෝ හානිකර යැයි ප්‍රකාශ කරන ප්‍රවණතාවක් ඇති හෙයින්, වාත්තු කිරීම ප්‍රයෝජනවත් හෝ අවශ්‍ය වීමට හොඳ හේතු සපයන මෙම ප්‍රශ්න කෙරෙහි අවධානය යොමු කිරීමට මට අවශ්‍යය:


සාරාංශය:

සත්‍යය නම්, සී ප්‍රමිතියට අනුව වාත්තු අතිරික්ත වීමයි (දැනටමත් ANSI-C (C89 / C90) සිට). දර්ශකය ස්වයංක්‍රීයව පෙලගැසී ඇති බැවින් ඔබට වාත්තු කිරීම අවශ්‍ය නොවේ:

"Aligned_alloc, calloc, malloc, සහ realloc ශ්‍රිතයන් සඳහා අනුප්‍රාප්තික ඇමතුම් මගින් වෙන් කරන ලද ගබඩාවේ අනුපිළිවෙල සහ පරස්පරතාව නිශ්චිතව දක්වා නැත. මූලික පෙළගැස්වීමේ අවශ්‍යතාවයක් වන අතර පසුව වෙන් කරන ලද අවකාශය තුළ එවැනි වස්තුවකට හෝ එවැනි වස්තු සමූහයකට ප්‍රවේශ වීමට භාවිතා කරයි (අවකාශය පැහැදිලිවම අවලංගු කරන තුරු).

මුලාශ්‍රය: සී 18, §7.22.3 / 1

අනෙක් සෑම දෙයක්ම නිශ්චිත භාවිත නඩුව හා තමාගේම මතය වේ.

කරුණාකර ඔබ ඔබම අධ්‍යාපනය ලබන ආකාරය ගැන සැලකිලිමත් වන්න.

මේ දක්වා ලබා දී ඇති සියලුම පිළිතුරු පළමුව ප්‍රවේශමෙන් කියවන ලෙස මම ඔබට නිර්දේශ කරමි malloc().

කරුණාකර සටහන් කර ගන්න:

එම ප්‍රශ්නයට නිවැරදි හා වැරදි පිළිතුරක් නොමැත. එය ශෛලිය පිළිබඳ කාරණයක් වන අතර ඔබ තෝරා ගන්නා මාර්ගය ඔබම තීරණය කරයි (ඔබට අධ්‍යාපනය හෝ රැකියාවෙන් බල නොකෙරේ නම්). කරුණාකර ඒ ගැන සැලකිලිමත් වන්න, ඔබව රැවටීමට ඉඩ නොදෙන්න .


අවසාන සටහන: මෙම ප්‍රශ්නය මතය මත පදනම් වූවක් ලෙස අවසන් කිරීමට මම ඡන්දය ප්‍රකාශ කළෙමි. ඔබට සමීප / නැවත විවෘත කිරීමේ වරප්‍රසාදය ලැබුනේ නම්, එසේ කිරීමට මම ඔබට ආරාධනා කරමි.


1
මම මෙම ප්‍රකාශයට පූර්ණ සහය දෙමි.
Ctx

මෙම පැරණි පිළිතුරෙහි සඳහන් කර ඇති ආකාරයටම මෙයද වේ : stackoverflow.com/a/22538350/584518 .
ලුන්ඩින්

Und ලුන්ඩින් ඔබ වැරදි සබැඳියක් අලවා තිබිය යුතුය, මෙම පිළිතුර මෙම අෆයික්ස් සමඟ සම්පුර්ණයෙන්ම සම්බන්ධ නොවේ
Ctx

Und ලුන්ඩින් මම සාමාන්‍යයෙන් ඔබේ අන්තර්ගතයට බෙහෙවින් කැමති වුවත්, මෙහි දී මම ඔබ සමඟ සම්පූර්ණයෙන්ම එකඟ නොවිය යුතුය. ඔබේ පිළිතුර සහ මගේ අතර විශාල වෙනසක් තිබේ. ඔබේ පිළිතුර පැහැදිලිවම යෝජනා කරන්නේ මතය මත පදනම් වූ ආකාරයකින් නළු නිළියන් මඟ හැරීමටයි. ඇත්ත වශයෙන්ම, ඔබගේ සහ නොවිසඳුණු පිළිතුරු ප්‍රධාන හේතුවක් විය, මම මෙම පිළිතුර මෙහි කළේ ඇයි. - ඔබ කතා කරන්නේ " ඔබ malloc හි ප්‍රති result ලය නොදක්වන හෙයිනි, එසේ කිරීමෙන් ඔබේ කේතයට අර්ථ විරහිත අවුල් ජාලයක් එකතු වේ. " සහ " මිනිසුන් malloc හි ප්‍රති result ල ලබා දීමට වඩාත් පොදු හේතුව වන්නේ C භාෂාව ක්‍රියා කරන ආකාරය පිළිබඳව ඔවුන් නොදැන සිටීමයි. . "ඒවා නිවැරදි නොවේ.
රොබට්ස්

කැළඹීම ” යනු තමන්ගේම මතයක ගොඩනැගීමකි. SO හි ඇති ඕනෑම ප්‍රශ්නයකට අදාළ ඕනෑම ආකාරයකින් එම පදය භාවිතා කිරීම පිළිබඳව මම සම්පූර්ණයෙන්ම එකඟ නොවෙමි. එසේ පැවසුවහොත්, මම ඔබේ පිළිතුරට දොන් හැච්ගේ ප්‍රකාශය වෙත යොමු කරමි.
රොබට්ස්

0

මට නම්, ගෙදර ගෙන යාම සහ නිගමනය නම් malloc, සී හි වාත්තු කිරීම මුළුමනින්ම අවශ්‍ය නොවන නමුත් ඔබ කෙසේ වෙතත්, ඔබ ඉල්ලූ ආශීර්වාද ලත් මතක අවකාශය තවමත් ඔබට ලබා දෙන mallocබැවින් එය බලපාන්නේ නැත malloc. ගෙදර ගෙන යාමේ තවත් හේතුවක් වන්නේ මිනිසුන් වාත්තු කිරීමට හේතුව හෝ එක් හේතුවක් වන අතර මෙය C හෝ C ++ වලින් එකම වැඩසටහනක් සම්පාදනය කිරීමට ඔවුන්ට හැකියාව ලබා දීමයි.

වෙනත් හේතු තිබිය හැකි නමුත් වෙනත් හේතු, ඉක්මනින් හෝ පසුව ඔබව බරපතල කරදරයකට ඇද දමනු ඇත.


0

ඔබට සී තුළ වාත්තු කිරීමට අවශ්‍ය නැත, නමුත් එම කේතය සී ++ ලෙස සම්පාදනය කර ඇත්නම් ඔබට වාත්තු කළ යුතුය.

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.