0

I donno if this is possible or not but am confused. Are they both same? I know that in the first case we are allocating memory dynamically for 20 elements of type int.

int *p;
p=(int *) malloc(20*sizeof(int));

and

p=(int *) malloc(sizeof(int)*20);
user207421
  • 305,947
  • 44
  • 307
  • 483
blogger10
  • 23
  • 5
  • 3
    They are both the same. Multiplication is commutative, therefore `20*sizeof(int)` is equivalent to `sizeof(int)*20`. malloc just takes the _number of bytes_ to allocate, so either way around will give you the correct result - e.g. `amount_of_space_for_int * 20` v.s. `20 * amount_of_space_for_int` – robthebloke Jul 03 '23 at 04:39
  • ok thanks ,it cleared my doubt. – blogger10 Jul 03 '23 at 05:05
  • 2
    This has nothing to do with [tag:pointer] or [tag:malloc]. The same is true of any multiplication operator in C, and of others such as addition as well. – user207421 Jul 03 '23 at 05:14
  • 1
    OT #1: In C it is not necessary and therefore frowned upon to cast the `void*` returned by `malloc()`. – the busybee Jul 03 '23 at 05:57
  • 3
    OT #2: Instead of a `sizeof` operation with a type, better use it with the dereferenced target: `p = malloc(20 * sizeof *p);` (please note that `sizeof` is an operator, not a function). – the busybee Jul 03 '23 at 06:03
  • When you multiply by any *factor*, the order of in which you multiply the factors does not change the *product*. That is the *associative property of multiplication*. – David C. Rankin Jul 03 '23 at 06:31
  • @DavidC.Rankin "the order of in which you multiply the factors" is _communitive_, not _associative_. Associative is a problem as `int * int * size_t` can overflow where `size_t * int * int` does not. – chux - Reinstate Monica Jul 03 '23 at 06:52
  • 1
    @chux -- yes, thank you for the catch! Associative is *grouping*... That's what happens when it's been over 45 years since you had basic math `:)` – David C. Rankin Jul 03 '23 at 07:02
  • @DavidC.Rankin For me, **co**mmunative is 2, **ass**ociative is 3. And we should not [assume](https://www.explainxkcd.com/wiki/index.php/1339:_When_You_Assume). – chux - Reinstate Monica Jul 03 '23 at 07:09
  • @chux-ReinstateMonica The word is *commutative*, not "communitive" or "communative". – nielsen Jul 03 '23 at 07:24
  • @nielsen Yes _commutative_, The spell checker did not help with the in-word bolding and spelling is my Achilles heel. – chux - Reinstate Monica Jul 03 '23 at 07:26

1 Answers1

2

Recall that sizeof operator returns type: size_t.

In the case of int * size_t (20*sizeof(int)) versus size_t * int (sizeof(int) * 20): the product is the same as the narrower type is widened to the other first and multiplication in C is commutative: a*b equals b*a.

The situation changes with int * int * size_t versus size_t * int * int as in C, multiplication is not associative. The first multiples int * int (with an int product), then does int * size_t. With select values, the first multiplication may overflow whereas size_t * int * int does not.

When more than 2 objects may be multiplied, best to make certain the widest multiplication happens first and subsequently: example size_t * int * int.


Is there any difference between these two?

With only 2 objects to multiply, code in whatever way you like.
I like to lead with the likely wider type.


Since the cast is not needed and sizing to the object is easier to code right, review and maintain, consider:

p = malloc(sizeof p[0] * 20);
if (p == NULL) {
  TBD(); // Handle out-of-memory
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • 1
    Regarding the rather subjective arguments of coding style, check out [How to properly use malloc?](https://software.codidact.com/posts/285898/285910#answer-285910) – Lundin Jul 03 '23 at 09:11
  • `size_t * int * int` can also overflow. – 12431234123412341234123 Jul 03 '23 at 11:04
  • @Lundin In reviewing compliable code `p.member = malloc(sizeof p.member[0])` vs. `p.member = malloc(sizeof(int))`, the first is correct on its face. The 2nd obliges a hunt for the definition of `p` and then its type. The type definition may well lie in another file. Concerning "easier to code right, review and maintain", it is the _review_ part that is strongest of using size of the object over using the size of the type. As with such _style_ issues, best to code to the group's coding standard as there is much entrenchment on this issue . – chux - Reinstate Monica Jul 03 '23 at 15:32
  • 1
    @12431234123412341234123 True that `size_t * int * int` _can_ overflow, yet `size_t * int * int` will not overflow for many combinations that `int * int *size_t` does. – chux - Reinstate Monica Jul 03 '23 at 15:33
  • @chux-ReinstateMonica A seasoned programmer does not write coding using _any_ variable without looking up its type first. Luckily, "modern" (as in made this millennium) IDEs make it easy to track down identifiers with a single key press or at worst some right-click menu. So it's a poor rationale - we shouldn't use _any_ variable in any context without knowing its type first. – Lundin Jul 04 '23 at 06:55
  • 1
    @Lundin As mentioned [before](https://stackoverflow.com/questions/76601840/is-there-any-difference-between-these-two/76602546?noredirect=1#comment135065707_76602546), an advantage to `p = malloc(sizeof p[0])` is in review. That is not about writing code, but others (not the original maybe junior author) reviewing. IDEs may help when available, yet not apply as in reviewing code here or in [Code review](https://codereview.stackexchange.com) for example. The 1 click look-up is still more than 0 afforded with `sizeof p[0]`. It is a good rational to not even need the context when its irrelevant. – chux - Reinstate Monica Jul 04 '23 at 15:20