invalid conversion from ‘const int*’ to ‘int*’ - c++

I receive the following error
$ g++ test.cpp
test.cpp: In function ‘int test1(const int**, int)’:
test.cpp:11:14: error: invalid conversion from ‘const int*’ to ‘int*’ [-fpermissive]
a=v[i];
^
test.cpp: In function ‘int main()’:
test.cpp:31:20: error: invalid conversion from ‘int**’ to ‘const int**’ [-fpermissive]
cout<<test1(c,2)<<endl;
^
test.cpp:4:5: error: initializing argument 1 of ‘int test1(const int**, int)’ [-fpermissive]
int test1(const int **v,int num)
^
when compiling the following code:
#include <iostream>
using namespace std;
int test1(const int **v,int num)
{
int *a;
int result=0;
// do somethings ....
for(int i=0;i<num;i++)
{
a=v[i];
// do somethings ....
result+=*a;
}
return result;
}
void test2(const int num)
{
cout<<num<<endl;
}
int main()
{
int a =5;
int b =8;
int **c;
c=new int *[2];
c[0]=&a;
c[1]=&b;
cout<<test1(c,2)<<endl;
test2(a);
delete [] c;
return 0;
}
i give an int to test2 which asks for const int and it is ok. however test1 does not accept int ** instead of const int **.
in the above code even typecast does not work:
a=(int *)v[i];
AFAIK, const means that I promise that I will not change the value of v and i didnt. however, the compiler gives me error.

Just write
int const *a; // or const int *a; which is the same.
...then const correctness will be preserved. The compiler complains because you try to assign v[i], which is an int const *, to int *, through which the elements that v promised would not be changed could be changed. Since you don't attempt to do that later, just use an int const* to reassure the compiler.
Note that a will remain a pointer variable (so you will be able to reassign it), only it will point to integer constants (which you cannot then change through a). To declare a constant pointer, you would write
int *const a; // pointer constant to int variable,or
int const *const a; // pointer constant to int constant
The other error is similar in origin, although it is a bit more difficult to see why it is forbidden (since you're only adding const and don't try to take it away). Consider: Were an assignment from int** to int const ** allowed, you could write the following piece of code:
int const data[] = { 1, 2, 3, 4 }; // this is not supposed to be changed.
int *space;
int **p = &space;
int const **p2 = p; // this is not allowed. Were it allowed, then:
*p2 = data;
**p = 2; // this would write to data.
And that would be bad, mkay. If you instead write
int test1(const int *const *v, int num)
Now v is a pointer (variable) to pointer constant(s) to int constant(s). Since *v is then constant, the loophole is closed, and the compiler will accept it.

Related

g++ error message when signedness of int type doesn't match

This is easiest if I just start with a sample program. (Note: my question is not about how to fix this program. Please do not reply if your answer is just about how to fix this program and not about my question.)
void f(int &x) { x = 1; }
int main(int, char **)
{
unsigned int x;
f(x);
return 0;
}
Of course the problem here is that f wants to take a signed int as a reference, whereas I'm trying to pass it an unsigned int.
However, the compiler warning from g++ is mystifying:
<source>: In function 'int main(int, char**)':
<source>:7:5: error: cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'
7 | f(x);
| ^
<source>:1:13: note: initializing argument 1 of 'void f(int&)'
1 | void f(int &x) { x = 1; }
| ~~~~~^
In case that goes off the side of your screen and you don't want to scroll, the error message is "cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'"
My best guess here is that it tried to implicitly convert an lvalue of type unsigned int to an rvalue of type int and then got stuck. But why would it report results halfway through this attempt? And why does it not report the type unsigned int anywhere here?
clang is markedly more helpful:
<source>:7:3: error: no matching function for call to 'f'
f(x);
^
<source>:1:6: note: candidate function not viable: no known conversion from 'unsigned int' to 'int &' for 1st argument
void f(int &x) { x = 1; }
Question: What is going on here? I assume the compiler has to be trying a conversion to see if it helps and failing, but it makes no sense that the error message would then be issued halfway through this process and wouldn't reference the original type.
you have to pass the address of the unsigned int to the function.
void f(int *x) { *x = 1; }
int main(int, char **)
{
unsigned int x;
f(&x);
return 0;
}
This program will still give you an error as you are passing unsigned int as the function only accepts int.
You cannot pass an address of another data type to a function.
You must convert the pointer type to unsigned int before sending its address.
void f(int *x) { *x = 1; }
int main(int, char **)
{
unsigned int x;
f(reinterpret_cast<int *>(&x));
return 0;
}
OR
void f(int &x) { x = 1; }
int main(int, char **)
{
unsigned int x;
f((int&)x);
return 0;
}

