Pointer not assignable in C? - c

I want to create an array of strings, so I first use:
char** p = malloc(sizeof(char*) * count); // count is the number of strings
But then trouble comes when I want to initialize those strings:
for (int i = 0; i < count; i++)
{
char* s = malloc(size_of_each_string);
*p + i = s; // THIS STEP INDUCES ERROR
while (*s++ = *input++); // initialize by copy
}
So I'm really confused. *p+i seems to be pointer arithmetic which shifts to another pointer. Pointer assignment in general is allowed (point to the same object). So why does such assignment not allowed? And how could I get around this to accomplish this task?
The error message is: Expression is not assignable.

Use *(p+i)=s instead of *p+i=s.
The things you're trying to do is to keep s in (p+i) address. For this you need to use *(p+i) instead of *p+i.
About Error Message:
Here the arithmetic expression *p+i will derive a value. But you can save a value only into a memory address. For this you're getting that error message.

*p + i = s;
is equivalent to
*(p) + i = s;
due to operator precedence. It yields an rvalue, which is not assignable.
Use parantheses instead:
*(p + i) = s;
or, even better, subscripting:
p[i] = s;

It's a problem with operator precedence.
The expression *p + i is parsed as (*p) + i not as *(p + i), so you need to do it explicitly. Or use normal array indexing syntax p[i].

Why don't you simplify your code by :
char** p = malloc(sizeof(char*) * count); // count is the number of strings
for (int i = 0; i < count; i++)
{
p[i] = malloc(sizeof(char) * size_of_each_string));
strcpy(p[i], input);
}

Related

How to find the total length of strings in an array of strings

In the following array:
["fix", "cache", "four"];
Is there a way to get the total length of characters in the array? = 3 + 5 + 4 = 12? Currently what I am doing is adding together all the lengths of the individual strings:
char * strings[] = {"fix", "cache", "four", NULL};
size_t len_strings = 0;
for (int i=0; strings[i] != NULL ;i++)
len_strings += strlen(strings[i]);
printf("StringLength: %lu\n", len_strings);
// StringLength: 12
Also, why couldn't the following be done instead?
for (int i=0; *strings != NULL ;i++) {
len_strings += strlen(*strings++);
}
I can do the folllowing (but I believe it's the same as doing the array offset, just with a different notation)
for (int i=0; *(strings+i) != NULL ;i++) {
len_strings += strlen(*(strings+i));
}
You are doing it the only way possible: iterating over the array and checking each string.
The pointer increment doesn't work because strings is not a pointer. It's an array, so you can't do array++. However you can do pointer arithmetic with it. You could also use a pointer to do what you initially wanted:
#include <stdio.h>
#include <string.h>
int main(void)
{
char * strings[] = {"fix", "cache", "four", NULL};
char **pointer = strings;
size_t len_strings = 0;
for (int i=0; *pointer != NULL ;i++) {
len_strings += strlen(*(pointer++));
}
printf("StringLength: %lu\n", len_strings);
}
It is not better, neither worse than indexing the array. It's just a way to do with pointer++. Notice that the parentheses around (pointer++) are not mandatory, but it's better to keep them. It can be confusing to rely on operator precedence when you have two operators with the same precedence and each is in one side of the operand.
Lastly, your belief is correct. For any array, this:
array[i]
is just the same as
*(array + i)
You have to iterate through each string of the the strings array to get the total length of all the strings.
strings is an array of char pointers. You cannot use ++ operator with strings variable (*strings++) because it's not allowed to change the address of an array. If you want to use pointers, you can do
char **p_strs = strings;
for (int i=0; *p_strs != NULL ;i++) {
len_strings += strlen(*p_strs++);
}
Yes, the *(strings+i) is same as strings[i]. From C Standard#6.5.2.1:
The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))).

Initialize values of dynamic array in a function (C language)

this is my code:
void init_array(int** array) {
*array = (int*) malloc(3 * sizeof(int));
/* ???? **(array+2) = 666; */
return;
}
void init(int* array, int* length) {
*length = 3;
*(array+0) = 0;
*(array+1) = 1;
*(array+2) = 2;
return;
}
int main(void) {
/* Variables */
int array_length;
int* array;
/* Initialize */
init_array(&array);
init(array, &array_length);
free(array);
return 0;
}
My question is: How can I initialize values of the array in a function init_array().
I have attempted things such as:
**(array+2) = 666;
*(*(array+2)) = 666;
*array[2] = 666;
**array[2] = 666;
When I used pencil and paper I came to result that **(array+2) should work but it gives me a segmentation fault.
I would appreciate your answer because I am confused how pointers in C actually work.
You have the address of a pointer passed to the function:
array
You want to dereference that to get the pointer:
*array
Then apply the array subscript operator to the result:
(*array)[2]
Or equivalently:
*((*array) + 2)
The parenthesis are required because the array subscript operator [] has higher precedence than the dereference operator *.
Generally speaking, you should use the array subscript operator whenever possible, as it tends to be easier to read.

I am learning about pointers in C and am starting with a basic idea, but I keep getting errors. What am I doing wrong?

I am learning about pointers in C and am starting with a basic idea: using a pointer to go through and change an array. Then print that array. What mistakes am I making?
I was told you can go through an array by assigning it to a pointer variable, as I have done below:
int main(void){
int i = 0;
char entry[40], n, p;
p = entry;
printf("Enter a sentence: ");
while ((n = getchar()) != '\n'){
*(p + i) = n;
i++;
}
*(p + i) = 0;
printf("%s", p);
return 0;
}
I've been experimenting with different ways of doing this for a bit now and could use some help. I keep receiving errors such as:
assignment makes integer from pointer without a cast
invalid lvalue in assignment
assignment makes integer from pointer without a cast
This refers to code p = entry where you try to assign a pointer (entry) to p which is of type char
invalid lvalue in assignment
This refers to *(p + i) = n as (p + i) is a number (a char can be considered as an int for this case) and not a pointer, thus cannot be assigned.

