Size of dynamic array in C doesn't change - c

I was getting realloc(): invalid next size for a program. So I just coded this to understand what's happening.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *inp;
printf("%lu ",sizeof(inp));
char *res = (char*)malloc(15*sizeof(char*));
printf("%lu ",sizeof(res));
res = "hello world";
printf("%lu\n",sizeof(res));
return 0;
}
And surprisingly it outputs 8 8 8. Can anyone explain why is it like that? Why is it 8 by default? And how malloc() effects size of inp?

sizeof(inp) gives you the size of pointer (8 bytes, 64-bits), not the storage under that pointer.

You are using sizeof.returns size in bytes of the object representation of type. Remember sizeof is an operator.
Now sizeof is returning here 8 a constant type of size_t
Why isn't it changing? because in all tha cases you are using the same type that is char *.
Here 8 bytes is the size of the character pointer that is 64 bit.
You can probably have a look at this-
printf("size of array of 10 int: %d\n" sizeof(int[10]));
This will give the output:40. 40 bytes.
And malloc will never affect the size of a char*. It still needs 64 bits to store an address of a dynamically allocated space from heap.
Is it possible to determine size of dynamically allocated memory in c?
There is no standard way to do this. You have to take this overhead on your own. You may find some extensions to the compiler that may accomplish this.

sizeof(inp) in your case is sizeof(pointer) and hence sizeof(char-pointer) on your system is 8 bytes which is a constant. While allocating memory using malloc() you would have specified the size so why do you need to get the size of the allocated space again?
And I see res is being initialized and not inp

****EDIT**** : The below post was written before the edit of the question.
You're missing stdlib.h, to the most, for function malloc() to work properly. After that,
Point 1:
char *res = (char*)malloc(15*sizeof(char*));
should be
char *res = malloc(15); //will also issue warning to resolve missing stdlib.h
Point no note: you should be allocating memory for chars, not char *s. Then , you should write sizeof(char), not sizeof(char *). Also, sizeof(char) is always 1 in C. So, can omit that part.
Please read: do not cast the return value of malloc() and family in C.
Point 2:
strings are not supposed to be assigned to already malloc()ed pointers. use strcpy() instead.
inp = "hello world";
should be
strcpy(inp, "hello world");
Otherwise, you'll overwrite the previously allocated memory, returned by malloc(). The assignment will overwrite the memory location held by inp, causing memory leak.
Point 3.
sizeof() operator returns a value of size_t. To print that, you need %zu format specifier.
Related, from C11 standard document, chapter §7.21.6.1, paragraph 7,
z
Specifies that a following d, i, o, u, x, or X conversion specifier applies to a
size_t or the corresponding signed integer type argument; or that a
following n conversion specifier applies to a pointer to a signed integer type
corresponding to size_t argument.
Then, to answer the query about the output, in all the cases, you're printing sizeof(inp) which is essentially sizeof(char *) and that value is fixed for a particular platform (8, in your case).
Just FYI, sizeof() is an operator, it's not a function. It returns the size of the datatype, not the amount of space pointed by the variable.

Related

inserting elements to a dynamically allocated array [duplicate]

I was getting realloc(): invalid next size for a program. So I just coded this to understand what's happening.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *inp;
printf("%lu ",sizeof(inp));
char *res = (char*)malloc(15*sizeof(char*));
printf("%lu ",sizeof(res));
res = "hello world";
printf("%lu\n",sizeof(res));
return 0;
}
And surprisingly it outputs 8 8 8. Can anyone explain why is it like that? Why is it 8 by default? And how malloc() effects size of inp?
sizeof(inp) gives you the size of pointer (8 bytes, 64-bits), not the storage under that pointer.
You are using sizeof.returns size in bytes of the object representation of type. Remember sizeof is an operator.
Now sizeof is returning here 8 a constant type of size_t
Why isn't it changing? because in all tha cases you are using the same type that is char *.
Here 8 bytes is the size of the character pointer that is 64 bit.
You can probably have a look at this-
printf("size of array of 10 int: %d\n" sizeof(int[10]));
This will give the output:40. 40 bytes.
And malloc will never affect the size of a char*. It still needs 64 bits to store an address of a dynamically allocated space from heap.
Is it possible to determine size of dynamically allocated memory in c?
There is no standard way to do this. You have to take this overhead on your own. You may find some extensions to the compiler that may accomplish this.
sizeof(inp) in your case is sizeof(pointer) and hence sizeof(char-pointer) on your system is 8 bytes which is a constant. While allocating memory using malloc() you would have specified the size so why do you need to get the size of the allocated space again?
And I see res is being initialized and not inp
****EDIT**** : The below post was written before the edit of the question.
You're missing stdlib.h, to the most, for function malloc() to work properly. After that,
Point 1:
char *res = (char*)malloc(15*sizeof(char*));
should be
char *res = malloc(15); //will also issue warning to resolve missing stdlib.h
Point no note: you should be allocating memory for chars, not char *s. Then , you should write sizeof(char), not sizeof(char *). Also, sizeof(char) is always 1 in C. So, can omit that part.
Please read: do not cast the return value of malloc() and family in C.
Point 2:
strings are not supposed to be assigned to already malloc()ed pointers. use strcpy() instead.
inp = "hello world";
should be
strcpy(inp, "hello world");
Otherwise, you'll overwrite the previously allocated memory, returned by malloc(). The assignment will overwrite the memory location held by inp, causing memory leak.
Point 3.
sizeof() operator returns a value of size_t. To print that, you need %zu format specifier.
Related, from C11 standard document, chapter §7.21.6.1, paragraph 7,
z
Specifies that a following d, i, o, u, x, or X conversion specifier applies to a
size_t or the corresponding signed integer type argument; or that a
following n conversion specifier applies to a pointer to a signed integer type
corresponding to size_t argument.
Then, to answer the query about the output, in all the cases, you're printing sizeof(inp) which is essentially sizeof(char *) and that value is fixed for a particular platform (8, in your case).
Just FYI, sizeof() is an operator, it's not a function. It returns the size of the datatype, not the amount of space pointed by the variable.

