Understanding declarations, malloc, and other parts of this line of C code - c

I just started working with C and came across a line of code I don't understand. Could someone explain what it does?
short int * work = (short int *) malloc(1000*16);

What don't you understand exactly? The code declares a short int* which is a pointer to one or more 16 bit (at least 16 bit) signed integers. It initializes it to a pointer returned by malloc, which is a chunk of memory large enough to fit 1000 * 16 bytes.
Now, why did they use 1000 * 16? I don't know. Typically you would allocate along the lines of num_elements * sizeof(element), i.e., num_elements * sizeof(short int).
More canonically, use num_elements * sizeof(*work) so that your code doesn't break if you change the type of the pointer.
Also note that it is a bad idea to cast the return value of malloc in C.

Let's break it down:
short int * work
This declares a pointer to an int, called work. It's declared as a short int, which means that it must be:
at least 16 bits in length (or two 8 bit bytes), and
not bigger than a plain int.
Generally, shorts are used when an int may be too large. Wikipedia has an excellent breakdown of C data types here: http://en.wikipedia.org/wiki/C_data_types
= (short int *) malloc(1000*16);
This allocates 1000*16 bytes, and assigns it to the pointer. You can read more about malloc() in the malloc() man page. This particular line is an example of bad style because:
It's unnecessary to cast the result of malloc - see Do I cast the result of malloc?
Because the size of a short int isn't defined in a standard, this line isn't guaranteed to produce any particular number of short ints.
It would be better to instead write:
short int * work = malloc(sizeof(short int) * NUMBER_OF_SHORT_INTS_REQUIRED);
or, even better:
short int * work = malloc(sizeof(work[0]) * NUMBER_OF_SHORT_INTS_REQUIRED);
Remember to check to make sure that malloc hasn't returned NULL before doing anything with work.

You are reserving (dynamically = on run-time) 1000 * 16 = 16000 bytes by using malloc. Using malloc what you get is a pointer to the address of the first byte of the 16000 bytes that have been reserved. You store the result to the pointer that you have for short integers named "work". Typically, every short integer has size 2 bytes, so, essentially malloc has reserved space for 8000 short integers (assuming it succeeded).
If malloc failed to allocate the space, it returns NULL.
Finally, it is bad practice to cast what malloc has returned.

Saw "declarations" in your title.
They have a very good web site for complex declarations. here

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.

What is the sizeof(1), and does it differ from 1?

Correct me if I am wrong but does
malloc(1) // Mallocing 1 which is a int
equal
malloc( sizeof(1) )
void* malloc(size_t) returns a pointer, and the memory after the pointer has been allocated with size equal to the argument fed into malloc. In your case, malloc(1) simply allocates a single byte, while malloc(sizeof(int)) allocates 2 or 4 bytes.
malloc(sizeof(1)) and malloc(sizeof(int)) are equivalent statements but the latter is more apparent. Hence malloc(1) is not equivalent to malloc(sizeof(1)) as sizeof(1) == 4. (Or sometimes 2, 8)
The size of an integer constant depends on the value of the constant and on a possible suffix. Integer constants are at least of the type int if it fits in an int, if the value of the constant is larger and don't fit in an int then long or long long are used. The constant 1 is small enough to fit in an int so sizeof(1) == sizeof(int) is true.
However, malloc( sizeof(1) ) == malloc( sizeof(int) ) will not be true, since you allocate two different memory areas and each call will return different pointers. The sizes of those memory areas will be the same, but not the pointers returned by malloc. The exception being if both malloc calls fail and return NULL.
I know that you probably don't mean the comparison of the malloc calls literally, but in programming such things are important to spell out. Semantics is very important.
As for the question in your title, malloc(1) returns a pointer to one single byte.
Also be careful with assuming sizes, because sizeof(int) may actually not be four bytes. On small embedded platforms (or very old systems) it could be two bytes. And on future systems it might be eight or even more.
You might want to read e.g. this malloc reference where it says that the argument is the number of bytes to allocate.
Integer constants such as 1 have their own type just as variables do. In this case int.
Meaning that sizeof(1) is equivalent to sizeof(int).
So malloc(1) means "allocate 1 bytes", while malloc(sizeof(1)) means allocate as many bytes as the size of an int.

