Macro for allocation in C

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP












3












$begingroup$


As we all know, the syntax of allocating memory is a bit clunky in C. The recommended way is:




int *p;
int n=10;
p = malloc(n*sizeof *p);



You can use sizeof (int) instead of sizeof *p but it is bad practice.



I made a solution to this with a macro:



#define ALLOC(p,n) do *p=malloc(n*sizeof **p); while(0)


This get called this way:




int *p;
int n=10;
ALLOC(&p, n);



The reason I want to pass the address of p rather than p, is to offer a bit of protection. When you call a function with foo(x), then foo can never change the value of x. If you're not passing the address, the argument will not change. (Sure there are ways around that too.)



Any comments?










share|improve this question











$endgroup$











  • $begingroup$
    Please see What to do when someone answers. I have rolled back Rev 3 → 2.
    $endgroup$
    – 200_success
    Jan 26 at 18:10






  • 3




    $begingroup$
    I think the basic problem here is that your opinion of the "clunkiness" of C memory allocation is not shared by many experienced C programmers. (To me, it seems elegantly simple.) So by hiding what you're actually doing in a macro, you just introduce possible confusion.
    $endgroup$
    – jamesqf
    Jan 27 at 5:18















3












$begingroup$


As we all know, the syntax of allocating memory is a bit clunky in C. The recommended way is:




int *p;
int n=10;
p = malloc(n*sizeof *p);



You can use sizeof (int) instead of sizeof *p but it is bad practice.



I made a solution to this with a macro:



#define ALLOC(p,n) do *p=malloc(n*sizeof **p); while(0)


This get called this way:




int *p;
int n=10;
ALLOC(&p, n);



The reason I want to pass the address of p rather than p, is to offer a bit of protection. When you call a function with foo(x), then foo can never change the value of x. If you're not passing the address, the argument will not change. (Sure there are ways around that too.)



Any comments?










share|improve this question











$endgroup$











  • $begingroup$
    Please see What to do when someone answers. I have rolled back Rev 3 → 2.
    $endgroup$
    – 200_success
    Jan 26 at 18:10






  • 3




    $begingroup$
    I think the basic problem here is that your opinion of the "clunkiness" of C memory allocation is not shared by many experienced C programmers. (To me, it seems elegantly simple.) So by hiding what you're actually doing in a macro, you just introduce possible confusion.
    $endgroup$
    – jamesqf
    Jan 27 at 5:18













3












3








3





$begingroup$


As we all know, the syntax of allocating memory is a bit clunky in C. The recommended way is:




int *p;
int n=10;
p = malloc(n*sizeof *p);



You can use sizeof (int) instead of sizeof *p but it is bad practice.



I made a solution to this with a macro:



#define ALLOC(p,n) do *p=malloc(n*sizeof **p); while(0)


This get called this way:




int *p;
int n=10;
ALLOC(&p, n);



The reason I want to pass the address of p rather than p, is to offer a bit of protection. When you call a function with foo(x), then foo can never change the value of x. If you're not passing the address, the argument will not change. (Sure there are ways around that too.)



Any comments?










share|improve this question











$endgroup$




As we all know, the syntax of allocating memory is a bit clunky in C. The recommended way is:




int *p;
int n=10;
p = malloc(n*sizeof *p);



You can use sizeof (int) instead of sizeof *p but it is bad practice.



I made a solution to this with a macro:



#define ALLOC(p,n) do *p=malloc(n*sizeof **p); while(0)


This get called this way:




int *p;
int n=10;
ALLOC(&p, n);



The reason I want to pass the address of p rather than p, is to offer a bit of protection. When you call a function with foo(x), then foo can never change the value of x. If you're not passing the address, the argument will not change. (Sure there are ways around that too.)



Any comments?







c memory-management macros






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Feb 4 at 12:46









Toby Speight

24.4k740114




24.4k740114










asked Jan 26 at 15:39









BromanBroman

24418