Why does the compiler give the error "invalid conversion from const int * to int*?" [duplicate]

I receive the following error
$ g++ test.cpp
test.cpp: In function ‘int test1(const int**, int)’:
test.cpp:11:14: error: invalid conversion from ‘const int*’ to ‘int*’ [-fpermissive]
a=v[i];
^
test.cpp: In function ‘int main()’:
test.cpp:31:20: error: invalid conversion from ‘int**’ to ‘const int**’ [-fpermissive]
cout<<test1(c,2)<<endl;
^
test.cpp:4:5: error: initializing argument 1 of ‘int test1(const int**, int)’ [-fpermissive]
int test1(const int **v,int num)
^
when compiling the following code:
#include <iostream>
using namespace std;
int test1(const int **v,int num)
{
int *a;
int result=0;
// do somethings ....
for(int i=0;i<num;i++)
{
a=v[i];
// do somethings ....
result+=*a;
}
return result;
}
void test2(const int num)
{
cout<<num<<endl;
}
int main()
{
int a =5;
int b =8;
int **c;
c=new int *[2];
c[0]=&a;
c[1]=&b;
cout<<test1(c,2)<<endl;
test2(a);
delete [] c;
return 0;
}
i give an int to test2 which asks for const int and it is ok. however test1 does not accept int ** instead of const int **.
in the above code even typecast does not work:
a=(int *)v[i];
AFAIK, const means that I promise that I will not change the value of v and i didnt. however, the compiler gives me error.
Just write
int const *a; // or const int *a; which is the same.
...then const correctness will be preserved. The compiler complains because you try to assign v[i], which is an int const *, to int *, through which the elements that v promised would not be changed could be changed. Since you don't attempt to do that later, just use an int const* to reassure the compiler.
Note that a will remain a pointer variable (so you will be able to reassign it), only it will point to integer constants (which you cannot then change through a). To declare a constant pointer, you would write
int *const a; // pointer constant to int variable,or
int const *const a; // pointer constant to int constant
The other error is similar in origin, although it is a bit more difficult to see why it is forbidden (since you're only adding const and don't try to take it away). Consider: Were an assignment from int** to int const ** allowed, you could write the following piece of code:
int const data[] = { 1, 2, 3, 4 }; // this is not supposed to be changed.
int *space;
int **p = &space;
int const **p2 = p; // this is not allowed. Were it allowed, then:
*p2 = data;
**p = 2; // this would write to data.
And that would be bad, mkay. If you instead write
int test1(const int *const *v, int num)
Now v is a pointer (variable) to pointer constant(s) to int constant(s). Since *v is then constant, the loophole is closed, and the compiler will accept it.

initialise const struct with const pointer

I want to form a struct from const parameters passed to the function. As the parameters are const, i guess the struct has to be const too. However, it does not work with pointers.
The following code compiles (MinGW 4.9.2 32bit)
struct structType_t {
int b;
};
void func1(const int b) {
const structType_t s={b}; // invalid conversion from 'const int*' to 'int*' [-fpermissive]
// do something with s;
}
but with pointers it doesn't:
struct structType_t {
int* b;
};
void func1(const int* b) {
const structType_t s={b}; // invalid conversion from 'const int*' to 'int*' [-fpermissive]
// do something with s;
}
Why does the compiler try to cast away the const here?
So how can i use a const pointer to initialise a const structure?
If you change your struct to hold a const int* you can use it to store the const int* passed to the function, regardless of whether your s is const or not.
struct structType_t {
const int* b;
};
void func1(const int* b) {
const structType_t s={b};
// or
structType_t s2={b};
// do something with s or s2 ...
}
In the first case you are creating a copy of an int. Copy of const int does not have to be const so it works.
In the second case you are creating copy of a pointer to const int and assigning it to a pointer to an int - this is not allowed and that's why it does not compile.

