assignment from incompatiable pointer type C - c

Say I want to read in a list of pages
name of max 19 character, e.g. 4
(Number of page) Name1 Name2 Name3
Name4
I am trying to use a global 2D array
to store the page number and page
name, I got an error saying assignment
from incompatiable pointer type...
Thanks
static int nPages;
static char** pageName;
int main(void){
scanf(" %d", &nPages);
pageName = (char *)malloc(nPages*sizeof(char));
for(int i=0; i < nPages ;i++){
pageName[i] = (char *)malloc(20*sizeof(char));
scanf(" %s", pageName[i]);
}
//Free Memory Here of coz.
return 0;
}

Never cast the return value of malloc() in C. It hides compiler warnings that actually help you, and it's never necessary so it just adds clutter. You should use:
pageName = malloc(nPages * sizeof *pageName);
Note how this is free from repetitions of the type name of pageName. Here, sizeof *pageName means "the size of the object pointed at by pageName", i.e. "the size of a character pointer". You should expect a sizeof expression as malloc()'s argument very often.
Also, sizeof (char) is always 1 in C, so that particular expression, it can be argued, adds more clutter than it helps make the code safe.

The problem lies right there:
pageName = (char *)malloc(nPages*sizeof(char));
pageName is a char **, not a char *. So it should read:
pageName = malloc(nPages*sizeof(char*)); // sizeof(char *), and no need to cast
EDIT: removed the cast

Your defined pageName as char ** but when calling malloc to initialize the pointer, you use a cast to (char *). Maybe that is the problem.

You are assigning char* to char** at your first malloc line. Just drop the (char*) cast - C handles void* to char** conversion automatically.

char* and char** are two different types, and you can't freely assign the first to the latter.
Having said that, you have to do a two-step initialization. First, you have to malloc() space for nPages string:
pageName = (char**) malloc(nPages * sizeof(char*));
then, you have to malloc() space for each pageName:
for (i = 0; i < nPages; ++i) {
pageName[i] = (char*) malloc(20);
}

Related

Extremely confused about the role of triple pointers

int main()
{
char** subject_array;
char** courses_array;
initialize(subject_array, courses_array);
}
void initialize(char*** subject_array, char*** courses_array)
{
int i;
*subject_array = (char**) malloc(100 * sizeof(char*)); // 100 char pointers
*courses_array = (char**) malloc(100 * sizeof(char*));
for(i = 0; i < 100; i++) //malloc for subject_array
{
(*subject_array)[i] = (char*) malloc(4 * sizeof(char)); // 4 chars for each
(*courses_array)[i] = (char*) malloc(6 * sizeof(char)); // char pointer
}
} //void initialize
My question is: Why is there a discrepancy between the declared double pointers in main and the triple pointers in the initialize function? I think the triple pointer allows me to modify where the 2d array points.
My assignment gives these requirements:
Since you will be changing to where the pointers point, this will involve triple pointers for subjects and
courses!
The above code takes care of bolded requirement but I have absolutely no idea what this even means.
Can someone break it down to me? Does that mean I can modify contents of the 2d arrays of subject_array and courses_array? Such as swapping?
But I can do that already with just double pointers making a 2d array! WHY triple pointers?
First of all, the code is incorret, because initialize asks for char***'s and main gives it char**'s. To add another "pointer level", you take the address of whatever you want to give it to. So, the last line of main shall read initialize(&subject_array, &courses_array) (or shall it be return 0?)
After all, if you don't need to modify the variable subject_array and courses_array themselves, not what they point to, you may remove those pointers. And you actually do modify those variables themselves by means of *var = malloc(...). And, as I already noted, the only problem is that the arguments to initialize are char***, char***, not char**, char** as main is doing.

Whats the difference between char** and char* in this example?

