I'm trying to write a function that converts a base 10 integer to a binary number.
I am constructing the function like this:
void dec2bin(int dec, char * bin);
The function will store the binary result by means of the pointer in the argument. It is passed a variable declared elsewhere as follows:
char *r1 = (char *)malloc(24);
The first thing the function has to do is fill the "24 bit result" with all zeros. It works great now since I've coded it based on me knowing the "size," but I can't figure out how to determine the "size" of an arbitrary "r1". Every way I can think to use the sizeof function does not give me 24.
I am confused at this point, and not connecting the relationship between the respective sizes of a char, char*, etc and how I can use those sizes to get what I'm looking for with respect to "r1".
Would someone mind giving me a pointer? Pun intended.
Thanks!
You may just pass the size as another parameter:
void dec2bin(int dec, char * bin, size_t max_chars);
I can't figure out how to determine the "size" of an arbitrary "r1".
You cannot do that: the information about the size that you passed to malloc is irreversibly lost after the call. All you have at that point is a pointer to the chunk of at least 24 bytes of memory. If you need the size, you need to store it somewhere else - for example, in a separate variable that you carry around.
Two typical work-arounds to this issue include (1) storing a zero-terminated string in the allocated space, and using the length of that string as the proxy to the size of the allocated chunk, and (2) defining your own structure that contains both the size and the allocated pointer. Neither solution is ideal, but at least the choice is with you.
The type of r1 is a char* (char pointer), so, like all pointers, its size is 4 (or 8, depending on your situation). No matter the size of the memory block you're allocating to it.
You can't retrieve the size of the allocated block from a pointer, so if you need the size later, you will have to remember the size yoursef (e.g. by storing it in a different variable).
r1 is a variable of pointer type, and its size is fixed and always the same (just like the size of any variable of a given type), which is no larger than (and usually equal to) sizeof(void *). What you really want to know is the size of the array that's sitting at *r1 (note the asterisk), and that is something you cannot know. You have to keep track of it yourself, typically like this:
size_t const n = get_some_number();
foo * p = calloc(n, sizeof(foo));
Now you use the pair (p, n) to describe your dynamic array.
(Note that C99 and C11 have the notion of a variable-length array, in whose context sizeof does actually (sometimes) give you the actual array size, but that's a somewhat murky affair, and in any case it isn't what you asked for.)
When you allocate memory, you get back a pointer, which has a fixed size, so there's no way to get the size of the allocated memory with sizeof.
As others have said, if it's just a pointer, you won't be able to tell anything (unless it's zero-terminated, in which case you can just iterate until you hit an element equal to zero (not the character '0')).
However, if you set it up as follows, you can actually see the buffer size after calling sizeof()... at least until you send it to a function, where the array decays to a plain char* pointer.
void test( char* s )
{
int i2 = sizeof( s ) / sizeof( char );
}
char c1[] = "Testing!";
int i1 = sizeof( c1 ) / sizeof( char ); // i1 is 9 (size of buffer)
test( c1 ); // i2 is 4 (size of pointer)
Related
I'm trying to improve my knowledge with pointers by making an pointer who points to another pointer that is practically a string.
Now I want to get size who normally I could get fromsizeof(foo[0])/sizeof(foo[0][0])
Pointer form
char** foo;
sizeof(test)/sizeof(*test) doesn't indicate the number of elements anymore with your declaration, because the compiler doesn't know what is the pointer pointing to, because sizeof() is a compile time operation and hence not dynamic.
To find no of elements, you can add a sentinel value:
char **test = {"New York", "Paris", "Cairo", NULL};
int testLen = -1;
while(test[++testLen] != NULL){
//DO NOTHING
}
You will never get the size of a block of memory where a pointer points to... because there can be anything.
test simply points to a place in memory where some other pointers are stored (to the first one). Each pointer will again lead to another place in Memory where some character values are stored. So, your test variable contains a simple number (the index of a place in Memory) and depending on your operating System sizeof(test) will maybe have 4 bytes or 8 bytes as result regardless of the size of the allocated memory.
sizeof() will work as you might have expected when using stack arrays. If test is declared as
char test[10][20];
Then sizeof(test) will in fact return 200.
How I can get it's length (=rows)?
You cannot. Read more in How to get the length of dynamically allocated two dimensional arrays in C
Your attempt:
char** foo;
sizeof(foo[0])/sizeof(foo[0][0])
most probably results in 8, right? That's because you are getting the size of a pointer (which is probably 8 in your system) and then divide by the size of a character, which is always 1.
If you are allocating something large you use malloc() and malloc receives one argument - the size in bytes(e.g malloc(sizeof(int)*20).
malloc also returns a void pointer to the allocated memory. You typically cast this pointer to fit your type.
In other words you can't really get the size. You must store it somewhere and pass it to other functions when its needed.
A pointer to pointer (**) is like adding one additional dimension.
[] these are more of a syntax sugar for pointer arithmetic.
a[i] would be the same as *(a+i).
This may vary on your system but sizof() will give you these values for these types.
int a; //4
int b[5]; //20
int* c; //8
int d[5][5];//100
int** e; //8
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.
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.
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?
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.