Should I change the pointer to an array?

for (int a=0; a<10; ++a) {
printf ("%d", a);
}
char *foo;
foo = (char*)malloc(a);
I want to store more than one char value in foo variable.
Should I change it to an array, since the buffer is only allocating 1 char length?
Is 1 the longest length that can be stored in this buffer?
Well, foo now points to some useable address of a bytes, because this is how malloc() works. It doesn't matter if its type is char *, void * or anything else, you can only use a bytes.
Here, you increment a to 10. That means you can store 10 bytes, being 10 chars, (because in the context of C, 1 char = 1 byte), starting at the address where foo points to. Using a pointer or an array is strictly equivalent.
Since the buffer is only allocating 1 char length...
No, it is not the case here.
Quoting from the C11 standard, chapter §7.22.3.4, The malloc function
void *malloc(size_t size);
The malloc function allocates space for an object whose size is specified by size and
whose value is indeterminate.
So, in case of
foo = malloc(a); //yes, the cast is not required
a memory of size same as the value of a will be allocated, considering malloc() is successful.
Simply put, if I write a snippet like
int * p = malloc(10 * sizeof*p);
then, I can also write
for (int i = 0; i < 10, i++)
p[i] = i;
because, I have allocated the required memory for 10 ints.
That said, please see this discussion on why not to cast the return value of malloc() and family in C..
There are a couple of things you could do in a case like this.
If you know at compile time how many chars you want to store you could make it an array char foo[10]; If you know that there is always going to be 10 (or less) characters you want to store.
If you are not sure how many chars it needs to hold at compile time you would typically do dynamic allocation of memory using malloc. Now when using malloc you specify how many bytes of memory you want so for 12 chars you would do malloc(12) or malloc(12 * sizeof(char)). When using malloc you need to manually free the memory when you are done using it so the benefit of being able to ask for arbitrary (within limits) sizes of memory comes at the cost of making memory management harder.
As a side note: You typically do not want to cast the return value of malloc since it can hide some types of bugs and void *, that malloc returns can be implicitly cast to any pointer type anyway.

Size of pointer, pointer to pointer in C

