This question already has answers here:
Using sizeof() on malloc'd memory [duplicate]
(5 answers)
Newbie questions about malloc and sizeof
(8 answers)
Closed 1 year ago.
I'm learning C dynamic memory allocation and can't figure out why malloc or calloc are not allocating the amount of memory specified for the struct array, nor for the name char array.
Code example:
struct spaceShip{
long long int distance; // 8 bytes
int numParts; // 4 bytes
char *name; // 1 byte
}; // 13 bytes total
int main (int argc, char *argv[]){
int amount=10;
struct spaceShip *spaceShipArray;
printf("size of struct spaceShip = %d bytes\n", sizeof(struct spaceShip));
spaceShipArray = malloc(amount * sizeof(*spaceShipArray));
printf("size of spaceShipArray = %d bytes\n", sizeof(*spaceShipArray));
spaceShipArray[0].name = malloc(100 * sizeof(char));
printf("size of name char array = %d \n", sizeof(spaceShipArray[0].name));
free(spaceShipArray);
return 0;
}
Output:
size of struct spaceShip = 16 bytes //I guess because of the pagination mechanism it takes more?
size of spaceShipArray = 16 bytes // not ok. should be 160
size of name char array = 4 // not ok. should be 100
For starters to output objects of the type size_t you have to use the conversion specifier %zu. For example
printf("size of struct spaceShip = %zu bytes\n", sizeof(struct spaceShip));
These two statements
printf("size of struct spaceShip = %zu bytes\n", sizeof(struct spaceShip));
printf("size of spaceShipArray = %zu bytes\n", sizeof(*spaceShipArray));
output the same value because the expression sizeof(*spaceShipArray) is equivalent to the expression sizeof(struct spaceShip).
That is dereferencing the pointer spaceShipArray gives an object of the type struct spaceShip. Pointers know nothing whether they point to a single object or a first element of an array.
If you want to output the size of the allocated memory then you should write for example
printf("size of spaceShipArray = %zu bytes\n", amount * sizeof(*spaceShipArray));
This statement
printf("size of name char array = %zu \n", sizeof(spaceShipArray[0].name));
outputs the size of a pointer of the type char * because it is the type of the expression spaceShipArray[0].name.
So the program output is correct.
Take into account that you forgot to free the memory allocated for a character array. For example
free( spaceShipArray[0].name );
free(spaceShipArray);
First output: char* uses 4 bytes on a old computer (32bit) or 8 bytes on a modern computer (64bit) because it is a pointer (not a single char).
Second output: it is correct because it's the size of a single element of the vector (16 byte)
Third output: it is correct because sizeof returns the size of the char pointer (4 bytes on a 32bit computer)
Related
I am trying to read in user input then parse it to tokens using strtok().
Here is my code:
int main(){
char argv[200];
char** tokenList = NULL;
printf("shell>>");
scanf("%[^\n]%*c", argv);
int len = 0;
char* line = strtok(argv, " ");
while (line != NULL) {
printf("%s\n", line);
printf("%lu\n", sizeof(tokenList) + (sizeof(char*) * (len+1)));
tokenList = realloc(tokenList, sizeof(tokenList) + (sizeof(char*) * (len+1)));
printf("%lu\n", sizeof(tokenList));
char* p = malloc(sizeof(char) * (sizeof(line) + 1));
p=line;
tokenList[len] = p;
len++;
line = strtok(NULL, " ");
}
The three print statements are for my debugging purposes and I cannot figure out what is going on. When I run the shell and enter "a b c" my output is the following:
a
16
8
b
24
8
c
32
8
Why is the size of my array tokenList not getting updated by the realloc call?
You are using sizeof operator on a pointer. This yields the size in bytes of the pointer, not of the length of data pointed to. It's easy to imagine why, since tokenList is just a variable that stores an address, you obtain the size of the variable, not of what the variable points to.
In C, arrays allocated on heap doesn't know their size, the developer must take care of knowing it and storing/updating it when necessary somewhere.
The only case in which you are allowed to use directly sizeof is when an array is declared with static or local storage (and not on heap). In this circumstance sizeof return the total length in bytes of the array, so that you can do sizeof(array) / sizeof(array[0]) to obtain the element count.
I was testing around with sprintf a bit to convert an int into a string/char and noticed something:
When I make a string like this
char *str = "anything";
no matter what I write in it, sizeof always returns a value of 8 byte.
But as far as I know, a char is ususally the size of 1 byte, so why doesn't the number of characters in the string/array change its size?
If I write
char str[15];
I get a size of 15 bytes, so why do I not get a size of 15 bytes if I type
char *str = "11111111111111\0"
but a size of 8 bytes?
Similar to this, if I type
char str[] = {"67"}
sizeof returns a value of 3 byte, which makes sense since it is 6, 7 and \0.
And then I write this
int aInt = 368;
sprintf(str, "%d", aInt);
to convert int aInt 368 into a string and write that string into str.
These are three char then, and therefor, sizeof should return a value of 4 byte, counting \0 in.
But it still returns 1, even through I wrote 3 chars.
Can anyone explain this to me, please?
This is the piece of code with which I've been testing this:
#include <stdio.h>
int main(int argc, char *arfv[])
{
int aInt = 368;
printf("value of aInt: %d\n", aInt);
char str[15];
//Other ways of creating a string/array which were tested:
//char *str = "anything";
//char str[] = {"67"};
//printf("value of str before: %s\n", str); //value of str before converting
printf("size of str before: %ld\n", sizeof(str)); //size of str before converting
sprintf(str, "%d", aInt); //convert aInt into a string
printf("value of str after: %s\n", str); //value of str after converting
printf("size of str after: %ld\n", sizeof(str)); //size of str after converting
return 0;
}
A char* is just a pointer to some memory, and has a size of whatever a pointer is on your architecture (8 bytes would indicate a 64-bit architecture, 4 bytes would indicate 32-bit).
Since pointers convey no information about the size of the allocation they point to, sizeof will not evaluate to the size of the allocation, it will simply tell you how large the pointer is. Further, note that sizeof is a compile time construct; its value is evaluated fully at compile time.
char *ptr = "1234567890";
char str[10] = "12345";
int numbers[10];
sizeof(ptr) evaluates the size of the pointer. The value will typically be 4 (32-bit) or 8 (64-bit).
sizeof(*ptr) evaluates the size of char. (1)
sizeof(str) evaluates the size of the array. (Its size is 10 bytes, even though only 6 were assigned.)
sizeof(numbers) will evaluate to sizeof(int) * 10.
sizeof gives you the number of bytes necessary to store a value of a given type. For a char * this is usually 4 or 8 bytes. A char * can store a memory address were you may find chars. How many chars are at such an address ? If these chars encode a C-string, then you can use strlen to get the length of the string.
I am making a program that concatenates two strings given by user. Everything is fine, but I don't know why the program shows that the sizeof of the final result is 8-bit long. Doesn't matter how long the strings are, it always shows 8. I guess, that it is the size of char, but I would like to know why it acts this way. This is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* concatenate(char *fir, char *sec)
{
int firLen = strlen(fir);
int secLen = strlen(sec);
int len = firLen + secLen + 1;
int i = 0,c=0;
int *wsk = &i;
char *result = (char *)malloc(len*sizeof(char));
while (fir[i]!='\0')
{
result[i]=fir[i];
(*wsk)++;
}
while (sec[c]!='\0')
{
result[i]=sec[c];
(*wsk)++;
c++;
}
result[len-1] = '\0';
return result;
}
int main(int argc, char **argv)
{
char *first, *second, *output;
int size1, size2;
printf("How long will your first string be: ");
scanf("%d", &size1);
first = (char *) malloc ((1+size1)*sizeof(char));
if (!first)
{
puts("\nError. Can't allocate memory!");
abort();
}
printf("How long will your second string be: ");
scanf("%d", &size2);
second = (char *) malloc ((size2+1)*sizeof(char));
if (!second)
{
puts("\nError. Can't allocate memory!");
abort();
}
printf("\nPlease, type in the first string: ");
scanf("%s",first);
printf("\nPlease, type in the second string: ");
scanf("%s",second);
output = (char *)malloc((size1+size2+1)*sizeof(char));
output = concatenate(first, second);
printf("\nConcatenation of the strings: %s", output);
printf("\n%d", sizeof(output));
free(first);
free(second);
free(output);
getchar();
return 0;
}
Don't use sizeof to determine string length, use the strlen function, as you're doing in other parts of your program.
printf("\nConcatenation of the strings: %s", output);
printf("\n%d", strlen(output));
Use sizeof to determine the size of data types, like char, a struct, an array, etc.
You've mentioned that you want to use sizeof to check if everything is fine with memory allocation, but you can't use sizeof this way on a buffer of memory allocated with malloc: you can only rely on the return value of malloc - which you aren't checking - to know if your allocation was successful.
You can use sizeof to determine the size of an array:
char myStr[13];
printf("%d\n", sizeof(myStr));
But this only works for arrays, and not buffers allocated using malloc.
Also this line creates a memory leak because you overwrite the pointer in the next line:
output = (char *)malloc((size1+size2+1)*sizeof(char));
sizeof gives the size in bytes, where a byte is the size of a char.
printf("\n%d", sizeof(output));
output is a char*, so on your system char*s are 8 bytes large. You must use strlen to obtain the length of a 0-terminated string.
printf("\n%d", sizeof(output)); prints a size of pointer to char. You platform appears to have pointers that are 8 bytes in size.
First:
second = (char *) malloc ((size2+1)*sizeof(char));
Don't typecast the result of malloc().
Second:
sizeof(char) is going to be 1, a char is 1 byte and sizeof() returns the number of bytes required to hold that data type. So you don't need the *sizeof(char), you need that for larger types like int.
Finally:
printf("\nConcatenation of the strings: %s", output); printf("\n%d", sizeof(output));
output is a char * so this is going to give you the sizeof(char *) on your system.
You said in a previous comment:
I know the differences between strlen and sizeof, but using sizeof(output) I wanted to check if everything is fine with memory allocation
Sounds like what you wanted was to verify that you allocated the correct amount of memory for the two concatenated strings. sizeof() won't give you that information. It's in the low level details at this point, you need to do something OS dependent to try and find that information. (ex. in the linux kernel if you kmalloc() memory you can use ksize() to find out exactly how many bytes you got)
I am trying to create a char array dynamically. However, do not matter which number I put as the desired value of the size array it just keep using 4 has the size. If I place 3,2 or even 8, 10 it does not change...
Part where I initialize it...
char *x;
x = (char *)calloc(10, sizeof(char));
if(x == NULL )
{
return;
}
cout <<"Size_Vector = "<<sizeof(x)<<endl; //Keep making the size of the array 4..no matter what
sizeof(x) returns the size of the pointer not the allocated memory or the size of array.
It always returns 4 size of an pointer on your envrionment is 4and it will be the same for all.
You will have to keep track of how much memory you allocated yourself & also ensure that you do not write beyond the bounds of that allocated memory.
x is a pointer of type char *. sizeof(x) returns the size of the pointer instead of the array size.
Generally, there is no way to know the array size from a pointer type even if it's pointing to an array, because of array decaying.
char *x = malloc(sizeof(char)*10);
// This will give you 4
printf ("%d\n", sizeof(x));
But you can get the size of an array type.
char x[10];
// This will give you 10
printf ("%d\n", sizeof(x));
This is a short piece of code i wrote for you in case you really want to find the size of the memory piece you reserved by calling calloc though its obvious that when you say 10 spaces of 1 byte each then you are going to get 10 bytes like the case here which says you want 10 * sizeof(char) :
#include<stdio.h>
#include<stdlib.h>
main(){
char *ptr = NULL;
int i = 0;
int size = 0;
int n = 0;
printf("Enter the size of the dynamic array in bytes : ");
scanf("%d",&n);
ptr = (char*) calloc (n,sizeof(char));
for(i=0;i<n;i++){
size = size + sizeof(ptr[i]);
}
printf("Size is %d\n",size);
}
The malloc call returns a void pointer and when you say sizeof(pointer) you ask for the size of the pointer and not the chunk of memory that you just declared.So it gives you 4/8/... bytes depending on the m/c you are using.
Try this out :
char *cptr;
int *iptr;
printf("size of integer pointer is : %d\n",sizeof(iptr));
printf("size of character pointer is : %d\n",sizeof(cptr));
Note : malloc points to the address of the first element of the chunk of memory(ie 10 * 1 = 10 bytes) that you have dynamically obtained by calling it.
I'm reading a C code that do
char * buf = malloc(sizeof (char *) * 16)
instead of
char buf[sizeof (char *) * 16]
what's the difference? well, I think the first expression unnecessary, if realloc() is not called, or am I wrong thinking?
char buf[sizeof(char*)*16] is an array allocated automatically, which is generally the stack. It is valid as long as buf is in scope, and there is sufficient stack space.
malloc allocates memory from some heap. It is valid until this memory is free()ed. Generally, there is much more heap available.
Yann's note is correct.
This appears to be an array of pointers. Since it is allocating memory for 16 times the size of a char pointer. Pointer size can vary on different systems. Pointers on some are 32-bit (4 bytes) where others are 64-bit (8 bytes).
char buf[sizeof(char *) * 16] is not an array of pointers, it's an array of chars that has elements equal to the size of a char pointer times 16.
Dynamic Array
The first one, is a dynamic array. The expression char * buf = malloc(sizeof (char *) * 16) stores the elements in memory ( the malloc is basically used for memory allocation ). The advantages of using it are, you can reallocate it, i.e resize it during runtime. However, you may have to allocate new memory every time you add a new element. Here's an example:
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
int main() {
int* array;
int n, i;
printf("Enter the number of elements: ");
scanf("%d", &n);
array = malloc(n*sizeof(int));
for (i=0; i<n; i++) {
printf("Enter number %d: ", i);
scanf("%d", &array[i]);
}
printf("\nThe Dynamic Array is: \n");
for (i=0; i<n; i++) {
printf("The value of %d is %d\n", i, array[i]);
}
printf("Size= %d\n", i);
getch();
return 0;
}
The output:
Automatic (Static?) Array
The second expression char buf[sizeof (char *) * 16] just declares a boring automatic array. It's size is static. No dynamic resizing, reallocation etc.
note: apologies for the type cast before malloc. typecasting the return value of malloc will result in the compiler not giving an error if you do something wrong. This may be followed by undefined runtime errors and debugging hell. Always avoid typecasting the result of malloc. Thanks #Lundin.
The main difference is that if this is code is in a function, you can still use the pointer declared in the former after you return.