24418











  • $begingroup$
    Please see What to do when someone answers. I have rolled back Rev 3 → 2.
    $endgroup$
    – 200_success
    Jan 26 at 18:10






  • 3




    $begingroup$
    I think the basic problem here is that your opinion of the "clunkiness" of C memory allocation is not shared by many experienced C programmers. (To me, it seems elegantly simple.) So by hiding what you're actually doing in a macro, you just introduce possible confusion.
    $endgroup$
    – jamesqf
    Jan 27 at 5:18
















  • $begingroup$
    Please see What to do when someone answers. I have rolled back Rev 3 → 2.
    $endgroup$
    – 200_success
    Jan 26 at 18:10






  • 3




    $begingroup$
    I think the basic problem here is that your opinion of the "clunkiness" of C memory allocation is not shared by many experienced C programmers. (To me, it seems elegantly simple.) So by hiding what you're actually doing in a macro, you just introduce possible confusion.
    $endgroup$
    – jamesqf
    Jan 27 at 5:18















$begingroup$
Please see What to do when someone answers. I have rolled back Rev 3 → 2.
$endgroup$
– 200_success
Jan 26 at 18:10




$begingroup$
Please see What to do when someone answers. I have rolled back Rev 3 → 2.
$endgroup$
– 200_success
Jan 26 at 18:10




3




3




$begingroup$
I think the basic problem here is that your opinion of the "clunkiness" of C memory allocation is not shared by many experienced C programmers. (To me, it seems elegantly simple.) So by hiding what you're actually doing in a macro, you just introduce possible confusion.
$endgroup$
– jamesqf
Jan 27 at 5:18




$begingroup$
I think the basic problem here is that your opinion of the "clunkiness" of C memory allocation is not shared by many experienced C programmers. (To me, it seems elegantly simple.) So by hiding what you're actually doing in a macro, you just introduce possible confusion.
$endgroup$
– jamesqf
Jan 27 at 5:18










4 Answers
4






active

oldest

votes


















14












$begingroup$


p = malloc(n*sizeof *p);




This is dangerous if n gets large, because the multiplication could overflow. After the overflow, too little memory has been allocated but code will continue without detecting the error.



This is especially dangerous if n comes from untrusted source, such as some file format or remote user. Then it gives attacker easy way to overwrite parts of memory with exploit code.



The easy safe solution is to use calloc() which will detect the overflow (at least on most common libc implementations). If you really need to use malloc() for some reason, you can check for overflow separately.






share|improve this answer









$endgroup$












  • $begingroup$
    Indeed, this is an often overlooked but very important point. I think that any calloc implementation that does not return a null pointer on overflow would not be conforming.
    $endgroup$
    – jamesdlin
    Jan 26 at 23:38






  • 1




    $begingroup$
    @jamesdlin Yes. Still, one should not ignore that calloc() has to zero the memory too.
    $endgroup$
    – Deduplicator
    Jan 26 at 23:43


















7












$begingroup$

You've taken an expression statement and unnecessarily made a do/while statement out of it. You need parentheses around your macro parameters. You don't need to pass in the pointer you're assigning to as a pointer.



Put all that together and you end up with:



#define ALLOC(p, n) ((p) = malloc((n) * sizeof *(p)))


This puts fewer restrictions on how it is used, and allows things like



struct monster *AddMonsters(monster *monsters, int which_monster, int how_many)

int difficulty_add = ExtraMonsters();
return ALLOC(monsters + which_monster, how_many + difficulty_add);



Yes, you could use monsters[which_monster], add the extra before using the macro, and put a separate return statement, but all that would be unnecessary restrictions on its use.






share|improve this answer









$endgroup$








  • 1




    $begingroup$
    The do-while is just something I always do with macros. A bit redundant here, but it does not hurt. Parenthesis I forgot. Thanks for that. But I do have a good reason for passing it as a pointer. See my edit.
    $endgroup$
    – Broman
    Jan 26 at 17:18






  • 5




    $begingroup$
    @Broman "Does not hurt"? Sure it does. You're unnecessarily making it illegal to use your macro where an expression is expected, such as with if (ALLOC(...)).
    $endgroup$
    – jamesdlin
    Jan 26 at 23:24











  • $begingroup$
    @jamesdlin That's true. Thanks.
    $endgroup$
    – Broman
    Jan 27 at 0:08






  • 1




    $begingroup$
    I would prefer the do-while, personally. The body technically works as an expression, but it’s still an assignment. Those can be surprising in expression position, especially behind a macro.
    $endgroup$
    – gntskn
    Jan 27 at 1:44


















