-3

Here is the essence of what I am trying to do:

double *E; //Array of doubles
int N;  //The eventual size of the array, typically >1

// some code where variable N gets assigned

//inside of some function
E = malloc(sizeof(double)*N);

printf("size of E = %lu\n",sizeof(E)/sizeof(E[0])); //checking size of array E

The output of this code is "size of E = 1", regardless of the actual value of N. Why does the malloc() function not allocate the correct size in memory?

I know this seems very rudimentary, but I cannot understand why this would not work.

Any insight would be greatly appreciated.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
Daniel M
  • 21
  • 4
  • 3
    `sizeof(E)` is the size of the pointer. You already know the size of the array, because you only just told `malloc` how memory you want, `N`. If `E == NULL` then the size is `0`.This is a frequently asked question. – Weather Vane Jun 19 '16 at 21:57
  • On a related note, you should always use `calloc` for this kind of cases. –  Jun 19 '16 at 21:59
  • @Rhymoid for what "kind of case"? Are you saying `malloc` should not be used? – Weather Vane Jun 19 '16 at 22:00
  • @WeatherVane ~~~Kinda. The use of `malloc` to allocate an array of structures is often a sign of ignorance or premature optimisation.~~~ -edit- Never mind. –  Jun 19 '16 at 22:03
  • 4
    @Rhymoid: No. `calloc()` initializes the allocated memory to all-bits-zero. There is no guarantee that either floating-point `0.0` or a null pointer is represented as all-bits-zero (though they often are). – Keith Thompson Jun 19 '16 at 22:04
  • 3
    @Rhymoid Op has given no indication of usage. If the array is to be initialised with specific data, `calloc` just wastes CPU time. – Weather Vane Jun 19 '16 at 22:05
  • @KeithThompson I stand corrected. I thought that `calloc` also prevented multiplication overflows, but that's [apparently not a guarantee either](https://www.securecoding.cert.org/confluence/display/c/MEM07-C.+Ensure+that+the+arguments+to+calloc%28%29%2C+when+multiplied%2C+do+not+wrap). –  Jun 19 '16 at 22:07
  • Safest (and most portable) way to initialise an array allocated by `malloc` is to use an explicit loop with proper initialiser (use a compound literal for agregate types and `union`s). A good compiler might very well optimise and possibly even call `memset` or `calloc`. But leave it to the implementation. – too honest for this site Jun 19 '16 at 22:15
  • @Rhymoid: `calloc` *is* required to avoid multiplication overflows. Assume for simplicity 16-bit `size_t` and `unsigned int`. The multiplication `65535 * 65535` wraps around and evalutes to `1`, but `calloc(65535, 65535)` *must* either allocate `4294836225` bytes or fail. Any implementation that successfully allocates fewer bytes is non-conforming (buggy). The [link](https://www.securecoding.cert.org/confluence/display/c/MEM07-C.+Ensure+that+the+arguments+to+calloc%28%29%2C+when+multiplied%2C+do+not+wrap) you cite is a workaround for buggy implementations. – Keith Thompson Jun 19 '16 at 22:35

4 Answers4

2

You are essentially dividing the size of the pointer by the size of a double. Both take the same amount of bytes (8 typically) to store. therefore you get 1.

Muli Yulzary
  • 2,559
  • 3
  • 21
  • 39
  • Thanks, I just misunderstood the use of the sizeof() function. It seems like there is a lot of confusion about this, as I saw many posts such as this one (http://stackoverflow.com/questions/37538/how-do-i-determine-the-size-of-my-array-in-c), which indicates that sizeof() will give the length of the array being pointed to. – Daniel M Jun 19 '16 at 22:43
1

E's type is pointer to double. E's value is an address. When you get the sizeof(E), you are getting the size of the variable that is the pointer rather than the size of what is being pointed to by the variable. In order to get the size of what malloc allocated, you need to dereference the pointer in sizeof so your last line becomes :

printf("size of E = %lu\n",sizeof(*E) * N/sizeof(E[0]));

EDIT

There is no difference between *E and E[0] as pointed out by one of the comments. In C, there is no way of you knowing where you array ends because the array itself as a datatype does not store its length. This is partly why the vector datatype in C++ was necessary.

Also, since you already stored the length of the array in N, you might as well just print N. When you pass the array to any functions, pass the array along with the length. With strings, you can get away with iterating over the character array till you get '\0', the null terminating character. For integer and floating point datatype arrays, there is no such convention.

RonaldMunodawafa
  • 223
  • 3
  • 11
  • 2
    Will `sizeof *E` and `sizeof E[0]` ever be different? – Weather Vane Jun 19 '16 at 22:04
  • @WeatherVane I don't believe so. – Schwern Jun 19 '16 at 22:09
  • @Schwern well I shouln't have phrased it as question. Text lacks intonation. – Weather Vane Jun 19 '16 at 22:13
  • @WeatherVane Thank you for reminding me. *E and sizeof E[0] will return the same value. I have updated the answer. In some contexts, I suppose you could get the address of each element as you iterate through the array until you get a null pointer but this is far from being a reliable method to actually use in any given context. – RonaldMunodawafa Jun 19 '16 at 22:18
  • 1
    The answer is a simple `N`, if the allocation was successful. That is *all* that is known about the size of the allocation. – Weather Vane Jun 19 '16 at 22:22
0

malloc is allocating a right size array, else your test is wrong.

sizeof(E) is the size of the pointer = 8

sizeof(*E) is the size of the first double = 8

you can know the size of your array multiplying sizeof(*E) * N

danilonet
  • 1,757
  • 16
  • 33
0

To put another spin on this explanation, if sizeof(E) worked as you expected (giving the size of the allocated memory, rather than the size of the pointer) then you could use that to get the size of dynamically allocated arrays. You can't do that in C.

Schwern
  • 153,029
  • 25
  • 195
  • 336