Size of dynamic array in C doesn't change

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.

C memory allocating - char* and char sizeof

What form is correct in allocating string in C?
char *sample;
sample = malloc ( length * sizeof(char) );
or
sample = malloc ( length * sizeof(char*) );
Why does char* take 4 bytes when char takes 1 byte?
Assuming the goal is to store a string of length characters, the correct allocation is:
sample = malloc(length + 1);
Notes:
Don't use sizeof (char), since it's always 1 it doesn't add any value.
Remember the terminator, I assumed (based on name) that length is the length in visible characters of the string, i.e. the return of strlen() will be length.
I know you didn't, but it's worth pointing out that there should be no cast of the return value from malloc(), either.
The reason char * is larger is that it's a pointer type, and pointers are almost always larger than a single character. On many systems (such as yours, it seems) they are 32 bit, while characters are just 8 bits. The larger size is needed since the pointer needs to be able to represent any address in the machine's memory. On 64-bit computers, pointers are often 64 bits, i.e. 8 characters.
Why does char* take 4 bytes when char takes 1 byte?
Because you are on a 32-bit systems, meaning that pointers take four bytes; char* is a pointer.
char always takes exactly one byte, so you do not need to multiply by sizeof(char):
sample = malloc (length);
I am assuming that length is already padded for null termination.
sample = malloc ( length * sizeof(char) );
First is the correct one if you want to allocate memory for length number of characters.
char* is of type pointer which happens to be 4 bytes on your platform. So sizeof(char*) returns 4.
But sizeof(char) is always 1 and smae is guaranteed by the C standard.
In the given cases you are doing two different things:
In the first case : sample = malloc ( length * sizeof(char) );
You are allocating length multiplied by the size of type char which is 1 byte
While in the second case : sample = malloc ( length * sizeof(char*) );
You are allocating length multiplied by the size of pointer to char which is 4 byte
on your machine.
Consider that while case 1 remains immutable, on the second case the size is variable.
sample = malloc(length);
is the right one
char* is a pointer, a pointer uses 4 bytes (say on a 32-bit platform)
char is a char, a char uses 1 byte
In your case, you want to alloc an array of length characters. You will store in sample a pointer to an array of length times the size of what you point to. The sizeof(char*) is the size of a pointer to char. Not the size of a char.
A good practice is
sample = malloc(length * sizeof(*sample));
Using that, you will reserve length time the size of what you want to point to. This gives you the ability to change the data type anytime, simply declaring sample to be another kind of data.
int *sample;
sample = malloc(length * sizeof(*sample)); // length * 4
char *sample;
sample = malloc(length * sizeof(*sample)); // length * 1
Provided the length already accounts for the nul terminator, I would write either:
sample = malloc(length);
or:
sample = malloc(length * sizeof(*sample));
sizeof(char*) is the size of the pointer, and it is completely irrelevant to the the size that the allocated buffer needs to be. So definitely don't use that.
My first snippet is IMO good enough for string-manipulation code. C programmers know that memory and string lengths in C are both measured in multiples of sizeof(char). There's no real need to put a conversion factor in there that everybody knows is always 1.
My second snippet is the One True Way to write allocations in general. So if you want all your allocations to look consistent, then string allocations should use it too. I can think of two possible reasons to make all your allocations look consistent (both fairly weak IMO, but not actually wrong):
some people will find it easier to read them that way, only one visual pattern to recognise.
you might want to use the code in future as the basis for code that handles wide strings, and a consistent form would remind you to get the allocation right when the length is no longer measured in bytes but in wide chars. Using sizeof(*sample) as the consistent form means you don't need to change that line of code at all, assuming that you update the type of sample at the same time as the units in which length is measured.
Other options include:
sample = calloc(length, 1);
sample = calloc(length, sizeof(char));
sample = calloc(length, sizeof(*sample));
They're probably fairly pointless here, but as well as the trifling secondary effect of zeroing the memory, calloc has an interesting difference from malloc that it explicitly separates the number and size of objects that you're planning to use, whereas malloc just wants the total size.
For any type T, the usual form is
T *p = malloc(N * sizeof *p);
or
T *p;
...
p = malloc(N * sizeof *p);
where N is the number of elements of type T you wish to allocate. The expression *p has type T, so sizeof *p is equivalent to sizeof (T).
Note that sizeof is an operator like & or *, not a library function; parentheses are only necessary if the operand is a type name like int or char *.
Please visit this Linkhttps://www.codesdope.com/c-dynamic-memory/for understand how it allocat the memory dynamically at run time. It might be helpful to understand the concept of malloc and how it allocate the amount of memory to the variable.
In your example;
char *sample;
sample = malloc ( length * sizeof(char) );
here, you are declare a pointer to character for sample without declaring how much memory it required. In the next line, length * sizeof(char) bytes memory is assigned for the address of sample and (char*) is to typecast the pointer returned by the malloc to character.