3












$begingroup$

There are a couple questionable things here, first since ALLOC() is a macro you don't need to pass the address of p. If ALLOC() were a function call then you would want to pass the address of p.



Second, for an array I would probably use calloc() rather than malloc().






share|improve this answer









$endgroup$








  • 1




    $begingroup$
    The reason for passing the address is to make it clear that the argument will be modified.
    $endgroup$
    – Broman
    Jan 26 at 17:54


















0












$begingroup$

First of all, remove the unnecessary parts, which can cause errors and make the code harder to read.



#define ALLOC(p,n) p=malloc(n*sizeof *p)


You can make your code more readable with describing names. After months it will be quite hard to understand even your own code.



#define ALLOC(pointer, size) pointer = malloc(size * sizeof *pointer)


Parenthesizes are important! The following call: ALLOC(pointer, size + 1); would be equal with pointer = malloc(size + 1 * sizeof *pointer);, which clearly is a bug.



#define ALLOC(pointer, size) (pointer) = malloc((size) * sizeof(*pointer))


Use calloc instead of malloc, because of security reasons.



#define ALLOC(pointer, size) (pointer) = calloc((size), sizeof(*pointer))


Lastly, do not use function-like macros, instead a function would be a better choice.
https://rules.sonarsource.com/c/tag/preprocessor/RSPEC-960






share|improve this answer









$endgroup$












  • $begingroup$
    "because of security reasons" is very vague, and arguably untrue. It's certainly not enough to justify an obvious pessimisation.
    $endgroup$
    – Toby Speight
    Feb 4 at 12:48










  • $begingroup$
    @jpa explained it quite well, so I did not went into details, but I focused on mentioning different, possible error sources.
    $endgroup$
    – Norbert Incze
    Feb 4 at 14:38










Your Answer





StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
);
);
, "mathjax-editing");

StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f212271%2fmacro-for-allocation-in-c%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























4 Answers
4






active

oldest

votes








4 Answers
4






active

oldest

votes









active

oldest

votes






active

oldest

votes









14












$begingroup$


p = malloc(n*sizeof *p);




This is dangerous if n gets large, because the multiplication could overflow. After the overflow, too little memory has been allocated but code will continue without detecting the error.



This is especially dangerous if n comes from untrusted source, such as some file format or remote user. Then it gives attacker easy way to overwrite parts of memory with exploit code.



The easy safe solution is to use calloc() which will detect the overflow (at least on most common libc implementations). If you really need to use malloc() for some reason, you can check for overflow separately.






share|improve this answer









$endgroup$












  • $begingroup$
    Indeed, this is an often overlooked but very important point. I think that any calloc implementation that does not return a null pointer on overflow would not be conforming.
    $endgroup$
    – jamesdlin
    Jan 26 at 23:38






  • 1




    $begingroup$
    @jamesdlin Yes. Still, one should not ignore that calloc() has to zero the memory too.
    $endgroup$
    – Deduplicator
    Jan 26 at 23:43















14












$begingroup$


p = malloc(n*sizeof *p);




This is dangerous if n gets large, because the multiplication could overflow. After the overflow, too little memory has been allocated but code will continue without detecting the error.



This is especially dangerous if n comes from untrusted source, such as some file format or remote user. Then it gives attacker easy way to overwrite parts of memory with exploit code.



The easy safe solution is to use calloc() which will detect the overflow (at least on most common libc implementations). If you really need to use malloc() for some reason, you can check for overflow separately.






share|improve this answer