How can I justify the output of the below C program?
#include <stdio.h>
char *c[] = {"Mahesh", "Ganesh", "999", "333"};
char *a;
char **cp[] = {c+3, c+2, c+1, c};
char ***cpp = cp;
int main(void) {
printf("%d %d %d %d ",sizeof(a),sizeof(c),sizeof(cp),sizeof(cpp));
return 0;
}
Prints
4 16 16 4
Why?
Here is the ideone link if you want to fiddle with it.
char *c[] = {"Mahesh", "Ganesh", "999", "333"};
c is an array of char* pointers. The initializer gives it a length of 4 elements, so it's of type char *[4]. The size of that type, and therefore of c, is 4 * sizeof (char*).
char *a;
a is a pointer of type char*.
char **cp[] = {c+3, c+2, c+1, c};
cp is an array of char** pointers. The initializer has 4 elements, so it's of type char **[4]. It size is 4 * sizeof (char**).
char ***cpp = cp;
cpp is a pointer to pointer to pointer to char, or char***. Its size is sizeof (char***).
Your code uses %d to print the size values. This is incorrect -- but it happens to work on your system. Probably int and size_t are the same size. To print a size_t value correctly, use %zu -- or, if the value isn't very large, you can cast it to int and use %d. (The %zu format was introduced in C99; there might still be some implementations that don't support it.)
The particular sizes you get:
sizeof a == 4
sizeof c == 16
sizeof cp == 16
sizeof cpp == 4
are specific to your system. Apparently your system uses 4-byte pointers. Other systems may have pointers of different sizes; 8 bytes is common. Almost all systems use the same size for all pointer types, but that's not guaranteed; it's possible, for example, for char* to be larger than char***. (Some systems might require more information to specify a byte location in memory than a word location.)
(You'll note that I omitted the parentheses on the sizeof expressions. That's legal because sizeof is an operator, not a function; its operand is either an expression (which may or may not be parenthesized) or a type name in parentheses, like sizeof (char*).)
a is an usually pointer, which represents the memory address. On 32-bit operating system, 32bit (4 Byte) unsigned integer is used to represent the address. Therefore, sizeof(a) is 4.
c is an array with 4 element, each element is a pointer, its size is 4*4 = 16
cp is also an array, each element is a pointer (the first *, wich point to another pointer (the second *). The later pointer points to an string in the memory. Therefore its basic element size should represent the size of a pointer. and then sizeof(cp) = 4*4 = 16.
cpp is a pointer's pointer's pointer. It is as well represent the 32bit memory address. therefore its sizeof is also 4.
a is a pointer. cpp is also a pointer just to different type (pointer to pointer to pointer).
Now c is an array. You have 4 elements, each is a pointer so you have 4 * 4 = 16 (it would be different if you would run it on x64).
Similar goes for cp. Try changing type to int and you will see the difference.
So the reason you got 4 16 16 4, is because 'a' is simply a pointer, on its own, which only requires 4 bytes (as a pointer is holding a 32bit address depending on your architecture) and so when you have a **pointer which is == to a *pointer[], your really making an array of pointers, and since you initalized 4 things that created 4 pointers, thus the 4x4 = 16. And for the cpp you may ask "well wouldn't it then be 16 as it was initalized?" and the answer is no, because a ***pointer is its own separate variable and still just a pointer(a pointer to a pointer to a pointer, or a pointer to an array of pointers), and requires only 4bytes of memory.

Getting array size in C. Cannot understand output

I am curious why I am getting the following behaviour in my code.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int M=24;
int arr[M];
int N=24;
int* ptr=(int*) malloc(sizeof(int)*N); /*Allocate memory of size N */
printf("Size of your malloced array is %lu\n",sizeof(ptr)/sizeof(ptr[0])); /* Get the size of memory alloctaed. Should be the same as N?*/
printf ("Size of your normal arrays is %lu\n",sizeof(arr)/sizeof(arr[0])); /* Ditto */
free(ptr);
return 0;
}
The output is
Size of your malloced array is 2
Size of your normal arrays is 24
I would have thought the output would be 24 in both places. How then does one get the size of the malloced array If somehow I have "forgotten" it?
Surely the pointer ptr will contain some information about the size of the malloced array since when we call free(ptr) it will release the array just malloced
When you use sizeof() on a pointer, you get the size of the pointer. Not the size of the allocated array. In your case, a pointer is probably 8 bytes and an int is 4 bytes, hence why you get 2.
In short, you can't get the size of an allocated array. You need to keep track of it yourself.
EDIT : Note that some compilers do actually support this functionality as an extension:
For example, MSVC supports _msize(): http://msdn.microsoft.com/en-us/library/z2s077bc.aspx
While sizeof() works as you'd expect with fixed-length and variable-length arrays, it doesn't know anything about the sizes of malloc()'ed arrays.
When applied to a pointer, sizeof() simply returns the size of the pointer.
More generally, given a pointer to a malloc()'ed block, there's no standard way to discover the size of that block.
See C FAQ questions 7.27 and 7.28.
In summary, if you need to know the size of a heap-allocated array in a portable manner, you have to keep track of that size yourself.
You cannot obtain, at runtime, the size of an array if you only have a pointer to (the first element of) the array. There are no constructs at all in C that allow you to do this. You have to keep track of the length yourself.
If you happen to have an array rather than a pointer then you can find its length, but not for a pointer to an element of the array.
In your code, ptr is a pointer and so you cannot find out the length of the array to which it points. On the other hand, arr is an array and so you can find out its length with sizeof(arr)/sizeof(arr[0]).
As this other question points out, there is no portable way getting the size of a dynamic array, since malloc may allocate more memory than requested. Furthermore managing malloc requests is up to the operating system. For instance *nix would calls sbrkand store the requests somewhere. So, when you call sizeof(ptr) it returns the size of the pointer and not the size of the array. On the other hand, if your array is fixed, the size of it is determined at compile time, so the compiler is able to replace sizeof(arr) with the size of the fixed array, thus providing you the "correct" size.
The size of a pointer is 4 bytes on 32-bit machines and 8 bytes on 64-bit machines. I guess you work on a 64-bit machine since the size of an int is 4, and you got that sizeof(ptr)/sizeof(ptr[0]) is 2.
The thing to remember about sizeof is that it is a compile-time operator1; it returns the number of bytes based on the type of the operand.
The type of arr is int [24], so sizeof arr will evaluate to the number of bytes required to store 24 int values. The type of ptr is int *, so sizeof ptr will evaluate to the number of bytes required to store a single int * value. Since this happens at compile time, there's no way for sizeof to know what block of memory ptr is pointing to or how large it is.
In general, you cannot determine how large a chunk of memory a pointer points to based on the pointer value itself; that information must be tracked separately.
Stylistic nit: a preferred way to write the malloc call is
int *ptr = malloc(sizeof *ptr * N);
In C, you do not need to cast the result of malloc to the target pointer type2, and doing so can potentially mask a useful diagnostic if you forget to include stdlib.h or otherwise don't have a prototype for malloc in scope.
Secondly, notice that I pass the expression *ptr as the operand to sizeof rather than (int). This minimizes bugs in the event you change the type of ptr but forget to change the type in the corresponding malloc call. This works because sizeof doesn't attempt to evaluate the operand (meaning it doesn't attempt to dereference ptr); it only computes its type.
1 The exception to this rule occurs when sizeof is applied to a variable-length array; since the size of the array isn't determined until runtime, a sizeof operator applied to a VLA will be evaluated at runtime.
2 Note that this is not the case in C++; a cast is required, but if you're writing C++ you should be using new and delete instead of malloc and free anyway. Also, this is only true since C89; older versions of C had malloc return char * instead of void *, so for those versions the cast was required. Unless you are working on a very old implementation (such as an old VAX mini running an ancient version of VMS), this shouldn't be an issue.

