How to create a function that allocates an array to hold pointers - c

I understand I want to use malloc, but How do I have it hold pointers?
If I am given a number for the size of the array and I want each one of those indexes to point to another array.
Some input on how to start it would be helpful. I know its not too many lines of code but the concept is abstract to me making it hard to know where to start in the code.

Well malloc allocates an area of memory the size of so many bytes. So if you want to hold pointers in that memory, you'll need to multiply the size of a single pointer by how many you want in that area.
Here's a little example for an array of strings (which are just pointers)...
const char ** array_of_strings;
array_of_strings = malloc(2 * sizeof (const char *));/* size for two pointers */
array_of_strings[0] = "first string";
array_of_strings[1] = "second string";

Related

How to Manage a 2 Dimensional Char Array?

Having gone through dozens of tutorials & programming guides, an answer has not become obvious, hence the post. Please be kind.
The matter at hand is the practical manipulation of double-d arrays of char.: {"aaaaa", "bbbbb", "ccccc",.... M}
The first problem is the declaration an initialisation of such beasts, with view to changing data in the strings "aaaaa", "bbbbb" etc.
The declarations and initialization go as:
char *chararray[M][N + 1] //M & N are set as constant values, the extra 1 for the null terminator.
memset (chararray, '\0', sizeof(chararray)); //Assuming array bounds remain constant, in the hope that dynamic allocation is not required
Assume there is also a string literal defined:
char *copyme; //Has been given a string value well within the bounds of N
The problem arises when attempting to use this in strcat or strcat_s (strcpy or strcpy_s similar):
strcat_s (chararray [i][0], N + 1, (char *) copyme); //i ranges from 0 to M
Having not come across any code that handles arrays this way, I did note from this tutorial that memcpy is the only way. Correct?
Also, how does one implement John Bode's General Procedure when calling the function from Main? (For the sake of brevity, this may have to be submitted as a separate question,)
Your initialization is wrong, you are declaring a 2D array of pointers not characters. Change it to char chararray[M][N + 1].
Also regarding the comment to memset, you declared the array with static dimensions, so the bounds will never change and you cannot use dynamic allocation if you picked the above method.
Basically you have the following options when using arrays of strings in C:
In case you are only dealing with read-only string literals, you could use a const char* per literal. An array of strings in that case would then be an array of const char* pointers.
Similarly, you could have an array of pointers if the strings are allocated elsewhere, not in your array. You'd have a lookup table.
If the length of the strings have a known maximum, you could declare it with static dimensions such as char chararray[M][N + 1]. This is a 2D array of characters, or if you will: an array of arrays of characters.
If the length of the strings are unknown, if you need them to be flexible, or if you are allocating large amounts of strings (several hundred), you can allocate them on the heap. In that case you should use an array of pointers, where each pointer is assigned a string through malloc followed by strcpy().
You probably meant
char chararray[M][N + 1];
in order then to copy a string you specify the first index
strcat_s(chararray[i], N + 1, (char *) copyme);
If you have declared it as
char *chararray[M][N + 1]
then you have a 2-dimensional array of pointers which are NULL and then when you derefence them you get an error:
strcat_s(chararray [i][0], N + 1, (char *) copyme); // boom!

C struct pointer

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.

Dynamic Memory Allocation and multi-level arrays in C

