#include <iostream>
using namespace std;
int func(int arg0, int *arg1, int *arg2);
int main() {
int *b;
int z;
int a[10];
z = func(*a[0], &a[z], b+a[4]);
}
The following code above gives me an error "invalid type argument of unary '*' (have 'int')". I know that * when used in a declaration creates a pointer and when used with a variable name it gets the value stored at that pointer. In the function func(), it takes 3 parameters, 1 int and 2 int pointers. I think that the first argument passed into the function is giving me an error but I am not understanding why. Shouldn't *a[0] get the value of the first element in the a array which was declared as an int?
No, the * when used on a pointer dereferences the pointer. But a[0] is already equivalent to:
*(a + 0) // And since the offset is 0, this is equivalent to *a.
In other words, dereferencing a pointer to the beginning of the array that has been offset to give you the value of the item at a given 'index'. What YOU wrote is equivalent to:
**(a + 0) // And since the offset is 0, this is equivalent to **a.
Therefore, you are trying to 'dereference' an int, which won't work. Since * is not a valid unary operator for an int, that fails and causes the error you've seen to appear.
*a[0] is the same as **a.
Given the declaration int a[10];, it should be fairly clear that you are not able to dereference a twice.
If you want the first element of the array a, then that is simply a[0].
You could also simplify your example to this, and still get the same error:
int main() {
int a[10];
int b = *a[0];
}
Related
i was just playing with pointers as function arguments and i know this.
#include <iostream>
using namespace std;
void func(int *a)
{
*a+=1;
return;
}
int main()
{
int a=1;
cout<<a<<endl;//prints 1
func(&a);
cout<<a;//prints 2
return 0;
}
My question is why does below code act similar to the one above, more precisely
when we call func(&a) from main function in above case
// starting address of that 4 bytes(size of int) of data gets passed and in our function(func) this address is stored in local pointer 'a' and when we write *(a) our compiler knows to read 4 bytes of data because its an integer pointer.
in short, my question is
what exactly are we passing to 'func'
when we call func(a) where 'a' is a variable which stores an integer value
and what exactly func(int &a) means
#include <iostream>
using namespace std;
void func(int &a)
{
//cout<<*a;// error
a+=1;
// cout<<a<<endl;
}
int main()
{
int a=1;
cout<<a<<endl;// prints 1
func(a);
cout<<a;// prints 2
return 0;
}
sorry for bad english
One way to read pointers and references is that during declarations, the '*' can be replaced by "something that points to".
So:
int* a;
Means that 'a' is something that points to an integer (i.e. 'a' is a pointer).
In other places in the code (not declarations), the '*' can be replaced by "the thing pointed to by".
So:
*a = 5;
Means that "thing pointed to by 'a' becomes equal to 5". I.e. the integer which a points to is now 5.
In your first block of code, 'a' is just an integer type. when you write func(&a);, you are passing the address of 'a' (i.e. the name of the memory location which stores the value of 'a') to the function. The function is expecting an int* type, (something which points to an int), which is exactly what you've given it.
Within the function, 'a' is just the address of your variable. The function then takes this address, and says "increment the thing that 'a' points to".
In your secondblock of code, 'a' is again just an integer type. This time however, the function is expecting a reference variable (because the function definition is expecting an int& type.
So within the function, 'a' is the original variable - not a copy or a pointer to the original variable. The function says "increment the actual integer that was sent".
Read more
The two cases work similarly:
Case 1: func expects some pointer to some direction of an integer (int *a) which is, as you said, the first byte of a sizeof (int) bytes block according to the OS. When func is called you passed correctly that direction func(&a), so the compiler considers that call as something like: int p = &a; func(p); anyway a pointer to that direction is actually what is being passed.
Case 2: func expects some direction of some integer (int &a). When func is called you just passed correctly the value func(a), as all C++ compilers support reference paramenters, the compiler passes internally the direction of the passed value, func (&a). Notice if you try to call func like func (&a) an error will occur because it would be passed something like func (&&a) while the compiler is just waiting for (&a).
OBS: We can also look to the second case void func(int &a) as a reference which is different from a pointer with an example:
int a = 10;
int &b = a;
cout<<a; //10 is printed
cout<<b; //10 is printed
b = 20;
cout<<a; //20 is printed
cout<<b; //20 is printed
Whether you modify a reference to a (i.e b) or you modify a directly, you are modifying the same value beacause they stand at the same direction of a.
For example, in a function, "a" array and "first" array (normally arrays cannot take an integer as a parameter which is not const) can take "d" and "a1" as parameter). My question is that why this works like that, what is the difference between them?
#include <iostream>
using namespace std;
class BC {
int first[];
int modify(int a[], int d) {
int a1;
a[a1];
first[a1];
int sec[a1];
//a[d];
//first[d];
//sec[d];
}
};
a[a1]; // This is not an array declaration. This is referring to the a1-th element of the array.
first[a1]; // Same as above
int sec[a1]; // This IS a declaration and so SHOULD fail because a1 is non-const.
To further illuminate, you could say
a[a1] = 5;
or
int x = a[a1];
When you write
a[a1];
you are referring to an element of an array, but without doing anything with the value. This is allowed even though it seems pointless. Potentially, the [] operator can be overidden and hence this statement COULD do something. That's why it's allowed.
In my below code , It compiles and runs when I use it as a c file , but gives an error when I run it as cpp file.
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
struct ploc_t {
int num;
ploc_t *right;
};
ploc_t *create_ploc(int *point , int *triangles, int n , int m){
// just for testing
ploc_t *result;
result=(ploc_t*)malloc(sizeof(ploc_t));
return result;
}
int main( )
{
int points[1][2];
int triangles[1][2];
points[0][1]=2;
points[0][2]=4;
triangles[0][1]=8;
triangles[0][2]=6;
create_ploc(points,triangles,3,4);
}
Error which I get in when using cpp file is :
Invalid arguments candidates are: plot_t(int*,int*,int,int)
Why is this error? and how can it be resolved?
The difference between C and C++ in this instance is that in C, what you're doing (passing a pointer to int[2] to a function expecting a pointer to int) is legal although discouraged, whereas in C++ you're not allowed to do it. So in C, the compiler will issue a warning. If you're not using the -Wall flag, you might not see the warning. In C++, it doesn't matter whether you used -Wall or not (although you always should) because it's an error and the compile will fail.
Arrays passed as parameters "decay" to a pointer to the array element type. (That's not the only case in which arrays decay to pointers, but it's the one relevant to this question.) Your arrays are of type int[][2], so the element type is int[2]. Consequently, when you use them as arguments, they decay to int(*)[2], which is C/C++'s idiosyncratic way of saying "a pointer to a two-element array of ints".
What's the difference between a pointer to an int and a pointer to an int[2]? One important difference is the size of the target:
int a[2];
int* p = a;
p++;
// p now points to a[2]; it was incremented by sizeof(int)
int aa[10][2];
int(*pp)[2] = aa;
pp++;
// pp now points to aa[2]; it was incremented by sizeof(int[2])
Rather than fighting with the syntax for pointer to arrays, you probably want to define you function to accept two-dimensional arrays:
ploc_t *create_ploc(int points[][2], int triangles[][2], int n , int m);
But you could, with exactly the same semantics, write out the decayed types:
ploc_t *create_ploc(int (*points)[2], int (*triangles)[2], int n , int m);
Looking at your main:
int points[1][2];
int triangles[1][2];
"points" and "triangles" are two-dimensional arrays. The first two arguments to create_ploc() are pointers to integers. Passing these two-dimensional arrays directly into the function is not passing a pointer. I'm not sure exactly what you want to do, but a couple of ways to solve this are:
1)
int points[1];
int triangles[1]; // both one-dimensional arrays of ints (int*)
2)
create_ploc(points[0],triangles[0],3,4); // passing in a one-dimensional array of ints (int*)
int main()
{
int a[]={2,3,4,5,6};
int j;
for(j=0;j<5;j++)
{
printf("%d\n",*a);
a++;
}
return;
}
gives "Lvalue required" error but
int main()
{
int a[]={2,3,4,5,6};
int *p,j;
p=a;
for(j=0;j<5;j++)
{
printf("%d\n",*p);
p++;
}
return;
}
doesn't. why????
Though closely related, arrays are not pointers. The name of the array is just a label to identify some allocated memory (hence, the Lvalue error when you try to modify it).
An array is not a pointer. In most expressions, an array is converted to a pointer automatically. The result of this conversion is no longer the array; it is just a pointer value.
The ++ operator cannot operate on a mere value. It must have an object to act on.
For example, consider int x = 3; (x+5)++;. The result of x+5 is 8. It is not x. The result is just a value, not an object, so there is no object containing 8 that ++ can operate on. This is an error.
Similarly, if a is an array of int, then a++ is equivalent to ((int *) a)++. The ++ is not trying to act on the a; it is trying to act on the result of converting a to a pointer.
An array expression is always converted to a pointer to the first element except when the array expression is the operand of sizeof, &, or _Alignof or is a string literal used to initialize an array.
This will display all the array data.
#include <iostream>
#include <vector>
#include <stdio.h>
using namespace std;
int main()
{
int a[]={2,3,4,5,6};
int *p,j;
p=a;
for(j=0;j<5;j++)
{
printf("%d\n",p[j]);
}
return 0;
}
From here: https://stackoverflow.com/a/3473454/499125
int ( &fillarr( int (&arr)[5] ) )[5] { // no decay; argument must be size 5
return arr;
}
The definition above can force the compiler to become size-aware of its parameters. This statement seems complex to me. Can someone give an anatomy of this statement or explain how does the statement achieves the size-awareness?
Can this be extended to handle multiple parameters?
It all boils down to being able to read the declaration. A simpler way of writing exactly the same would be:
typedef int int5[5]; // create a typedef
int5& fillarr( int5& ) {
}
As of the exact way of reading the original declaration, just break it into pieces:
int (&fillarr( int (&arr)[5] ))[ 5 ];
^^^^^^^^^^^^^ // A: reference to array of 5 int
^^^^^^ ^^^^^^ // B: reference to array of 5 int
^^^^^^^^ ^ // C: function taking A and returning B
You can split understanding this in two parts, 1) the return value and 2) the parameter type:
int ( &fillarr() )[5] {
static int arr[5];
return arr;
}
We can have a look at the type: int (&fillarr())[5]. To understand this, unfortunately the old C rule: "Declaration is like usage in expressions" doesn't work with references, so let's have a look at a similar declaration instead:
int (*fillarr())[5];
This is a function that returns a pointer instead of a reference to an array of size 5. How do I figure? Well, assume we do have a function f that returns a pointer to an array of ints, how would we access the fifth element? Let's see, we first have to call the function: f(). Then we have to dereference the result *f() and then access the fifth element (which doesn't exist, but ignore that) (*f())[5] which is an int. This is exactly the declaration syntax:
int x;
int (*f())[5];
x = (*f())[5];
// ^^^-------- call f -> yields pointer to array of 5 ints
// ^----------- dereferene the result of f -> yields array of 5 ints
// ^^^---- access the fifth element
Now you only substitute the * for an & because you're returning a reference in your example.
The parameter syntax works analogously.