char** surname;
surname = (char**) malloc(size*sizeof(char*));
char* middle_initial;
middle_initial = (char*) malloc(size*sizeof(char));
for(int i = 0; i<5;i++){
surname[i] = (char*) malloc(surname_max*sizeof(char));
middle_initial[i] = *(char*) malloc(middle_max*sizeof(char)); // Please focus on this line
}
surname is a double char pointer, and it makes sense that surname[i] is the i-th pointer pointed to by surname.
However, middle_initial confuses me. Is middle initial[i] the i-th character pointer? If so, why does malloc returns value call for a dereferenced *(char *) instead of (char *) during debugging?
** Follow up question**
I would like middle_initial [i] to be 6 char pointers each having the capacity to point to 1 character. What can I modify above to do such that?
Dereferencing effectively "reduces the type's pointer count by one".
Every piece of code there is okay, except for...
middle_initial[i] = *(char*) malloc(middle_max*sizeof(char));
What does this line is supposed to do apart from undefined behaviour? We don't now! As the type of middle_initial is char*, the dereference by index effectively references a char object. Then, we have the illogical expression. A char* of middle_max chars is allocated on the heap, but... that * at the front dereferences that allocated memory (memory that can be unitialized, BTW...). Then, such a garbage value is assigned to the forementioned char in middle_initial. The result of this loop is a middle_initial containing garbage chars comming from unrecoverably leaked memory.
And, of course, if size < 5, UB everywhere whenever dereferencing!

C multidimentional char array - assignment makes integer from pointer without a cast

I create a big 2d char array and want to assign strings to it.
int i;
char **word;
int start_size = 35000;
word=(char **) malloc(start_size*sizeof(char *));
for(i=0;i<start_size;i++)
word[i]=(char *) malloc(start_size*sizeof(char));
word[2][2] = "word";
how do I assign a string?
Explain me why this code doesn't work...
I am new to low level programming and C but experienced in high level programming
You cannot do string assignment in C.
You need to call a function, sepcifically strcpy() (prototype in <string.h>)
#include <string.h>
strcpy(word[2], "word");
word[2][2] = "word";
In the above statement, the string literal "word" is implicitly converted to a pointer to its first element which has type char * whereas word[2][2] has type char. This attempts to assign a pointer to a character. This explains the warning message you have stated -
assignment makes integer from pointer without a cast
You can use string literals only to initialize character arrays. What you need to do is use the standard function strcpy to copy the string literal. Also, you should not cast the result of malloc. Please read this - Do I cast the result of malloc? I suggest the following changes -
int i;
int start_size = 35000;
// do not cast the result of malloc
char **word = malloc(start_size * sizeof *word);
// check word for NULL in case malloc fails
// to allocate memory
for(i = 0; i < start_size; i++) {
// do not cast the result of malloc. Also, the
// the sizeof(char) is always 1, so you don't need
// to specify it, just the number of characters
word[i] = malloc(start_size);
// check word[i] for NULL in case malloc
// malloc fails to allocate memory
}
// copy the string literal "word" to the
// buffer pointed to by word[2]
strcpy(word[2], "word");
You have to decide if you want a list of strings or a 2D array of strings.
A list of string works like this:
char **word;
word = (char**)malloc(start_size*sizeof(char*));
word[2] = "word";
In this example word[2] would be the third string in the list and word[2][1] would be the second character in the third string.
If you want a 2D array of string you have to do this:
int i;
char ***word;
^^^ 3 stars
int start_size = 35000;
word = (char***)malloc(start_size*sizeof(char**));
^^^ 3 stars ^^^ 2 stars
for(i=0;i<start_size;i++)
word[i] = (char**) malloc(start_size*sizeof(char*));
^^^ 2 stars ^^^ 1 star
word[2][2] = "word"; // no it works!
Note that in C you do not need the casts before the malloc. So this would also work:
word = malloc(start_size*sizeof(char**));

How do I allocate memory for a pointer to an array of char *?