$endgroup$












  • $begingroup$
    Indeed, this is an often overlooked but very important point. I think that any calloc implementation that does not return a null pointer on overflow would not be conforming.
    $endgroup$
    – jamesdlin
    Jan 26 at 23:38






  • 1




    $begingroup$
    @jamesdlin Yes. Still, one should not ignore that calloc() has to zero the memory too.
    $endgroup$
    – Deduplicator
    Jan 26 at 23:43













14












14








14





$begingroup$


p = malloc(n*sizeof *p);




This is dangerous if n gets large, because the multiplication could overflow. After the overflow, too little memory has been allocated but code will continue without detecting the error.



This is especially dangerous if n comes from untrusted source, such as some file format or remote user. Then it gives attacker easy way to overwrite parts of memory with exploit code.



The easy safe solution is to use calloc() which will detect the overflow (at least on most common libc implementations). If you really need to use malloc() for some reason, you can check for overflow separately.






share|improve this answer









$endgroup$




p = malloc(n*sizeof *p);




This is dangerous if n gets large, because the multiplication could overflow. After the overflow, too little memory has been allocated but code will continue without detecting the error.



This is especially dangerous if n comes from untrusted source, such as some file format or remote user. Then it gives attacker easy way to overwrite parts of memory with exploit code.



The easy safe solution is to use calloc() which will detect the overflow (at least on most common libc implementations). If you really need to use malloc() for some reason, you can check for overflow separately.







share|improve this answer












share|improve this answer



share|improve this answer










answered Jan 26 at 19:56









jpajpa

2412




2412











  • $begingroup$
    Indeed, this is an often overlooked but very important point. I think that any calloc implementation that does not return a null pointer on overflow would not be conforming.
    $endgroup$
    – jamesdlin
    Jan 26 at 23:38






  • 1




    $begingroup$
    @jamesdlin Yes. Still, one should not ignore that calloc() has to zero the memory too.
    $endgroup$
    – Deduplicator
    Jan 26 at 23:43
















  • $begingroup$
    Indeed, this is an often overlooked but very important point. I think that any calloc implementation that does not return a null pointer on overflow would not be conforming.
    $endgroup$
    – jamesdlin
    Jan 26 at 23:38






  • 1




    $begingroup$
    @jamesdlin Yes. Still, one should not ignore that calloc() has to zero the memory too.
    $endgroup$
    – Deduplicator
    Jan 26 at 23:43















$begingroup$
Indeed, this is an often overlooked but very important point. I think that any calloc implementation that does not return a null pointer on overflow would not be conforming.
$endgroup$
– jamesdlin
Jan 26 at 23:38




$begingroup$
Indeed, this is an often overlooked but very important point. I think that any calloc implementation that does not return a null pointer on overflow would not be conforming.
$endgroup$
– jamesdlin
Jan 26 at 23:38




1




1




$begingroup$
@jamesdlin Yes. Still, one should not ignore that calloc() has to zero the memory too.
$endgroup$
– Deduplicator
Jan 26 at 23:43




$begingroup$
@jamesdlin Yes. Still, one should not ignore that calloc() has to zero the memory too.
$endgroup$
– Deduplicator
Jan 26 at 23:43













7












$begingroup$

You've taken an expression statement and unnecessarily made a do/while statement out of it. You need parentheses around your macro parameters. You don't need to pass in the pointer you're assigning to as a pointer.



Put all that together and you end up with:



#define ALLOC(p, n) ((p) = malloc((n) * sizeof *(p)))


This puts fewer restrictions on how it is used, and allows things like



struct monster *AddMonsters(monster *monsters, int which_monster, int how_many)

int difficulty_add = ExtraMonsters();
return ALLOC(monsters + which_monster, how_many + difficulty_add);



Yes, you could use monsters[which_monster], add the extra before using the macro, and put a separate return statement, but all that would be unnecessary restrictions on its use.






share|improve this answer









