I've read various tutorials on pointers, and I now come with a question,
is this:
char *input = malloc(sizeof(char)*24);
the same as
char *input[24];
I was under the impression that the malloc will also create my space on the heap with 24 slots. Usually, I see char input[24], but the char *input[24] I figured was a simpler way than mallocing.
Thanks!
No, they are not the same.
char *input = malloc(sizeof(char)*24);
will allocate a block of 24 char's on the heap and assign a pointer to the start of that block to input. (technically you are just telling it to allocate x number of bytes where x is 24 times the size, in bytes, of each char)
char *input[24];
will create an array of 24 char pointers on the stack. These pointers will not point to anything (or garbage on init) as you have it written.
For the second example, you could then take each pointer in the array input and allocate something for it to point to on the heap. Ex:
char *input[NUM_STRS];
for( int i = 0; i < NUM_STRS; i++ )
{
input[i] = malloc( MAX_STR_LEN * sizeof(char) );
}
Then you would have an array of character pointers on the stack. Each one of these pointers would point to a block of characters on the heap.
Keep in mind, however, that things on the stack will be popped off when the function exits and that variable goes out of scope. If you malloc something, that pointer will be valid until it is freed, but the same is not true of an array created on the stack.
EDIT:
Based on your comment, here is an example of making 24 character pointers on the heap and allocating space for them to point to:
#define NUM_STRS 24
#define MAX_STR_LEN 32
char **input = malloc( sizeof(char *) * NUM_STRS );
for( int i = 0; i < NUM_STRS; i++ )
{
input[i] = malloc( sizeof(char) * MAX_STR_LEN );
}
Please keep in mind that with this example you will have to free each pointer in input, and then input itself at the appropriate time to avoid leaking memory.
These are not the same at all.
char *input = malloc(sizeof(char)*24);
This allocates enough memory to hold 24 char, and assigns the address to input (a pointer). This memory is dynamically-allocated, so it needs to be released at some point with an appropriate call to free().
char *input[24];
This declares input to be an array of 24 pointers. This has automatic storage, which means you do not need to free it. (However, you may need to free the things being pointed to by each of the pointers, but that's a different matter!)
Fundamentally, the types of the two variables are different. In the first case, you declare a pointer to char that points to memory dynamically allocated by malloc (which you are morally obligated to free at a later instant). In the second case, you declare an array of pointers to char.
Couple of observations:
sizeof(char) is one by definition, so you can leave that out. (No, it does not convey a documenting purpose. You are better of rewriting it as char *input = malloc( 24 * sizeof *input );)
Very seldom will the call to malloc have an integer literal. If it does (24) in your example, then usually one would prefer to have an array to hold that (there are some considerations regarding stack usage that I am side-stepping here).
hope this helps,
You can compare it better to char input[24]; (note no *). With that you can use input in the same way but the memory is on the stack instead of on the heap.
Related
I am not able to understand the difference between strcpy function and the method of equating the addresses of the strings using a pointer.The code given below would make my issue more clear. Any help would be appreciated.
//code to take input of strings in an array of pointers
#include <stdio.h>
#include <strings.h>
int main()
{
//suppose the array of pointers is of 10 elements
char *strings[10],string[50],*p;
int length;
//proper method to take inputs:
for(i=0;i<10;i++)
{
scanf(" %49[^\n]",string);
length = strlen(string);
p = (char *)malloc(length+1);
strcpy(p,string);//why use strcpy here instead of p = string
strings[i] = p; //why use this long way instead of writing directly strcpy(strings[i],string) by first defining malloc for strings[i]
}
return 0;
}
A short introduction into the magic of pointers:
char *strings[10],string[50],*p;
These are three variables with distinct types:
char *strings[10]; // an array of 10 pointers to char
char string[50]; // an array of 50 char
char *p; // a pointer to char
Then the followin is done (10 times):
scanf(" %49[^\n]",string);
Read C string from input and store it into string considering that a 0 terminator must fit in also.
length = strlen(string);
Count non-0 characters until 0 terminator is found and store in length.
p = (char *)malloc(length+1);
Allocate memory on heap with length + 1 (for 0 terminator) and store address of that memory in p. (malloc() might fail. A check if (p != NULL) wouldn't hurt.)
strcpy(p,string);//why use strcpy here instead of p = string
Copy C string in string to memory pointed in p. strcpy() copies until (inclusive) 0 terminator is found in source.
strings[i] = p;
Assign p (the pointer to memory) to strings[i]. (After assignment strings[i] points to the same memory than p. The assignment is a pointer assignment but not the assignment of the value to which is pointed.)
Why strcpy(p,string); instead of p = string:
The latter would assign address of string (the local variable, probably stored on stack) to p.
The address of allocated memory (with malloc()) would have been lost. (This introduces a memory leak - memory in heap which cannot be addressed by any pointer in code.)
p would now point to the local variable in string (for every iteration in for loop). Hence afterwards, all entries of strings[10] would point to string finally.
char *strings[10]---- --------->1.
strcpy(strings[i],string) ----->2.
strings[i] = string ----------->3.
p = (char *)malloc(length+1); -|
strcpy(p,string); |-> 4.
strings[i] = p;----------------|
strings is an array of pointers, each pointer must point to valid memory.
Will lead undefined behavior since strings[i] is not pointing to valid memory.
Works but every pointer of strings will point to same location thus each will have same contents.
Thus create the new memory first, copy the contents to it and assign that memory to strings[i]
strcpy copies a particular string into allocated memory. Assigning pointers doesn't actually copy the string, just sets the second pointer variable to the same value as the first.
strcpy(char *destination, char *source);
copies from source to destination until the function finds '\0'. This function is not secure and should not be used - try strncpy or strlcpy instead. You can find useful information about these two functions at https://linux.die.net/man/3/strncpy - check where your code is going to run in order to help you choose the best option.
In your code block you have this declaration
char *strings[10],string[50],*p;
This declares three pointers, but they are quite different. *p is an ordinary pointer, and must have space allocated for it (via malloc) before you can use it. string[50] is also a pointer, but of length 50 (characters, usually 1 byte) - and it's allocated on the function stack directly so you can use it right away (though the very first use of it should be to zero out the memory unless you've used a zeroing allocator like Solaris' calloc. Finally, *strings[10] is a double pointer - you have allocated an array of 10 pointers, each element of which (strings[1], strings[9] etc) must be allocated for before use.
The only one of those which you can assign to immediately is string, because the space is already allocated. Each of those pointers can be addressed via subscripts - but in each case you must ensure that you do not walk off the end otherwise you'll incur a SIGSEGV "segmentation violation" and your program will crash. Or at least, it should, but you might instead get merely weird results.
Finally, pointers allocated to must be freed manually otherwise you'll have memory leaks. Items allocated on the stack (string) do not need to be freed because the compiler handles that for you when the function ends.
char **three = (char**)malloc(sizeof(char*));
char**, the char pointer type is used. and char** means I'm dereferencing char pointer. and as for the sizeof(char*) I'm using the size of char pointer which is 8 byte.
Am I misunderstanding this?
So the code:
char **three = ( char** )malloc( sizeof( char* ) );
Allocates an array of pointers-to-char, but with only a single element. The variable three is a pointer-to, a pointer-to a char. Much the same as:
char *three[1];
Normally (as #paxdiablo points out), it would be more usual to allocate a number of pointers:
int line_count = 66;
char **three = ( char** )malloc( line_count * sizeof( char* ) );
Once allocated, this can be used with array notation:
three[0] = "The Owl and the Pussy-cat went to sea";
three[1] = "In a beautiful pea-green boat,";
three[2] = "They took some honey, and plenty of money,";
three[3] = "Wrapped up in a five-pound note."
There's nothing particularly special about a char**, every C/C++ program gets one as its argv.
As a programmer, you don't really know that your pointer is 8 bytes, you know the pointer will be some size. This is where the sizeof( char* ) comes in. During compilation the compiler swaps this with the real value. That way when the architecture is 16, 32 or 64 bit (or maybe 128 bit in the future), the code still compiles fine.
Let's see if we can break this down:
char **three = (char**)malloc(sizeof(char*));
[ 1 ][5][ 4 ][ 3 ] [ 2 ]
Create a variable three of type char **, a pointer to a char * (often a "string" in C).
Use the size of a char* to pass to malloc.
Use malloc to allocate that many bytes.
Cast the return value from malloc, a void*, to char**.
Assign that value to three.
So in terms of where I think your misunderstanding lies:
Do not cast the return value of malloc or realloc in C. C is perfectly capable of implicitly casting void* to other pointer types and doing it explicitly can hide certain subtle errors.
There is no dereferencing going on here. The (unwise) cast is exactly that, telling the compiler you want to treat an expression of one type as if it was another type.
You've actually allocated an array of char* variables and that array size is one. So, short of calling realloc on it at some point, its use is limited (unless you need it to survive the current scope, you're probably just better using a local variable rather than an allocated one-element 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.
I have a char** which is designed to hold and unknown amount of strings with unknown length
I've initially allocated 10 bytes using
char **array = malloc(10);
and similarly, before adding strings to this array, I allocate
array[num] = malloc(strlen(source)+1)
I've noticed that my program crashes upon adding the 6th element to the array
My question is, how does memory with these arrays work? When I allocated 20 bytes, nothing happened, yet when I allocated 30, it suddenly could hold 10 elements. These were all strings of 2-3 characters in size. I'm struggling to think of a condition to realloc memory with, e.g
if condition{
memoryofarray += x amount
realloc(array, memoryofarray)
}
What exactly uses the memory in the char**? I was under the impression that each byte corresponds to how many lines they can hold, i.e. malloc(10) would allow the array to hold 10 strings. I need to know this to establish conditions + to know how much to increment the memory allocated to the array by.
Also, curiously, when I malloced
array[num] = malloc(0)
before assigning a string to that array element, it worked without problems. Don't you need to at least have strlen amount of bytes to store strings? This is confusing me massively
This line:
char **array = malloc(10);
allocates 10 bytes, however, remember that a pointer is not the same size as a byte.
Therefore you need to make sure you allocate an array of sufficient size by using the size of the related type:
char **array = malloc(10 * sizeof(char*));
Now that you have an array of 10 pointers you need to allocate memory for each of the 10 strings, e.g.
array[0] = malloc(25 * sizeof(char));
Here sizeof(char) is not needed but I added it to make it more obvious how malloc works.
If you want to hold 10 strings then you need to allocate memory for 10 char *'s and then allocate memory to those char pointers .You allocate memory of 10 bytes( not enough for 10 char *'s ) .Allocate like this -
char **array = malloc(10*sizeof(char *)); // allocate memory for 10 char *'s
And then do what you were doing -
array[num] = malloc(strlen(source)+1) // allocate desired memory to each pointer
note - take care that num is initialized and does not access out of bound index.
This will allocate enough memory for 10 pointers to char (char*) in array
char **array = malloc(10*sizeof(array[0]));
On a 64bit system the size of a char* is 8 bytes = 64 bits. The size of a char is typically 1 byte = 8 bits.
The advantage of using sizeof(array[0]) instead sizeof(char*) is that it's easier to change the type of array in the future.
char** is pointer to a pointer to char. It may point to the start of a memory block in the heap with pointers to char. Similarly char* is a pointer to char and it may point to the start of a memory block of char on the heap.
If you write beyond the allocated memory you get undefined behaviour. If you are lucky it may actually behave well! So when you do for example :
array[num] = malloc(0);
you may randomly not get a segmentation fault out of (good) luck.
Your use of realloc is wrong. realloc may have to move the memory block whose size you want to increase in which case it will return a new pointer. Use it like this :
if (condition) {
memoryofarray += amount;
array = realloc(array, memoryofarray);
}
Rather than allocating memory using the fault-prone style
pointer = malloc(n); // or
pointer = malloc(n * sizeof(type_of_pointer));
Use
pointer = malloc(sizeof *pointer * n);
Then
// Bad: certainly fails to allocate memory for 10 `char *` pointers
// char **array = malloc(10);
// Good
char **array = malloc(sizeof *array * 10);
how does memory with these arrays work?
If insufficient memory is allocated, it does not work. So step 1: allocate sufficient memory.
Concerning array[num] = malloc(0). An allocation of 0 may return NULL or a pointer to no writable memory or a pointer to some writable memory. Writing to that pointer memory is undefined behavior (UB) in any of the 3 cases. Code may crash, may "work", it is simply UB. Code must not attempt writing to that pointer.
To be clear: "worked without problems" does not mean code is correct. C is coding without a net. Should code do something wrong (UB), the language is not obliged to catch that error. So follow safe programming practices.
First allocate an array of pointers:
char* (*array)[n] = malloc( sizeof(*array) );
Then for each item in the array, allocate the variable-length strings individually:
for(size_t i=0; i<n; i++)
{
(*array)[i] = malloc( some_string_length );
}
I was trying to understand some code written by others. But I am not very familiar with C. Could anyone explain the following code? Thx ahead!
struct cell *ptr = (struct cell* ) malloc ( (input * 1024) * sizeof(struct cell));
This code creates a pointer of type struct cell named ptr which points to a memory location- a sequence of (input*1024) number of blocks, where each block is of size sizeof(struct cell)
This is dynamic memory allocation. During runtime if there is not that much amount of free memory, it will return NULL and ptr will be pointing to NULL It always advised to check ptr for NULL value before playing with it.
As you have allocated the memory dynamically, it's your responsibility to free/reclaim it by calling free(ptr) once you are done.
This was a way of allocating memory in the 1970s which is still sometimes seen today, perhaps due to a "cargo cult" programming mentality.
The effect is to allocate a contiguous array which has 1024 * input number of elements, and each element is an (uninitialized) struct cell.
Today we would write:
struct cell *ptr = malloc( input * 1024 * sizeof *ptr );
or
struct cell *ptr = calloc( input * 1024, sizeof *ptr );
The latter will also initialize any integers in the struct to have value 0, and any char arrays to contain empty strings; and may be faster depending on the operating system.
The sizeof *ptr part is necessary because the malloc family of functions expect number of bytes instead of number of elements so we must multiply by the number of bytes per element; and if ptr points to an element, then *ptr is an element, so sizeof *ptr retrieves the size of that element.
For explanation of why the old style is no longer in favour, see here.
This code dynamically allocates a number of struct cell's. The number is equal to input*1024. As a result ptr will be a 1D array of structs. Don't forget to free() it!
Also say to these others not to cast malloc().
The function malloc is used to dynamically allocate memory, it is used when you have no prior knowledge of how large something will be beforehand. Its argument is the number of bytes you want. Given an input, in this case input, it will give you that number of struct cells times 1024. Think of it like a matrix, where 1024 is the width and input is the height. Finally the function returns the pointer to the allocated memory block which is stored in ptr so that you can use it.In a object oriented language it is the equivalent of creating an array of objects, the size of the "object" is the size of the cell, input would be the number of such "arrays of objects" you are creating, and 1024 is the array length.