Could someone please explain how to correctly allocate memory for for a pointer to an array of pointer of characters in c? For example:
char *(*t)[];
I try to do it like this:
*t = malloc( 5 * sizeof(char*));
This gives me a compile error:
error: invalid use of array with unspecified bounds
Any assistance on this would be great! Thanks
What you can do is:
char **t = (char**)malloc( <no of elements> * sizeof(char*));
That allocates the array of pointers.
for (i = 0 ; i< <no of elements> ; i++)
{
t[i] = (char*)malloc( <length of text> * sizeof(char));
}
That allocates memory for the text that each element of the array points to.
When people say "a pointer to an array of X", usually they really mean a pointer to the first element of an array of X. Pointer-to-array types are very clunky to use in C, and usually only come up in multi-dimensional array usage.
With that said, the type you want is simply char **:
char **t = malloc(num_elems * sizeof *t);
Using a pointer-to-array type, it would look like:
char *(*t)[num_elems] = malloc(sizeof *t);
Note that this will be a C99 variable-length array type unless num_elems is an integer constant expression in the formal sense of the term.
Well it depends how you want it to be allocated, but here is one way.
char** myPointer = malloc(sizeof(char *) * number_Of_char_pointers)
int i;
for(i = 0; i < number_Of_char_pointers; i++)
{
myPointer[i] = malloc(sizeof(char) * number_of_chars);
}
something to note is that myPointer[i] is almost exactly identical to saying *(myPointer + i), when being used to dereference a variable, not during initialization.
Try this:
int main()
{
char** a = new char* [100];
delete []a;
return 0;
}

How do I dynamically allocate an array of strings in C?

If I have the number of items in a var called "totalstrings" and a var called "string size" that is the string size of each item, how do I dynamically allocate an array called "array?"
This is an array of strings in C, not C++.
Thanks!
NOTE: My examples are not checking for NULL returns from malloc()... you really should do that though; you will crash if you try to use a NULL pointer.
First you have to create an array of char pointers, one for each string (char *):
char **array = malloc(totalstrings * sizeof(char *));
Next you need to allocate space for each string:
int i;
for (i = 0; i < totalstrings; ++i) {
array[i] = (char *)malloc(stringsize+1);
}
When you're done using the array, you must remember to free() each of the pointers you've allocated. That is, loop through the array calling free() on each of its elements, and finally free(array) as well.
The common idiom for allocating an N by M array of any type T is
T **a = malloc(N * sizeof *a);
if (a)
for (i = 0; i < N; i++)
a[i] = malloc(M * sizeof *a[i]);
As of the 1989 standard, you don't need to cast the result of malloc, and in fact doing so is considered bad practice (it can suppress a useful diagnostic if you forget to include stdlib.h or otherwise don't have a prototype for malloc in scope). Earlier versions of C had malloc return char *, so the cast was necessary, but the odds of you having to work with a pre-1989 compiler are pretty remote at this point. C++ does require the cast, but if you're writing C++ you should be using the new operator.
Secondly, note that I'm applying the sizeof operator to the object being allocated; the type of the expression *a is T *, and the type of *a[i] is T (where in your case, T == char). This way you don't have to worry about keeping the sizeof expression in sync with the type of the object being allocated. IOW, if you decide to use wchar instead of char, you only need to make that change in one place.
char** stringList = (char**)malloc(totalStrings * sizeof(char*));
for( i=0; i<totalStrings; i++ ) {
stringList[i] = (char*)malloc(stringSize[i]+1);
}
I know this question is old and was already answered. I just want to point out that malloc is a system call and shouldn't be used multiple times.
It would be better to allocate one big chunk of memory and make the array point to it. Something like this :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STR_SIZE 100 //STR_SIZE doesn't have to be a constant
int main(){
int i;
char **arr;
char *long_string;
long_string = (char *)malloc(sizeof(char)*STR_SIZE*10);
arr = malloc(sizeof(char *)*10);
//Pointing each item of the array to an allocated memory.
for (i=0; i<10; i++){
arr[i] = (long_string + STR_SIZE * i);
}
//Initialising the array
for (i=0; i<10; i++){
strcpy(arr[i], "This is a line in a\
paragraph\n");
}
//Printing the items of the array
for (i=0; i<10; i++){
printf("%s \n", arr[i]);
}
//freeing the allocated memory
free(long_string);
free(arr);
return 0;
}
Well, first you might want to allocate space for "array", which would be an array of char * that is "totalstrings" long.
What would then be the starting and final indexes in "array"? You know the first one is 0; what's the last one?
Then, for each entry in "array", you could (if you wanted) allocate one area of memory that is "stringsize+1" (why +1, pray tell me?) long, putting the starting address of that area -- that string -- into the correct member of "array."
That would be a good start, imo.

Resources