$endgroup$








  • 1




    $begingroup$
    The do-while is just something I always do with macros. A bit redundant here, but it does not hurt. Parenthesis I forgot. Thanks for that. But I do have a good reason for passing it as a pointer. See my edit.
    $endgroup$
    – Broman
    Jan 26 at 17:18






  • 5




    $begingroup$
    @Broman "Does not hurt"? Sure it does. You're unnecessarily making it illegal to use your macro where an expression is expected, such as with if (ALLOC(...)).
    $endgroup$
    – jamesdlin
    Jan 26 at 23:24











  • $begingroup$
    @jamesdlin That's true. Thanks.
    $endgroup$
    – Broman
    Jan 27 at 0:08






  • 1




    $begingroup$
    I would prefer the do-while, personally. The body technically works as an expression, but it’s still an assignment. Those can be surprising in expression position, especially behind a macro.
    $endgroup$
    – gntskn
    Jan 27 at 1:44















7












$begingroup$

You've taken an expression statement and unnecessarily made a do/while statement out of it. You need parentheses around your macro parameters. You don't need to pass in the pointer you're assigning to as a pointer.



Put all that together and you end up with:



#define ALLOC(p, n) ((p) = malloc((n) * sizeof *(p)))


This puts fewer restrictions on how it is used, and allows things like



struct monster *AddMonsters(monster *monsters, int which_monster, int how_many)

int difficulty_add = ExtraMonsters();
return ALLOC(monsters + which_monster, how_many + difficulty_add);



Yes, you could use monsters[which_monster], add the extra before using the macro, and put a separate return statement, but all that would be unnecessary restrictions on its use.






share|improve this answer









$endgroup$








  • 1




    $begingroup$
    The do-while is just something I always do with macros. A bit redundant here, but it does not hurt. Parenthesis I forgot. Thanks for that. But I do have a good reason for passing it as a pointer. See my edit.
    $endgroup$
    – Broman
    Jan 26 at 17:18






  • 5




    $begingroup$
    @Broman "Does not hurt"? Sure it does. You're unnecessarily making it illegal to use your macro where an expression is expected, such as with if (ALLOC(...)).
    $endgroup$
    – jamesdlin
    Jan 26 at 23:24











  • $begingroup$
    @jamesdlin That's true. Thanks.
    $endgroup$
    – Broman
    Jan 27 at 0:08






  • 1




    $begingroup$
    I would prefer the do-while, personally. The body technically works as an expression, but it’s still an assignment. Those can be surprising in expression position, especially behind a macro.
    $endgroup$
    – gntskn
    Jan 27 at 1:44













7












7








7





$begingroup$

You've taken an expression statement and unnecessarily made a do/while statement out of it. You need parentheses around your macro parameters. You don't need to pass in the pointer you're assigning to as a pointer.



Put all that together and you end up with:



#define ALLOC(p, n) ((p) = malloc((n) * sizeof *(p)))


This puts fewer restrictions on how it is used, and allows things like



struct monster *AddMonsters(monster *monsters, int which_monster, int how_many)

int difficulty_add = ExtraMonsters();
return ALLOC(monsters + which_monster, how_many + difficulty_add);



Yes, you could use monsters[which_monster], add the extra before using the macro, and put a separate return statement, but all that would be unnecessary restrictions on its use.






share|improve this answer









$endgroup$



You've taken an expression statement and unnecessarily made a do/while statement out of it. You need parentheses around your macro parameters. You don't need to pass in the pointer you're assigning to as a pointer.



Put all that together and you end up with:



#define ALLOC(p, n) ((p) = malloc((n) * sizeof *(p)))


This puts fewer restrictions on how it is used, and allows things like



struct monster *AddMonsters(monster *monsters, int which_monster, int how_many)

int difficulty_add = ExtraMonsters();
return ALLOC(monsters + which_monster, how_many + difficulty_add);



Yes, you could use monsters[which_monster], add the extra before using the macro, and put a separate return statement, but all that would be unnecessary restrictions on its use.







share|improve this answer












share|improve this answer



share|improve this answer










answered Jan 26 at 16:59









1201ProgramAlarm1201ProgramAlarm

3,2082823