Q6: Dynamic Memory allocation: Consider the following declaration for the multi-level array,
names:
char name_1[]= “John”;
char name_2[]= “Paul”;
char name_3[] = “Stephen”;
char *names[3]={name_1, name_2, name_3};
Create an equivalent multi-level array: dynamic_names that has all its elements and the data
pointed to by its elements on the heap.
What exactly does this even mean? seems a little broad and with no direction to put me in... Would be very awesome to help!
Thanks!
Create an equivalent multi-level array: dynamic_names that has all its elements and the data pointed to by its elements on the heap.
The ...multi-level array with all its elements in heap... : char **dynamic_names; (Only a pointer because the space will be allocated dynamically using malloc).
Now the 3 elements in the array dynamic_names i.e. ...the data pointed to by its elements... also need to be in heap, therefore, each of the char *name_1; , char *name_2; ; char *name_3; will also be allocated memory dynamically similarly using malloc.
P.S. : I have explained the problem in words. Try to figure out how to write the code for it. :)
EDIT: (After OP's Comment)
More explanation:
The multi-level array dynamic_names will point to 3 char* pointers.
Each of the three pointers name_1 and similar will point to 1 char array of different sizes.
To allocate a space of 5 chars and assign it to a char * pointer, you write:
char *ptr = malloc(5 * sizeof(char));
[Sincere Advice: Don't cast return value of malloc]
EDIT 2:
char **dynamic_names = malloc(3*sizeof(char*)); This will allocate space for 3 char* pointers, and assign the base address of the allocated space to dynamic_names.
char *name_1 = malloc(10*sizeof(char)); This will allocate space for a string/array of size 10 (including '\0'), and assign the base address of the space to name_1.
strncpy(name_1, "John", 5); This will initialize the space allocated for the first string (pointed to by name_1) with "John".
dynamic_names[0] = name_1; this will assign "the pointer to first string" as the first element of the dynamic_names array.
Now you have to allocate space for other two strings and provide their base addresses to name_2 and name_3 and then assign these pointers as second and third elements resp. to dynamic_array.

is there a difference between malloc ** and *

I am wondering if there is a difference between doing this
char ** str;
str=(char **)malloc(sizeof(char*) * ARRAY_LEN);
and doing this :
str=(char*)malloc(sizeof(char)* ARRAY_LEN);
for(i=0;i<ARRAY_LEN;i++)
*(str+i)=(char*)malloc(sizeof(char)* ARRAY_LEN);
and doing this is the same too :
char str[ARRAY_LEN][ARRAY_LEN];
Yes, one is a pointer to a pointer to char, and the other is a pointer to char, there is a very big difference. between those. You can think of it as an array of strings in the first case, and a single string in the second.
Of course, in the first case you have to somehow allocate memory for the actual strings in the "array".
It all depends on what you want to achieve. I guess it is an array of strings, but maybe neither of your snippets will perform what you want. So let's go over them:
char ** str;
str=(char **)malloc(sizeof(char*) * ARRAY_LEN);
str is a pointer to a pointer to char. This could indeed be used for that purpose. The malloc then properly allocates space for ARRAY_LEN number of pointers to char, also OK for the intended purpose. The problem may lie in that there are no actual strings allocated, that is, all the ARRAY_LEN pointers to char are left pointing to God knows where (malloc() does not initialize them, not even to NULL). One way to properly finish this up would be setting all the pointers to NULL indicating your string list is empty.
str=(char*)malloc(sizeof(char)* ARRAY_LEN);
for(i=0;i<ARRAY_LEN;i++)
*(str+i)=(char*)malloc(sizeof(char)* ARRAY_LEN);
I assume str is still a pointer to a pointer to char. Then the cast itself will be invalid, as well as occupying just ARRAY_LEN bytes (sizeof(char) evaulates to 1) for ARRAY_LEN number of pointers (well, undefined as soon as you try to access all those...). The second part, the for loop would be OK for completing the first scenario if you wanted a rectangular array of chars, but this case the assignment to *(str+i) will likely cause a segfault when the loop starts writing outside the insufficient storage allocated for str.
char str[ARRAY_LEN][ARRAY_LEN];
This is a plain rectangular 2 dimensional array of chars. Note that it is conceptually different from both of the above! str can't decay to have an equal meaning to char ** str above since it's 2 dimensional (one dimensional arrays may decay to pointers as needed).
In all three cases it seemed you tried to get a rectangular (ARRAY_LEN * ARRAY_LEN) storage of characters, in the first two in the form of double indirection, in the last as a 2 dimensional array. This might not be what you wanted to do, probably you rather wanted to get an array of strings. If you don't know anything about the strings in advance, and neither their maximum length, this is more complicated to perform properly (you might want to handle all strings separately, by some means depending on use case figuring out their length, and allocating accordingly - probably even needing coding dynamically growing storage). Otherwise if you know or can limit the maximum length (pay attention to a terminating zero), you may allocate accordingly, and then limit the string lengths while you read them in.
Hope it helps.

Confused with results of sizeof() function

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)

Resources