Is this possible? [pointer to char array C]

Is this possible?
size_t calculate(char *s)
{
// I would like to return 64
}
int main()
{
char s[64];
printf("%d", calculate(s));
return 0;
}
I want to write a function which calculates the size of the char array declared in main().
Your function calculate(), given just the pointer argument s, cannot calculate how big the array is. The size of the array is not encoded in the pointer, or accessible from the pointer. If it is designed to take a null-terminated string as an argument, it can determine how long that string is; that's what strlen() does, of course. But if it wants to know how much information it can safely copy into the array, it has to be told how big the array is, or make an assumption that there is enough space.
As others have pointed out, the sizeof() operator can be used in the function where the array definition is visible to get the size of the array. But in a function that cannot see the definition of the array you cannot usefully apply the sizeof() operator. If the array was a global variable whose definition (not declaration) was in scope (visible) where calculate() was written - and not, therefore, the parameter to the function - then calculate() could indicate the size.
This is why many, many C functions take a pointer and a length. The absence of the information is why C is somewhat prone to people misusing it and producing 'buffer overflow' bugs, where the code tries to fit a gallon of information into a pint pot.
On statically declared char[] you can use operator sizeof, which will return 64 in this case.
printf("%d", sizeof(s));
On dynamically declared char*, it is not possible to get the size of the allocated memory.
Dynamic arrays are obtained through malloc and friends. All the others are statically declared, and you can use sizeof on them, as long as you use it in the same scope as the array was declared (same function, in your case, for example).
Yes, it's possible if s has a specific character in the end of it's array. For example you could have s[63] = 125 and by knowing that every other character from 0 to 62 won't be 125, you can do a for loop until you find 125 and return the size of the array.
Otherwise, it's not possible, as s in the function parameter is just a pointer to your array, so sizeof(s) inside calculate will only return your machines pointer size and not 64 as someone could expected.
Unfortunately, you cannot determine from a pointer value alone how many elements are in the corresponding array. You either need some sort of sentinel value in the array (like the 0 terminator used for strings), or you need to keep track of it separately.
What you can do is get the number of bytes or elements in an array using the sizeof operator:
char arr[64];
size_t size = sizeof arr; // # of bytes in arr
size_t count = sizeof arr / sizeof *arr; // # of elements in arr
However, this only works if arr is an array type; if you tried to do this in your function
size_t calculate(char *s)
{
return sizeof s;
}
it would return the size in bytes of the pointer value, not of the corresponding array object.
No. char *x or char x[] just creates a pointer to a memory location. A pointer doesn't hold any information about the size of the memory region.
However, char *x = "Hello" occupies 6 bytes (including the terminating null), and strlen(x) would return 5. This relies on the null char at the end of the string, strlen still knows nothing about the underlying buffer. So strlen("Hello\000There") would still be 5.
This is usually done with a macro in C, like:
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
Whether it's a good idea is a totally different question.

Resources