3,2082823







  • 1




    $begingroup$
    The do-while is just something I always do with macros. A bit redundant here, but it does not hurt. Parenthesis I forgot. Thanks for that. But I do have a good reason for passing it as a pointer. See my edit.
    $endgroup$
    – Broman
    Jan 26 at 17:18






  • 5




    $begingroup$
    @Broman "Does not hurt"? Sure it does. You're unnecessarily making it illegal to use your macro where an expression is expected, such as with if (ALLOC(...)).
    $endgroup$
    – jamesdlin
    Jan 26 at 23:24











  • $begingroup$
    @jamesdlin That's true. Thanks.
    $endgroup$
    – Broman
    Jan 27 at 0:08






  • 1




    $begingroup$
    I would prefer the do-while, personally. The body technically works as an expression, but it’s still an assignment. Those can be surprising in expression position, especially behind a macro.
    $endgroup$
    – gntskn
    Jan 27 at 1:44












  • 1




    $begingroup$
    The do-while is just something I always do with macros. A bit redundant here, but it does not hurt. Parenthesis I forgot. Thanks for that. But I do have a good reason for passing it as a pointer. See my edit.
    $endgroup$
    – Broman
    Jan 26 at 17:18






  • 5




    $begingroup$
    @Broman "Does not hurt"? Sure it does. You're unnecessarily making it illegal to use your macro where an expression is expected, such as with if (ALLOC(...)).
    $endgroup$
    – jamesdlin
    Jan 26 at 23:24











  • $begingroup$
    @jamesdlin That's true. Thanks.
    $endgroup$
    – Broman
    Jan 27 at 0:08






  • 1




    $begingroup$
    I would prefer the do-while, personally. The body technically works as an expression, but it’s still an assignment. Those can be surprising in expression position, especially behind a macro.
    $endgroup$
    – gntskn
    Jan 27 at 1:44







1




1




$begingroup$
The do-while is just something I always do with macros. A bit redundant here, but it does not hurt. Parenthesis I forgot. Thanks for that. But I do have a good reason for passing it as a pointer. See my edit.
$endgroup$
– Broman
Jan 26 at 17:18




$begingroup$
The do-while is just something I always do with macros. A bit redundant here, but it does not hurt. Parenthesis I forgot. Thanks for that. But I do have a good reason for passing it as a pointer. See my edit.
$endgroup$
– Broman
Jan 26 at 17:18




5




5




$begingroup$
@Broman "Does not hurt"? Sure it does. You're unnecessarily making it illegal to use your macro where an expression is expected, such as with if (ALLOC(...)).
$endgroup$
– jamesdlin
Jan 26 at 23:24





$begingroup$
@Broman "Does not hurt"? Sure it does. You're unnecessarily making it illegal to use your macro where an expression is expected, such as with if (ALLOC(...)).
$endgroup$
– jamesdlin
Jan 26 at 23:24













$begingroup$
@jamesdlin That's true. Thanks.
$endgroup$
– Broman
Jan 27 at 0:08




$begingroup$
@jamesdlin That's true. Thanks.
$endgroup$
– Broman
Jan 27 at 0:08




1




1




$begingroup$
I would prefer the do-while, personally. The body technically works as an expression, but it’s still an assignment. Those can be surprising in expression position, especially behind a macro.
$endgroup$
– gntskn
Jan 27 at 1:44




$begingroup$
I would prefer the do-while, personally. The body technically works as an expression, but it’s still an assignment. Those can be surprising in expression position, especially behind a macro.
$endgroup$
– gntskn
Jan 27 at 1:44











3












$begingroup$

There are a couple questionable things here, first since ALLOC() is a macro you don't need to pass the address of p. If ALLOC() were a function call then you would want to pass the address of p.



Second, for an array I would probably use calloc() rather than malloc().






share|improve this answer









$endgroup$








  • 1




    $begingroup$
    The reason for passing the address is to make it clear that the argument will be modified.
    $endgroup$
    – Broman
    Jan 26 at 17:54















3












$begingroup$

There are a couple questionable things here, first since ALLOC() is a macro you don't need to pass the address of p. If ALLOC() were a function call then you would want to pass the address of p.



