0
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    double *array;
    unsigned int size;

    printf("Choose size for your number array: ");
    scanf("%u", &size);

    array = malloc(sizeof(double) * size);

    return 0;
}

I memory allocated sizeof(double) * size, which I don't know if sizeof(double) is necessary, but sizeof(double) is not 1, so I don't know if I should either:

for (int i = 0; i < size; i++) {

} 

For loop through size without multiply it with sizeof(double), or:

for (int i = 0; i < sizeof(double) * size; i++) {

}

For loop and multiply size with sizeof(double) as well? The reason why I'm asking is because I really want to be careful and prevent going over size.

For loop without multiplying sizeof(double) or not?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Jack Murrow
  • 396
  • 3
  • 11
  • How many `double`s are there in your array? `size` or `size * sizeof(double)`? – ForceBru Jul 17 '20 at 20:21
  • 1
    When you increment the index of an array, it moves by a whole double, not a byte. Same for a pointer. – stark Jul 17 '20 at 20:23
  • For example, `sizeof(char)` would be 1, but `sizeof(double)` won't be 1 (Idk if it is 8), so am I supposed to multiply by `sizeof(double)` or what? I'm starting to get confused on the purpose of multiplying sizeof(double). – Jack Murrow Jul 17 '20 at 20:29
  • Usually without multiplying, but to make sure, tell us what's inside the loop and how you use `i`. – Nate Eldredge Jul 17 '20 at 20:43
  • Basically, you need to keep track of whether you are counting **bytes** or counting **elements**. `malloc` needs a count of bytes. Most other things, such as array declarations, subscripting `arr[i]` and pointer arithmetic `p+i` need a count of elements. The number of bytes is `sizeof(double)` times larger than the number of elements. – Nate Eldredge Jul 17 '20 at 20:45
  • 1
    Jack, consider `arr = malloc(sizeof *arr * size);`. It is the right size for an array `size` of whatever type `arr` points to. – chux - Reinstate Monica Jul 17 '20 at 20:45
  • If you are struggling to make friends with pointers, the following two links provide a basic discussion of pointers and their use. May help the pieces fall into place. [Difference between char *pp and (char*) p?](https://stackoverflow.com/a/60519053/3422102) and [Pointer to pointer of structs indexing out of bounds(?)...](https://stackoverflow.com/a/60639540/3422102) (ignore the titles, the discussion starts at the basic level) – David C. Rankin Jul 17 '20 at 20:57
  • @NateEldredge Thanks for that explanation. It was very basic and easy to understand. Now I understand about malloc. – Jack Murrow Jul 17 '20 at 21:22
  • @chux-ReinstateMonica Well, why are other people using `sizeof(char)` and stuff like that instead of yours? @DavidC.Rankin Thank you for those discussions – Jack Murrow Jul 17 '20 at 21:24
  • @JackMurrow I have found it easier to code right, review and maintain for decades. As to why others code with the type rather than the reference data, suggest asking them. I suspect [practice based on the observation that it has been used elsewhere, without understanding the motivation for its use](https://en.wikipedia.org/wiki/Cargo_cult). – chux - Reinstate Monica Jul 17 '20 at 22:10
  • @chux-ReinstateMonica When using `malloc`, it needs a count of bytes as people say. And for example, `sizeof(double)` would be 8 bytes so and array of 10 doubles, would need 80 bytes allocated. – Jack Murrow Jul 17 '20 at 22:22
  • Jack, If the reference data type was `char`, then the compiler would make an optimization and simply do `malloc(size)`. If the referenced data type size was more than 1, again the compiler would make a nice optimized multiply. Either way, I can more quickly code correctly and move on to highly level concerns knowing the code is right even if later, the type of `*array` changes. – chux - Reinstate Monica Jul 17 '20 at 22:28
  • Jack. is it clear for you that in this code, `sizeof *arr` and `sizeof(double)` are both the same value and type? – chux - Reinstate Monica Jul 17 '20 at 22:31
  • No, it is not clear, but you're saying that the compiler would do the multiplying for me? – Jack Murrow Jul 17 '20 at 23:36

3 Answers3

3

You allocate sizeof(double) * size memory to have array of doubles, the number of elements is size. So multiply in malloc, don't multiply in for

Alex Guteniev
  • 12,039
  • 2
  • 34
  • 79
  • Do you multiply `sizeof(double)` when `double array[sizeof(double) * size]` or only for malloc? – Jack Murrow Jul 17 '20 at 20:31
  • @JackMurrow You only multiply `sizeof(double) * size` in the malloc. There is no need to multiply for anything else. It seems to me that what you really need is to first understand what malloc does. – isrnick Jul 17 '20 at 20:48
  • "The `malloc()` function allocates size bytes ..." Note the `"bytes"`. If you have a `double` that is 8 bytes and you have an array of 10 doubles, then you need 80 bytes allocated. Which in your case is `size` (e.g. 10) times `sizeof(double)` (8) gives you storage for 10 doubles. – David C. Rankin Jul 17 '20 at 21:03
  • Ohh, it allocates size bytes. Thanks for the help! – Jack Murrow Jul 17 '20 at 21:09
2

In this statement

array = malloc(sizeof(double) * size);

there is allocated memory for size elements with the size of objects of the type double.

You could rewrite the statement like

array = malloc( sizeof( double[size] ) );

An equivalent declaration with automatic storage duration would look like

double array[size];

if you will write (for the declaration of the array shown above with automatic or static storage duration)

printf( "sizeof( array ) = %zu\n", sizeof( array ) );

you will get a value equal to size * sizeof( double ).

So if you want to traverse all allocated elements to initialize them you should write for example

for ( int i = 0; i < size; i++ )
{
    *( array + i ) = 0.0;
}

that is equivalent to

for ( int i = 0; i < size; i++ )
{
    array[i] = 0.0;
}

This expression

array + i

where there is used the pointer arithmetic yields the value of pointer equal to

( double * )( ( char * )array + i * sizeof( double ) ) 

That is it points to the i-th element of the allocated array.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • I don't exactly understand the part about when you said `This expression` `where there is used the pointer arithmetic yields the value of pointer equal to` `That is it points to the i-th element of the allocated array.` Can you explain a bit more in an easier way? – Jack Murrow Jul 17 '20 at 21:17
  • @JackMurrow When you write for example array[i] then you get the address that has the offset relative to the initial address of array equal to i * sizeof( double ). – Vlad from Moscow Jul 17 '20 at 21:19
  • Sorry, I still don't understand for `array[i] then you get the address that has the offset relative to the initial address of array equal to i * sizeof( double )`. I don't want to waste too much of your time. – Jack Murrow Jul 17 '20 at 21:30
  • @JackMurrow For example array[0] has the address (for simplicity) equal to 0. Then the address of the element a[1] is equal to 0 + 1 * sizeof( double ). That is to get the access to the second element of the array you have to move the pointer to the right by the value of the object of the type double. – Vlad from Moscow Jul 17 '20 at 21:33
  • @JackMurrow Imagine that you are in the beginning of a street that has several buildings of the same size. To come to the second building you have to walk as many meters as the size of the first building – Vlad from Moscow Jul 17 '20 at 21:38
  • I am understanding more of what you are saying. But, I don't understand `by the value of the object of the type double`. – Jack Murrow Jul 17 '20 at 21:40
  • @JackMurrow The street contains two buildings of the type double.:) To come to the second building you have to walk sizeof( double ) meters. That is the index in a loop is being changed according to the number of buildings but that means that the passed distance is equal to i * sizeof( double ). – Vlad from Moscow Jul 17 '20 at 21:43
  • Now I understand, thanks for taking the time to help me! I really appreciate it! – Jack Murrow Jul 17 '20 at 21:47
1

malloc(X) returns X bytes, so if you want to store size doubles, call malloc(size * sizeof(double))

Morten Jensen
  • 5,818
  • 3
  • 43
  • 55