Memory Allocation Problem

This question was asked in the written round of a job interview:
#include<alloc.h>
#define MAXROW 3
#define MAXCOL 4
main()
{
int (*p)[MAXCOL];
p = (int (*)[MAXCOL]) malloc(MAXROW*(sizeof(*p)));
}
How many bytes are allocated in the process?
To be honest, I did not answer the question. I did not understand the assignment to p.
Can anybody explain me what would be the answer and how it can be deduced?
It's platform dependent.
int (*p)[MAXCOL]; declares an pointer to an array of integers MAXCOL elements wide (MAXCOL of course is 4 in this case). One element of this pointer is therefore 4*sizeof(int) on the target platform.
The malloc statement allocates a memory buffer MAXROW times the size of the type contained in P. Therefore, in total, MAXROW*MAXCOL integers are allocated. The actual number of bytes will depend on the target platform.
Also, there's probably additional memory used by the C runtime (as internal bookeeping in malloc, as well as the various process initialization bits which happen before main is called), which is also completely platform dependant.
p is a pointer to an array of MAXCOL elements of type int, so sizeof *p (parentheses were redundant) is the size of such an array, i.e. MAXCOL*sizeof(int).
The cast on the return value of malloc is unnecessary, ugly, and considered harmful. In this case it hides a serious bug: due to missing prototype, malloc is assumed implicitly to return int, which is incompatible with its correct return type (void *), thus resulting in undefined behavior.
sizeof(*p) will be MAXCOL*sizeof(int). So totally MAXROW*MAXCOL*sizeof(int) number of bytes are alloctaed.
You might want to check out cdecl for help translating C declarations into English. In this instance, int (*p)[4]; becomes declare p as pointer to array 4 of int.
#include<alloc.h>
#define MAXROW 3
#define MAXCOL 4
main() {
int (*p)[MAXCOL];
p = (int (*)[MAXCOL]) malloc(MAXROW*(sizeof(*p));
}
How many bytes are allocated in the process ?
p is a pointer, so will occupy sizeof(int(*)[MAXCOL]) on the stack, which might look daunting but it's almost always the same as sizeof(void*), sizeof(int*) or any other pointer. Obviously pointer sizes are what give applications their classification as 16-, 32-, 64-etc. bits, and this pointer will be correspondingly sized.
Then p is pointed at some memory obtained from malloc...
malloc( MAXROW * sizeof(*p) )
sizeof(*p) is the size of the int array that p points to, namely sizeof(int) * MAXCOL, so we get
malloc( MAXROW * (sizeof(int) * MAXCOL) )
requested from the heap. For illustrative purposes, if we assume the common 32-bit int size, we're looking at 48 bytes. The actual usage may be rounded up to whatever the heap routines feel like (heap routines often used fixed-sized "buckets" to speed their operations).
To confirm this expectation, simply substitute a logging function for malloc():
#include <stdio.h>
#define MAXROW 3
#define MAXCOL 4
void* our_malloc(size_t n)
{
printf("malloc(%ld)\n", n);
return 0;
}
int main()
{
int (*p)[MAXCOL];
p = (int (*)[MAXCOL]) our_malloc(MAXROW*(sizeof(*p)));
}
Output on my Linux box:
malloc(48)
The fact that malloc's returned pointer is cast to p's type doesn't affect the amount of memory allocation done.
As R sharply observes, lack of a malloc prototype would cause the compiler to expect malloc to return int rather than the actually-returned void*. In practice, it's probable that the lowest sizeof(int) bytes from the pointer would survive the conversion, and if sizeof(void*) happened to be equal to sizeof(int), or - more tenuous yet - the heap memory happens to start at an address representable in an int despite the size of pointers being larger (i.e. all the truncated bits were 0s anyway), then later dereferencing of the pointer just might work. Cheap plug: C++ won't compile unless it's seen the prototype.
That said, perhaps your alloc.h contains a malloc prototype... I don't have an alloc.h so I guess it's non-Standard.
Any program will also allocate memory for many other things, such as a stack frame providing some context within which main() may be called. The amount of memory for that varies with the compiler, version, compiler flags, operating system etc..
int (*p)[MAXCOL] == int (*p)[4] == "pointer to array 4 of int" (see Note below)
sizeof(*p) would then be what p points to, i.e. 4 * sizeof(int). Multiply that by MAXROW and your final answer is:
12 * sizeof(int)
Note: This is in contrast to:
int *p[MAXCOL] == int *p[4] == "array 4 of pointer to int"
The parentheses make quite a bit of difference!
It should be MAXROW*MAXCOL*sizeof(int) number of bytes
I really dislike questions like this, because I think it's far better as a working engineer to run the experiment than to assume that you know what you are doing - especially if there's reason for suspicion such as a program not working as expected or someone crafting trick questions.
#include <stdlib.h>
#include <stdio.h>
#define MAXROW 3
#define MAXCOL 4
main()
{
int (*p)[MAXCOL];
int bytes = MAXROW * (sizeof(*p));
p = (int (*)[MAXCOL]) malloc(bytes);
printf("malloc called for %d bytes\n", bytes);
}
On a 32 bit linux system:
gcc test.c
./a.out
malloc called for 48 bytes
(edited to remove pasting accident of multiplying by maxrow twice, yielding mistaken size of 144 bytes)
Running the following in codepad.org:
//#include<alloc.h>
#define MAXROW 3
#define MAXCOL 4
int main()
{
int (*p)[MAXCOL];
p = (int (*)[MAXCOL]) malloc(MAXROW*(sizeof(*p)));
int x = MAXROW*(sizeof(*p));
printf("%d", x);
return 0;
}
prints out 48.
Why? Because MAXROW is 3, and sizeof(*p) is 16, so we get 3 * 16.
Why is sizeof(*p) 16? Because MAXCOL is 4, so p is a pointer to an array of 4 ints. Each int is 32 bits = 4 bytes. 4 ints in the array * 4 bytes = 16.
Why is sizeof(*p) not 4? Because it is the size of what p points to, not the size of p. To be the size of p it would have to be sizeof(p), which would be 4, as p is a pointer.
Pedantically you could add:
If the machine is 64 bit (say) the answer would be 96.
As the question states "How many bytes are allocated in the process?", you need to add the 4 bytes for the pointer p.
malloc can allocate more than you ask for (but not less) so the question cannot be answered.
In a similar vein as 2, you could argue that as the process is also loading system dlls such as the C runtime dll in order to run, it is allocating the space for those too. Then you could argue for the space allocated by dlls that are being injected into the process by other (non system) processes, such as those injected by Actual Window Manager and its ilk. But how pedantic do we want to get?
But I think the question is really asking for 48, with possible extra credit for explaining 96.
How about zero bytes because that won't even compile without the non-standard alloc.h. If you can't compile it, you can't run it and if you can't run it, it can't allocate any memory at all.

Resources