1

size of allocated memory

int main() {

    char *aPtr[10];

    aPtr[0] = (char *)malloc(20 * sizeof(char));

    aPtr[0] = "This is a test";

    aPtr[1] = (char *)malloc(20 * sizeof(char));

    aPtr[1] = "This is a test2";

    printf("%s\n%s\n", aPtr[0], aPtr[1]);

    printf("%d", sizeof(aPtr[0]));
}

In this case why the size of the aPtr[0] is showing 4 bytes instead of showing 20 bytes. I don't understand why it is happening.

chqrlie
  • 131,814
  • 10
  • 121
  • 189

3 Answers3

4

aPtr is an array of pointers to char. So each element of aPtr is a single pointer to char, or char *. In particular, aPtr[0] is a char *. So sizeof(aPtr[0]) gives you the size of that pointer. On many machines (on "32 bit machines"), the size of a pointer is 32 bits, or 4 bytes.

Based on your question, it sounds like you're interested in the size of the data the pointer points to. That's completely different. (Again, realize carefully the distinction we're making between the pointer and the pointed-to data.) And in this case, finding the size of the pointed-to data can be tricky, and it turns out it probably won't involve the sizeof operator at all.

If you want to find out the size of a malloc'ed block of memory, it turns out there's no portable way to do that. That is, after you say p = malloc(20), there's no way to ask "Hey, malloc. That pointer you gave me, that I asked you to allocate some memory for, how much memory did I ask you to allocate, again? I forget." If you need to know how much memory your malloc'ed pointers point to, you have to remember it somehow.

If you want to find out how long a string is, on the other hand, that's simple: just call strlen. For example, a reasonable fix to your program is to have the last line be

printf("%d", strlen(aPtr[0]));

Actually, since strlen (like sizeof) returns a special type called size_t that might be bigger than an int, the more portable way to write this would be

printf("%zu", strlen(aPtr[0]));

or

printf("%d", (int)strlen(aPtr[0]));

But going back to your original program, there's another misunderstanding we should talk about. You said

aPtr[0] = (char *)malloc(20*sizeof(char));
aPtr[0] = "This is a test";

Now, I know you've been taught that memory allocation is important, and that's true, but in this case, it turns out you're allocating 20 bytes of memory and then throwing it away. Look closely: malloc returns a pointer value (pointing to the newly-allocated memory), and you assign it to (you store the value in) aPtr[0]. But then, in the very next line, you assign aPtr[0] to a different pointer, pointing to the statically-allocated string "This is a test". The previous value, the one returned by malloc, is lost.

What you probably meant to write here was

aPtr[0] = malloc(20);
strcpy(aPtr[0], "This is a test");

Now we're doing something completely different with that string constant "This is a test". Instead of simply assigning a pointer to it, we're copying the while string (actually the library function strcpy is copying the whole string) byte-by-byte into the pointer pointed to by aPtr[0], that is, the pointer you just got back from malloc. (In this latest example I have also dropped the unnecessary cast of malloc's return value to (char *), and the unnecessary multiplication by sizeof(char *).)

Notice that in this case (now that you're actually using the malloc'ed memory), the size of the malloc'ed memory matters. If you had said

aPtr[0] = malloc(10);
strcpy(aPtr[0], "This is a test");

then you'd have a big problem.

Finally, there's one other answer to the question, "How big is the string?", although it's not usually too useful, and it's certainly not useful in this case. But if you want to you can write

printf("%zu\n", sizeof("This is a test"));

and this will print 15. (It prints one more than what you thought the string length was, because the count of the size of the string constant includes the terminating \0 character.)

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
  • 1
    If you don't need the extra space at the end, `aPtr[0] = malloc(20); strcpy(aPtr[0], "This is a test");` can be replaced with `aPtr[0] = strdup("This is a test");`. – ikegami Jul 21 '19 at 12:42
1

You are having an array of char pointers. So the size of a pointer and size of what it's pointing to is different. Here you are printing the size of a pointer which is fixed i.e, for a 32-bit machine it's 4 bytes.

Abhinav Kinagi
  • 3,653
  • 2
  • 27
  • 43
  • "*the size of a pointer which is generally fixed*" just drop "generally". The `sizeof` a pointer variable/type "always" is fixed. – alk Jul 21 '19 at 12:05
  • @alk, Pointers are not always the same size on same machine. So I feel *"generally"* is right word here. You can refer [this article.](http://en.wikipedia.org/wiki/Intel_Memory_Model#Pointer_sizes) – Abhinav Kinagi Jul 21 '19 at 13:23
  • I did not say pointers were "*always the same size*", I just tried to point out that a pointer's size "is fixed", will say: does not change. – alk Jul 21 '19 at 14:04
1

why the size of the aPtr[0] is showing 4 bytes instead of` showing 20 bytes.

From the docs:

The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand.

In your case aPtr[0] is a pointer to char. Pointer types in your environment seem to be 4 bytes wide

In C there is no portable way to from a pointer derive the size of valid memory it is pointing to. See also this answer: Determine size of dynamically allocated memory in C

alk
  • 69,737
  • 10
  • 105
  • 255