C++ non const to const casting compilation error

the below code doesn't compile
void aaa(const int **a) {
}
int *a[] = {new int[2]};
aaa(a);
I got "cannot convert parameter 1 from 'int [1]' to 'const int *" in VS2010 and similar error in gcc
when I change my declaration to:
int const *a[] = {new int[2]};
or
const int *a[] = {new int[2]};
it compiles, but I don't understand why it doesn't accept a non const variable declaration
The type of a is int*[]; the type you want is int const**.
int*[] converts to int**, but this will not convert implicitly to
int const**. Consider the following code to understand why:
static int const ci = 42;
void aaa( int const** out )
{
*out = &ci;
}
int
main()
{
int* pa;
aaa( &pa ); // NOT LEGAL, because...
*pa = 0; // would now change ci
std::cout << ci << std::endl;
return 0;
}
As you can see, allowing this conversion would break const without
requiring a cast.
Depending on what you are doing, you might want to use:
void aaa( int const* const* out );
The implicit conversion of int** to int const *const * is legal.
(Otherwise, you'll need a const_cast somewhere, to tell the compiler
that you know what you're doing, and that it isn't really a problem.)
The function aaa expects a pointer-to-pointer-to-constant-int.
Your variable a is a pointer-to-pointer-to-int.
It is an error to assign the latter to the former.
both int const *a[] and const int *a[] is actually the same thing, matching the signature of aaa. If you tried int * const a[], that would be a different type (pointer-to-constant-pointer-to-int) and you would trigger the type error again.
If you want your function aaa to take a constant-pointer-to-pointer-to-int, you need to write aaa(int ** const a), but having a const-ness on parameter values has actually no effect on what you can call with.
Edit: "But isn't constness added implicitly - done with an implicit cast? (Which is the actual question)"
Constness can be implicitly added to the value you are passing, e.g.
void aaa(const int a) {}
int b=5;
aaa(b);
... or one level pointer
void aaa(const int* a) {}
int *b=new int;
aaa(b);
... but cannot be added deeper. For example this is invalid:
void aaa(const int** a) {}
int* b=new int;
int** c=&b;
aaa(c);
I think James Kanze explains it much better in his answer.

const parameter problems

#include <iostream>
void f(const int * & p)
{
int i =0;
i = p[0];
std::cout << i << std::endl;
}
int main()
{
int * p =new int[1];
p[0] =102;
f(p);
return 1;
}
The gcc compiler gives error for this code:
prog.cpp: In function ‘int main()’:
prog.cpp:16: error: invalid initialization of reference of type ‘const int*&’ from expression of type ‘int*’
prog.cpp:5: error: in passing argument 1 of ‘void f(const int*&)’
But if I change the "f" function into
void f(const int * const & p)
Everything is ok. Can somebody explain why const behaves this way? thanks.
Going from int* to const int* requires creating a temporary const int* pointer and binding the reference const int*& to that temporary.
The Standard forbids doing that creating of a temporary for non-const references. You therefor need to make the reference const as you did your fix.
This is because non-const references mean "I want to change the argument that the caller passes using that reference parameter". But if the caller needs to convert their argument and ends up passing a temporary, the point of the reference is for naught, and so the Standard deems it an error to try and pass the temporary.
If the first conversion (int * to const int * &) were allowed, then you could write an evil function like this:
const int really_const[] = {1,2,3};
void evil(const int * & p)
{
p = really_const;
}
int main()
{
int not_const[3];
int * p = not_const;
evil(p);
p[0] = 0; // Whoops: modifying a const object
}
The second conversion is fine, since it prevents the function from modifying the pointer in this way.