Second, for an array I would probably use calloc() rather than malloc().






share|improve this answer









$endgroup$








  • 1




    $begingroup$
    The reason for passing the address is to make it clear that the argument will be modified.
    $endgroup$
    – Broman
    Jan 26 at 17:54













3












3








3





$begingroup$

There are a couple questionable things here, first since ALLOC() is a macro you don't need to pass the address of p. If ALLOC() were a function call then you would want to pass the address of p.



Second, for an array I would probably use calloc() rather than malloc().






share|improve this answer









$endgroup$



There are a couple questionable things here, first since ALLOC() is a macro you don't need to pass the address of p. If ALLOC() were a function call then you would want to pass the address of p.



Second, for an array I would probably use calloc() rather than malloc().







share|improve this answer












share|improve this answer



share|improve this answer










answered Jan 26 at 16:17









pacmaninbwpacmaninbw

5,15321537




5,15321537







  • 1




    $begingroup$
    The reason for passing the address is to make it clear that the argument will be modified.
    $endgroup$
    – Broman
    Jan 26 at 17:54












  • 1




    $begingroup$
    The reason for passing the address is to make it clear that the argument will be modified.
    $endgroup$
    – Broman
    Jan 26 at 17:54







1




1




$begingroup$
The reason for passing the address is to make it clear that the argument will be modified.
$endgroup$
– Broman
Jan 26 at 17:54




$begingroup$
The reason for passing the address is to make it clear that the argument will be modified.
$endgroup$
– Broman
Jan 26 at 17:54











0












$begingroup$

First of all, remove the unnecessary parts, which can cause errors and make the code harder to read.



#define ALLOC(p,n) p=malloc(n*sizeof *p)


You can make your code more readable with describing names. After months it will be quite hard to understand even your own code.



#define ALLOC(pointer, size) pointer = malloc(size * sizeof *pointer)


Parenthesizes are important! The following call: ALLOC(pointer, size + 1); would be equal with pointer = malloc(size + 1 * sizeof *pointer);, which clearly is a bug.



#define ALLOC(pointer, size) (pointer) = malloc((size) * sizeof(*pointer))


Use calloc instead of malloc, because of security reasons.



#define ALLOC(pointer, size) (pointer) = calloc((size), sizeof(*pointer))


Lastly, do not use function-like macros, instead a function would be a better choice.
https://rules.sonarsource.com/c/tag/preprocessor/RSPEC-960






share|improve this answer









$endgroup$












  • $begingroup$
    "because of security reasons" is very vague, and arguably untrue. It's certainly not enough to justify an obvious pessimisation.
    $endgroup$
    – Toby Speight
    Feb 4 at 12:48










  • $begingroup$
    @jpa explained it quite well, so I did not went into details, but I focused on mentioning different, possible error sources.
    $endgroup$
    – Norbert Incze
    Feb 4 at 14:38















0












$begingroup$

First of all, remove the unnecessary parts, which can cause errors and make the code harder to read.



#define ALLOC(p,n) p=malloc(n*sizeof *p)


You can make your code more readable with describing names. After months it will be quite hard to understand even your own code.



#define ALLOC(pointer, size) pointer = malloc(size * sizeof *pointer)


Parenthesizes are important! The following call: ALLOC(pointer, size + 1); would be equal with pointer = malloc(size + 1 * sizeof *pointer);, which clearly is a bug.



#define ALLOC(pointer, size) (pointer) = malloc((size) * sizeof(*pointer))


Use calloc instead of malloc, because of security reasons.



#define ALLOC(pointer, size) (pointer) = calloc((size), sizeof(*pointer))


Lastly, do not use function-like macros, instead a function would be a better choice.
https://rules.sonarsource.com/c/tag/preprocessor/RSPEC-960






share|improve this answer









$endgroup$












  • $begingroup$
    "because of security reasons" is very vague, and arguably untrue. It's certainly not enough to justify an obvious pessimisation.
    $endgroup$
    – Toby Speight
    Feb 4 at 12:48










  • $begingroup$
    @jpa explained it quite well, so I did not went into details, but I focused on mentioning different, possible error sources.
    $endgroup$
    – Norbert Incze
    Feb 4 at 14:38