Generic bidimensional array

I want to create a bidimensional array like so:
void **mdeclaraMatrice(int nrLini,int nrColoane, int sizeOfElement)
{
int i;
void **m = malloc(nrLini * 4);
if(m==NULL)
return NULL;
for(i=0; i<nrLini; i++)
{
*(m + (i*4)) = malloc(nrColoane * sizeOfElement);
if(*(m + (i*4)) == NULL)
return NULL;
}
return m;
}
I whant to use it like this:
int **m = (int **)mdeclaraMatrice(n,m,sizeof(int));
but it doesn't work. What do I do wrong?
You should use m[i] instead of *(m+i*4) and let the compiler do the arithmetic.
In addition, you should deallocate the already-allocated memory in case of a failure.
Try this instead:
void **mdeclaraMatrice(int nrLini, int nrColoane, int sizeOfElement)
{
int i;
void **m = malloc(nrLini * sizeof(void*));
if (m == NULL)
return NULL;
for (i=0; i<nrLini; i++)
{
m[i] = malloc(nrColoane * sizeOfElement);
if (m[i] == NULL)
{
while (i-- > 0)
free(m[i]);
free(m);
return NULL;
}
}
return m;
}
[not an answer to the question, but to the indented usage of the proper answer as given by others]
To access the void pointer array as an array of int, doing this
int **m = (int **)mdeclaraMatrice(n,m,sizeof(int));
is not correct, as per the C-Standard only void* converts to any other pointer properly, void** doesn't necessarily. So it shall correctly be
void ** ppv = mdeclaraMatrice(n,m,sizeof(int));
int * pi = *ppv; /* Please note, there is NO casting necessary here! */
Then access the members like so:
pi[0] = 42
pi[1] = 43;
...
Which essently is the same as doing
*((int *) (pi + 0)) = 42;
*((int *) (pi + 1)) = 43;
which indeed does not make sense really as pi already is int*, so the fully correct approach (also taking into account the 2nd dimension) would be:
((int *)(ppv[0]))[0] = 42;
((int *)(ppv[0]))[1] = 43;
Which could be made usable by definging a macro:
#define GENERIC_ARRAY_ELEMENT(type, address, r, c) \
((type *)(address[r]))[c]
GENERIC_ARRAY_ELEMENT(int, ppv, 0, 0) = 42;
GENERIC_ARRAY_ELEMENT(int, ppv, 0, 1) = 43;
I will address the problem of allocation an array of void pointers and then interpreting them as an array of int pointers.
int **nope = (int **)mdeclaraMatrice(n,m,sizeof(int));
Even assuming the allocation was completely correct the assignment and later usage of nope is undefined behavior. void** and int** have incompatible types.
What you can do is the following. Assign the void pointers one by one to an array of int pointers.
void** arrp = mdeclaraMatrice(n,m,sizeof(int));
int* arr[n] ;
for( size_t i = 0 , i < n ; i++ )
arr[i] = arrp[i] ;
And then use the arr array, When you want to free the memory you free the original pointer:
free( arrp ) ;
The problem occurs in this line:
*(m + (i*4)) = malloc(nrColoane * sizeOfElement);
You have to know that when adding a number to an address, the address will be incremented by the number times the size of the object the address points to. So if your pointer points to an object that is of size 4 bytes, and you add 1 to it, then the address will automatically be incremented by 4, not by 1. So you should abandon *4.
Also, use the sizeof operator when allocating space, because addresses (and thus pointers) can have different sizes on different processor architectures.
Actually, you don't even need your generic 2D array function if you know the powerfull VLA features of C99. To allocate a true 2D array (no index array required), you just do this:
int (*twoDIntArray)[width] = malloc(height*sizeof(*twoDIntArray));
That's it. Accesses are just as simple:
twoDIntArray[line][column] = 42;
In this code, twoDIntArray is a pointer to an array of width integers. The malloc() call simply allocates enough space for height such line arrays. When you do the pointer arithmetic twoDIntArray[line], you add the size of line line arrays to the pointer, which produces the address of the corresponding line array. This line array is then indexed by the second array subscript [column].
Needless to say that freeing such an array is just as trivial:
free(twoDIntArray);

Invalid type argument of -> C structs

I am trying to access items in an array of structs and print the structs fields as follows
printList(Album *a, int numOfStructs)
{
int i;
int j;
for(i = 0; i < numOfStructs; i++)
{
printf("number%d\n:", i+1);
printf("%s", a[i]->field2);
printf("%s", a[i]->field2);
printf("%d", a[i]->field3);
for(j = 0; j < a[i]->numOfStrings; j++)
{
printf("%s", a[i]->strings[j]);
}
printf("\n");
}
}
but I get loads of errors as such
invalid type argument of '->'
What am I doing wrong with this pointer?
a is of type Album* which means that a[i] is of type Album (it is the ith element in the array of Album object pointed to by a).
The left operand of -> must be a pointer; the . operator is used if it is not a pointer.
You need to use the . operator. You see, when you apply a * to a pointer, you are dereferencing it. The same goes with the []. The difference between * and [] is that the brackets require an offset from the pointer, which is added to the address in the pointer, before it is dereferenced. Basically, these expressions are identical:
*ptr == ptr[0]
*(ptr + 1) == ptr[1]
*(ptr + 2) == ptr[2]
To connect to your question: Change a[i]->field2 and a[i]->field3 to a[i].field2 and a[i].field3.

Resources