This question already has answers here:
pointer increment and dereference (lvalue required error)
(4 answers)
Closed 8 years ago.
I'm having getting an error related to lvalue in this code:
#include <stdio.h>
#include<string.h>
main()
{
int a[]={10,20,30,40,50};
int j;
for(j=0;j<5;j++)
{
printf("%d\n",a);
a++;
}
return 0;
}
The error is displayed is:
lvalue is required as an increment operator.
Why is this problem occuring?
Any help will be appreciated.
You are trying to increment a int[] variable but that kind of variable doesn't support the increment operator.
If you were trying to iterate over the array you just need to use the variable used as the loop condition with the subscript operator:
for (int j = 0; j < 5; ++j)
printf("%d\n",a[j]);
The main problem is that the ++x operator is semantically equivalent to x = x + 1, x. This requires x to be assignable (lvalue) (since you assign a new value to it) but an array is not assignable.
In this expression
a++;
a temporary object of type int * is created that points to the first element of array a. You may not increment temporary objects. It is the same if you would write for example
int x = 10;
( x + 0 )++;
You could write the program the following way
#include <stdio.h>
int main()
{
int a[] = { 10, 20, 30, 40, 50 };
int *p;
for ( p = a; p != a + sizeof( a ) / sizeof( *a ); ++p )
{
printf( "%d\n", *p );
// or printf( "%p\n", p ); depending on what you want to output
}
return 0;
}
While it's true that arrays decays to pointers, an array is not a pointer, and you can't e.g. increment it.
Instead you can let it decay to a pointer by doing e.g.
printf("%d\n", *(a + j));
Related
int **A;
A=(int**)malloc(3*sizeof(int*));
A[0]=(int *)malloc(4*sizeof(int));
A[1]=(int *)malloc(4*sizeof(int));
A[2]=(int *)malloc(4*sizeof(int));
A[3][4]={{1,2,3,4},{1,2,3,4},{1,2,3,4}};
for(int i=0;i<3;i++)
{
for(int j=0;j<4;j++)
printf("%d ",A[i][j]);
printf("\n");
}
}
Here it is showing that "expected expression" what should I do please help me out.
For starters bear in mind that it is not a good style of programming to use uppercase letters for identifiers of variables.
In this statement
A[3][4]={{1,2,3,4},{1,2,3,4},{1,2,3,4}};
you are trying to assign values in the braced list to the scalar object of the type int that even does not exists because the indices 3 and 4 access memory outside the dynamically allocated arrays.
So as the above expression statement uses the assignment operator then the compiler expects that the right operand of the assignment is an expression. Braced lists are not expressions. So the compiler issues an error.
Pay attention to that arrays do not have the assignment operator. You need to copy elements of one array into another or set elements individually.
You could initially declare an array and initialize it with the braced list like
int A[3][4]={{1,2,3,4},{1,2,3,4},{1,2,3,4}};
As for dynamically allocated arrays then you could initialize their elements in for loops like for example
for ( size_t i = 0; i < 3; i++ )
{
int value = 1;
for ( size_t j = 0; j < 4; j++ )
{
A[i][j] = value++;
}
}
Another approach is to use compound literals like
for ( size_t i = 0; i < 3; i++ )
{
memcpy( A[i], ( int[] ){ 1, 2, 3, 4 }, sizeof( int[4] ) );
}
Here is a demonstration program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( void )
{
enum { M = 3, N = 4 };
int **a = malloc( sizeof( int *[M] ) );
for ( size_t i = 0; i < M; i++ )
{
a[i] = malloc( sizeof( int[N] ) );
memcpy( a[i], ( int[N] ){ 1, 2, 3, 4 }, sizeof( int[N] ) );
}
for ( size_t i = 0; i < M; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
printf( "%d ", a[i][j] );
}
putchar( '\n' );
}
for ( size_t i = 0; i < M; i++ )
{
free( a[i] );
}
free( a );
}
The program output is
1 2 3 4
1 2 3 4
1 2 3 4
In general you should check whether memory was allocated successfully.
I see no reason to do more than one malloc here (and perhaps not even that one).
In the below you try to assign all values to one single element in the 2D array (and it's also out of bounds since A[2][3] is the last accessible element).
A[3][4]={{1,2,3,4},{1,2,3,4},{1,2,3,4}}
What you could do is to memcpy instead.
Example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int(*A)[4] = malloc(3 * sizeof *A); // only one allocation
// "assign" all values to where A points:
memcpy(A, (int[3][4]){{1, 2, 3, 4},{1, 2, 3, 4},{1, 2, 3, 4}}, 3 * sizeof *A);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) printf("%d ", A[i][j]);
printf("\n");
}
free(A); // only one deallocation
}
A[3][4]={{1,2,3,4},{1,2,3,4},{1,2,3,4}};
It is definitely wrong.
you can assign the pointer element of the allocated array with reference to the existing array or compound literal. But it will not possible to use it as 2D array as per your pseudo code, only 1D array.
A[3]=(int[]){1,2,3,4,5,6,7,8,9,0};
or
int B[] = {1,2,3,4,5,6,7,8,9,0};
A[3] = B;
A[3] is out of bounds so you need to change the malloc as well.
A = malloc(4 * sizeof(*A));
Also do not cast the result of malloc. If your code does not compile, it means that you are using C++ compiler to compile C code which is not correct
A[3][4]={{1,2,3,4},{1,2,3,4},{1,2,3,4}}; is wrong. I think you are trying to assign something to the whole array. There are at least three things wrong with that:
Arrays cannot be assigned to like that. The syntax you used is for initialization (as part of a declaration), not assignment (as part of an expression statement).
A is not a 2-D array of int, it is a dynamically allocated array of int * whose elements point to (the first elements of) dynamically allocated arrays of int.
In an expression, A[3][4] refers to a single int element. You can only assign a value of scalar type to it. Also, both the first index 3 and the second index 4 are out of range for array access; they both refer to an element one past the last element of the the array at the corresponding dimension. Taking the address of the element one past the last element is allowed, but accessing that element is not allowed.
The elements need to be assigned individually (or via memcpy), for example using a couple of for loops:
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
A[i][j] = j + 1;
}
}
If A was an actual 2-D array of int, it could be declared and initialized using an initializer:
int A[3][4]={{1,2,3,4},{1,2,3,4},{1,2,3,4}};
This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 8 months ago.
The following declaration:
int (*x)[10]
is defined as x is an integer pointer to an integer array of 10 elements.
Question 1 : Doesn't this mean that x initially points to the first element of an array of 10 integers? If so, then, how is this different from the simple int x[10]?
Question 2 : If int (*x)[10] is different, then how is it different and what are some instances of its practical usage?
Question 3 : I was trying to write a simple program access, write to and print the array elements.
#include <stdio.h>
void main()
{
int (*x)[12], i;
for(i = 0; i <= 11;)
{
(*x)[i] = i;
printf("%d\n", (*x)[i++]);
}
}
I keep getting a segmentation fault when I run it. I understand that a segmentation fault occurs when I try to access memory that I don't have access to. But I am only accessing the 12 elements that I have initialized. Then why does my program exit with a segmentation fault? Also, am I accessing the array ((*x)[i] = i) correctly and are there other ways to access it?
For starters according to the C Standard the function main without parameters shall be decalred like
int main( void )
In the shown program you declared an uninitialized pointer
int (*x)[12], i;
that has an indeterminate value. So dereferencing the pointer
(*x)[i] = i;
results in undefined behavior.
Instead you could write for example
#include <stdio.h>
int main( void )
{
enum { N = 12 };
int a[N];
int (*x)[N] = &a;
for ( size_t i = 0; i < N; i++ )
{
(*x)[i] = i;
printf( "%d\n", (*x)[i] );
}
}
Though the program will look simpler if to write it like
#include <stdio.h>
int main( void )
{
enum { N = 12 };
int a[N];
int *x = a;
for ( size_t i = 0; i < N; i++ )
{
x[i] = i;
printf( "%d\n", x[i] );
}
}
In this declaration
int *x = a;
is implicitly converted to a pointer to its first element of the type int *.
In this declaration
int (*x)[N] = &a;
the initializing expression &a is already a pointer of the type int ( * )[N].
So in the expression
(*x)[i] = i;
the subexpression *x yields lvalue of the array a. So in fact the above expression is equivalent to
a[i] = i;
Pay attention to that in the both declarations
int *x = a;
and
int ( *x )[N] = &a;
the pointers x store the starting address of the memory extent occupied by the array a but have different types. Dereferencing the first pointer you will get the first element of the array a. Dereferencing the second pointer you will get the whole array itself.
I am trying to print a 2-D array in C by using pointers but I am not getting the expected output.
Program:-
#include <stdio.h>
int main()
{
int arr[2][3] = {{1,2,3},{4,5,6}};
int* p;
for ( p = arr; p <= arr+6; p++)
{
printf("%d ", *p);
}
return 0;
}
Output:-
1 2 3 4 5 6 -1116112128 1587637938 0 0 1893963109 32521 -1453950296 32766 -1453805568 1 800797033 21984 -1453949463
Could you tell me where I am wrong as the output should only be:
1 2 3 4 5 6
Could you tell me where I am wrong
The elements of arr are not integers, but arrays of 3 integers. So arr+6 is surely a different address than what you expect, since pointer arithmetic works in multiples of the size of the type in the array.
You'll always be better off using nested loops to iterate over a multidimensional array; treating it as one single-dimensional array of int leads to exactly the kinds of confusion you see here. The code is harder to understand and verify, it won't be any slower.
First, when looping through arrays of size n wth an index i, the condition for continuation should be i < n rather than i <= n, because array indexes in C run from 0 through n-1.
However, your code has a more serious error: 1-dimensional arrays can be 'decayed' into pointers to the elements' type; however, 2-dimensional arrays decay into pointers to 1-dimensional arrays. So, in your case, the type of the pointer used in the arr + 6 expression is a pointer to an array of three integers; further, when the 6 is added, that operation is performed in terms of the size of the pointed-to object, which is sizeof(int) * 3 – so, even when changing the <= to <, you will be running far beyond the actual bounds of the array.
To make the pointer arithmetic work in the correct 'units' (i.e. sizeof(int)), cast the arr to an int* before the addition (and also change the <= to <):
#include <stdio.h>
int main()
{
int arr[2][3] = { {1,2,3},{4,5,6} };
int* p;
for (p = (int*)arr; p < (int*)arr + 6; p++) {
printf("%d ", *p);
}
return 0;
}
You are trying to access the value in the wrong way, The two-dimensional array is saved as a continuous block in the memory. So, if we increment the value of ptr by 1 we will move to the next block in the allocated memory.
int arr[2][3] = {{1,2,3},{4,5,6}};
int *ptr = arr;
int i,j;
for (i = 0; i < 6; i++) {
printf("%d ", *(ptr + i));
}
return 0;
Array designators used in expressions with rare exceptions are implicitly converted to pointers to their first elements.
The type of the array elements of this array
int arr[2][3];
is int [3]. So a pointer to the first element of the array has the type int ( * )[3].
This assignment
p = arr;
where p has the type int * is incorrect because the operands of the assignment have incompatible pointer types.
At least you need to cast the right expression to the type int * like
p = ( int * )arr;
The same casting you need to use in the condition in the for loop. That is instead of
p <= arr+6
you have to write
p < ( int * )arr+6
Below there is a demonstration program that shows how to output a two-dimensional array as a two-dimensional array using pointers.
#include <stdio.h>
int main( void )
{
int arr[2][3] = {{1,2,3},{4,5,6}};
for ( int ( *p )[3] = arr; p != arr + 2; p++ )
{
for ( int *q = *p; q != *p + 3; ++q )
{
printf( "%d ", *q );
}
putchar( '\n' );
}
return 0;
}
If you want to output the two-dimensional array as a one-dimensional array then you can write
#include <stdio.h>
int main( void )
{
int arr[2][3] = {{1,2,3},{4,5,6}};
for ( int *p = ( int * )arr; p != ( int * )arr + 6; p++ )
{
printf( "%d ", *p );
}
putchar( '\n' );
return 0;
}
In
for ( p = arr; p <= arr+6; p++)
the expression arr, as an rvalue, is a pointer to the first element of the array (which is of type int [3], so each time you increment that pointer, it moves three int positions forward ---a whole row---, and so, arr + 6 points just after the sixth row of the array (if the array should ever had six rows) You can do it (with the proper explicit pointer conversions, as you are mixing pointers to int with pointers to int [3]) with the expression arr + 2 which is the addres of the first array element after the second row (and the number of rows of the array).
You can do it also declaring
int (*aux)[2][3] = &arr; /* aux is a pointer to the whole 3x2 array,
* so aux + 1 will be the position of the second
* 2D array after this one */
and then
int *end = (int *)(aux + 1);
or simply
int *end = (int *)(&arr + 1); /* see below */
(Beware that arr and &arr are both pointers and point to the same place, but they are not the same type (arr is of type int (*)[3] and &arr is of type int(*)[2][3])
So let's rewrite your code as
for (p = (int *)arr; p < end; p++)
or
for (p = (int *)arr; p < (int *)&arr + 1; p++)
would work, which seems more natural to do the calculus in complete array units than in rows or single cells (and you can change freely the dimensions of the array)
Your code would be:
#include <stdio.h>
int main()
{
int arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
int *end = (int *)(&arr + 1); /* try to avoid evaluating this expression in the loop
* despite that it can be optimized to comparing
* with a constant value */
char *sep = "";
for (int *p = (int *)arr; p < end; p++)
{
printf("%s%d", sep, *p);
sep = ", ";
}
putchar('\n');
return 0;
}
(Beware that you have to use < operator and not <= as you don't want to print the value pointed by end, because it lies one place outside of the array)
Finally a note: this will work with true arrays, but not with function parameters declared as arrays, because they decay to pointers and then &arr is not a pointer to data the size of the array, but it is the address of the parameter itself, which points to the array somewhere else.
++*P--;
That is a question from an exam, if P a pointer to any element in an array, explain what this statement really does.
I even wrote a simple code to evaluate it:
int i;
int* array = calloc(10, sizeof(int));
for (i = 0; i < 10; i++) {
array[i] = i;
printf("%d,", array[i]);
}
int* P = array + 5;
printf("\n %p", P);
printf("\n %d", *P);
++*P--;
printf("\n %p", P);
printf("\n %d \n", *P);
for (i = 0; i < 10; i++) {
printf("%d,", array[i]);
}
But the output confuses me even more:
0,1,2,3,4,5,6,7,8,9,
0x100105534
5
0x100105530
4
0,1,2,3,4,6,6,7,8,9,
It looks like it first dereferences P, then increases its value and then decreases value of pointer P, but why?
According to K&R table 2-1 from p53 (see the picture below)
++, --, and * (dereference) has the same precedence and associativity from right to left.
So first step should be decreasing value of P, then dereference and then increasing dereferenced value, am I wrong?
You are correct that the precedence is
++(*(P--))
But note that the decrement is a postfix operation: even though the change to P happens first, the rest of the expression uses the old value of P. So in your example, first P is decremented to array+4, but the value of P-- is array+5, so array[5] gets incremented.
You can imagine this expression
++*P--
the following way
int *tmp = p;
--p;
int value = *tmp;
++value;
Here is a demonstrative program
#include <stdio.h>
int main( void )
{
char s[] = "Hello World";
char *p = s + 6;
std::printf( "%c\n", ++*p-- );
std::printf( "%s\n", s );
p = s + 6;
char *tmp = p--;
char value = *tmp;
++value;
std::printf( "%c\n", value );
std::printf( "%s\n", s );
}
The program output is
X
Hello Xorld
Y
Hello Xorld
The difference in the outputting the string is that expression ++*p-- changes the string itself but expression ++value; changes a separate object. But the logic is similar.
Postfix expression p-- has the highest priority but its value is the value of p before decreasing.
Unary operators ++ and * in expression ++*p-- group right to left. So at first operator * is applied to the expression and after that operator ++ is applied.
I'm trying to do pointer arithmetic with a pointer to array, but I get a wrong value since I can't dereference the pointer properly.
Here is the code:
#include "stdlib.h"
#include "stdio.h"
int main()
{
int a[] = {10, 12, 34};
for (int i = 0; i < 3; ++i)
{
printf("%d", a[i]);
}
printf("\n");
int (*b)[3] = &a;
for (int i = 0; i < 3; ++i)
{
printf("%d", *(b++));
}
printf("\n");
return 0;
}
In the second for I can't get to print the correct value.
It doesn't work even if I write
printf("%d", *b[i]);
I'd like to see how to print correctly using the b++ and the b[i] syntax.
The following should work:
printf("%d\n", *( *b+i ));
// * b + i will give you each consecutive address starting at address of the first element a[0].
// The outer '*' will give you the value at that location.
instead of:
printf("%d", *(b++));
You have declared b to be a pointer to arrays of 3 integers and you have initialized it with address of a.
int (*b)[3] = &a;
In the first loop you will print the first element of a array but then you will move 3*sizeof(int) and trigger undefined behavior trying to print whatever there is.
To print it correctly:
int *b = a;
// int *b = &a[0]; // same thing
// int *b = (int*)&a; // same thing, &a[0] and &a both points to same address,
// though they are of different types: int* and int(*)[3]
// ...so incrementing they directly would be incorrect,
// but we take addresses as int*
for (int i = 0; i < 3; ++i)
{
printf("%d", (*b++));
}
gcc will complain about the formatting in the second for loop: it will tell you format specifies type 'int' but the argument has type 'int *
your assignment of a to b should look like this:
int *b = a