0












0








0





$begingroup$

First of all, remove the unnecessary parts, which can cause errors and make the code harder to read.



#define ALLOC(p,n) p=malloc(n*sizeof *p)


You can make your code more readable with describing names. After months it will be quite hard to understand even your own code.



#define ALLOC(pointer, size) pointer = malloc(size * sizeof *pointer)


Parenthesizes are important! The following call: ALLOC(pointer, size + 1); would be equal with pointer = malloc(size + 1 * sizeof *pointer);, which clearly is a bug.



#define ALLOC(pointer, size) (pointer) = malloc((size) * sizeof(*pointer))


Use calloc instead of malloc, because of security reasons.



#define ALLOC(pointer, size) (pointer) = calloc((size), sizeof(*pointer))


Lastly, do not use function-like macros, instead a function would be a better choice.
https://rules.sonarsource.com/c/tag/preprocessor/RSPEC-960






share|improve this answer









$endgroup$



First of all, remove the unnecessary parts, which can cause errors and make the code harder to read.



#define ALLOC(p,n) p=malloc(n*sizeof *p)


You can make your code more readable with describing names. After months it will be quite hard to understand even your own code.



#define ALLOC(pointer, size) pointer = malloc(size * sizeof *pointer)


Parenthesizes are important! The following call: ALLOC(pointer, size + 1); would be equal with pointer = malloc(size + 1 * sizeof *pointer);, which clearly is a bug.



#define ALLOC(pointer, size) (pointer) = malloc((size) * sizeof(*pointer))


Use calloc instead of malloc, because of security reasons.



#define ALLOC(pointer, size) (pointer) = calloc((size), sizeof(*pointer))


Lastly, do not use function-like macros, instead a function would be a better choice.
https://rules.sonarsource.com/c/tag/preprocessor/RSPEC-960







share|improve this answer












share|improve this answer



share|improve this answer










answered Feb 2 at 17:53









Norbert InczeNorbert Incze

1




1











  • $begingroup$
    "because of security reasons" is very vague, and arguably untrue. It's certainly not enough to justify an obvious pessimisation.
    $endgroup$
    – Toby Speight
    Feb 4 at 12:48










  • $begingroup$
    @jpa explained it quite well, so I did not went into details, but I focused on mentioning different, possible error sources.
    $endgroup$
    – Norbert Incze
    Feb 4 at 14:38
















  • $begingroup$
    "because of security reasons" is very vague, and arguably untrue. It's certainly not enough to justify an obvious pessimisation.
    $endgroup$
    – Toby Speight
    Feb 4 at 12:48










  • $begingroup$
    @jpa explained it quite well, so I did not went into details, but I focused on mentioning different, possible error sources.
    $endgroup$
    – Norbert Incze
    Feb 4 at 14:38















$begingroup$
"because of security reasons" is very vague, and arguably untrue. It's certainly not enough to justify an obvious pessimisation.
$endgroup$
– Toby Speight
Feb 4 at 12:48




$begingroup$
"because of security reasons" is very vague, and arguably untrue. It's certainly not enough to justify an obvious pessimisation.
$endgroup$
– Toby Speight
Feb 4 at 12:48












$begingroup$
@jpa explained it quite well, so I did not went into details, but I focused on mentioning different, possible error sources.
$endgroup$
– Norbert Incze
Feb 4 at 14:38




$begingroup$
@jpa explained it quite well, so I did not went into details, but I focused on mentioning different, possible error sources.
$endgroup$
– Norbert Incze
Feb 4 at 14:38

















draft saved

draft discarded
















































Thanks for contributing an answer to Code Review Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

Use MathJax to format equations. MathJax reference.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f212271%2fmacro-for-allocation-in-c%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown






Popular posts from this blog

How to check contact read email or not when send email to Individual?

Displaying single band from multi-band raster using QGIS

How many registers does an x86_64 CPU actually have?