I come from a background of C# and Java and I can't seem to understand what casting with pointers means in C++.
For example:
int x = 1;
char c = *((char*)&x);
What does it do? What it is useful for?
In both your examples you're making mistakes making the code not compile. So I'll assume you're trying to do the following:
int x = 1;
char c = *((char*)&x);
Depending on your architecture, c will now have either the value of the least or the most significant byte of x. In this example this would be either 0 or 1 (this can actually be used to detect the byte ordering).
Your second example won't work, cause you're trying to ignore the const resulting in an illegal operation/bad cast (this is also called "const correctness").
Edit: Regarding your comment about "what does it mean?":
In expressions:
&somevariable will return the address of somevariable.
*somevariable will assume the contents of somevariable are the address of the actual value, which is then returned.
In declarations:
datatype is a normal variable/object. This is passed "by value".
datatype& is a reference. This works exactly like normal variables in Java/C# and is passed by reference.
datatype* is a pointer. This just contains the address where the actual value is located (see above) and is essentially passed by reference as well.
Actual casts work pretty much similar to Java/C#, but pointers are just that: They point to the location of the actual value. While this might confuse you, pointers in C/C++ work pretty much like the standard variables/references used in Java/C#.
Look at this:
MyClass x; // object of MyClass
MyClass *x; // pointer to an object of MyClass - the actual value is undefined and trying to access it will most likely result in an access violation (due to reading somewhere random).
MyClass *x = 0; // same as above, but now the default value is defined and you're able to detect whether it's been set (accessing it would essentially be a "null reference exception"; but it's actually a null pointer).
MyClass &x = MyClass(); // creating a new reference pointing to an existing object. This would be Java's "MyClass x = new MyClass();"
Casting in C++ works just like casting in Java, no pointers involved.
int x = 1;
char c = (char) x; // Lose precision
However, what you are doing here:
int x = 1;
char *c = (char *)x;
is telling the compiler that the value of x is the address of a character. It is equivalent to
char *c;
c = 1; // Set the address of c to 0x0000000000000001
There are very few times you need to do this.
There are two fundamentally different concepts in C++ which are both sometimes referred to as "casting": One is conversion, and one is reinterpretation.
Conversion creates a new object with the "same value" as an existing object, but of a different type. Here are some examples:
Example 1: type promotion
// 1a: promote int to double to get the correct type of division
int numerator = rand(), denominator = rand();
double d = double(numerator) / double(denominator);
// 1b: convert int to double to achieve a particular argument deduction
int n;
template <typename T> void do_numeric_stuff(T x) { /* ... */ }
do_numeric_stuff(double(n));
Example 2: Derived-to-base conversion
struct B { }; struct D : B { };
D x;
D * p = &x; // pointer to x
B * q = p; // implicit conversion; may change the value!
On the other hand, reinterpretation allows us to treat one variable as though it was another one. About the only correct and useful application for this is serialization, in one form or another.
Example 3: Serialization
std::ofstream file("output.bin"); // output file
char large_buffer[HUGE]; // in-memory buffer
unsigned int n = get_data();
char const * p = reinterpret_cast<char const *>(&n);
file.write(p, p + sizeof n); // write the bytes of `n`
std::copy(p, p + sizeof n, large_buffer); // ditto
std::copy(large_buffer + 17, large_buffer + 17 + sizeof n,
reinterpret_cast<char *>(&n)); // repopulate `n` from buffer
The standard says that it is undefined behaviour to access an object through a pointer that is not of the correct type (also called "type punning"). While it is OK to store an object pointer in, say, a void* and then convert it back and use it, it is not OK to treat a float as though it was an integer, etc. The only acceptable way of accessing one object as though it was another is the one I demonstrated, namely treating an object of type T as though it was an array char[sizeof(T)] — that is, you are allowed to access the underlying binary representation of every object.
You should avoid c-type casts like (char*) by all means. If you really have to do a type cast have a look at dynamic_cast, static_cast and reinterpret_cast.
But as already stated, you rarely need casting at all.
Have a look here for fruther information:
http://www.cplusplus.com/doc/tutorial/typecasting/
http://www.parashift.com/c++-faq/static-typing-and-cpp.html
http://www.parashift.com/c++-faq-lite/print-char-or-ptr-as-number.html
I used many time ago that idiom to access HW at specified address, on custom IO board. So for instance to write at PIC (programmable interrupt controller) to reset some flag (fictious code):
#define PIC_LOC 0x1000
#define PIC_ENABLE_PORT *((char*)(PIC_LOC+0x10))
#define BIT_ENABLE (1 << 3)
...
PIC_ENABLE_PORT |= BIT_ENABLE;
...
Related
Hello im confused by typecasting pointers.
I understand that void can hold any type.
So if i have an int * with a value inside of it then i make a void * to the int * can i then typecast it to a char?
It's quite hard to explain what i mean and the title might be wrong but will this work?
And is it safe to do this. I've seen it used quite alot in C. Is this bad practise.
int main() {
int* a = new int{ 65 };
void* v = static_cast<int*>(a);
std::cout << *(static_cast<char *>(v));
}
I understand that void can hold any type.
You understand it wrong. Pointer does not hold data, it points to it. So integer pointer points to memory with holds integer, float pointer points where float is etc. Void pointer just points to some memory, but it says - I do not know what kind of data is there.
Now conversion. Technically you can convert almost any pointer to any (there are exceptions like function pointers or pointers to a member, but they are completely different beasts and it is not what you are asking about) as they all just pointers. But problem happens when you try to access memory where they point to. So if you have int in memory and try to read it as float or vice versa - that's illegal. Now therte is one exception - you can access any data through pointer to char (or unsigned char) as char represents byte. Void pointer is irrelevant here, you can convert from pointer of one type to another without void * involved:
int main() {
int* a = new int{ 65 };
unsigned char *uptr = reinterpret_cast<unsigned char *>( a );
for( size_t i = 0; i < sizeof(int); ++i )
std::cout << static_cast<unsigned int>( uptr[i] ) << ' ';
}
Live example
Note I casted uptr[i] to unsigned int, that is to print bytes as numbers, as C++ stream ( std::cout in this case) will print character as symbol, which would be meaningless in this case.
First any object pointer can be cast to void*. That's the generic "could be anything" solution inherited from C and you should not use it. The C++ way is to use template<typename T> and T* for such cases where you need an anything pointer.
Secondly any object pointer can also be cast to char * as a special case. Casting to char* gives you access to the memory representation of the object. It does not convert the object to a char or anything, you get access to the raw bits for the value stored in the object.
So the reason why casting to void* and then to char* works is that casting any object pointer to char* is valid. The intermediate step to void* is not needed at all.
This only works for char* or unsigned char* or any other variant of char pointer, including std::byte*. You can not static_cast an int* to float* for example and using a void* and intermediate step will not make that work either.
Note: The value printed by the code is implementation defined since the memory representation of an int and a char is defined by the implementation. Specifically their endianness and size of an int and the signedness of char. Apart from that it perfectly valid code.
The question though is: Why do you want to do this?
I am confident I understand the meaning of rvalue and lvalue. What's not clear to me is whether a dereference is an rvalue.
Consider this:
#define GPIO_BASE 0x20200000
#define GPFSEL1 (*(volatile unsigned int *)(AUX_MU_BASE + 0x4))
GPFSEL1 is a dereference to an unsigned int pointer. That unsigned int pointer is a physical address of a hardware register.
I have read that this is a common technique in bare metal programming to access hardware registers directly. So far I am able to use it with no problem.
Now I want a reference to GPFSEL1 as a member of a struct. Is this possible?
struct MotorControl
{
u8 pwm_pin;
u8 ctrla_pin;
u8 ctrlb_pin;
volatile unsigned int* MYGPFSEL; // this is not the same thing so does not work
}
Given this function below, what's the correct way to reference GPFSEL1 which is defined elsewhere and how to dereference it to set the its value?
MotorContorl group
group.MYGPFSEL = ?
void set(unsigned char pin_number, bool high)
{
if (high)
{
// how to correct this statement
group.MYGPFSEL |= 1<< pin_number;
}
}
"Dereference" is a verb - you dereference a pointer to get access to the value it points to.
The type conversion is straightforward - if you have a pointer to an integer, and you dereference it, you're now working with an integer. It's an lvalue, as it (by construction) takes up a location in memory, and one that you can (usually) modify.
int x = 10;
int* xptr = &x;
*xptr = 5; // *xptr is an lvalue
std::cout << "X: " << x << std::endl; // Prints 5
However, the pointer needs to point to a place in memory. If you just start with
int* xptr;
*xptr = 5;
You're going to get an error, since you're trying to dereference a pointer that doesn't point to a valid memory address. (And if it does, that's purely by coincidence, and you'll incorrectly change the value.)
If you want a reference to GPFSEL1 as a member of your MotorControl struct, you will not be able to initialize the struct without passing it the object to which it will reference. What you probably want instead is a pointer inside the struct, which is much easier to work with:
MotorControl myMotorControl;
myMotorControl.MYGPFSEL = GPFSELF1;
Your current approach will work fine, you just need to initialize the member variable appropriately, e.g.
struct MotorControl control;
control.MYGPFSEL = (volatile unsigned int *)(AUX_MU_BASE + 0x4);
alternatively you can initialize it as
control = &GPFSEL1;
given that you have defined GPFSEL1 as in your original question:
#define GPFSEL1 (*(volatile unsigned int *)(AUX_MU_BASE + 0x4))`
Now you can read the register:
foo = *control.MyGPFSEL;
or set the register:
*control.MyGPFSEL = 123;
This is an easy question to answer, a dereference can be the left-hand side of an assignment so it's an l-value.
Easy case to illustrate:
char sz[] {"hello"};
*sz = 'j';
If something can be the left side of an assignment it is by definition an l-value.
I'm new to programming and I'm trying to wrap my head around the idea of 'pointers'.
int main()
{
int x = 5;
int *pointerToInteger = & x;
cout<<pointerToInteger;
}
Why is it that when I cout << pointerToInteger; the output is a hexdecimal value, BUT when I use cout << *pointerToInteger; the output is 5 ( x=5).
* has different meaning depending on the context.
Declaration of a pointer
int* ap; // It defines ap to be a pointer to an int.
void foo(int* p); // Declares function foo.
// foo expects a pointer to an int as an argument.
Dereference a pointer in an expression.
int i = 0;
int* ap = &i; // ap points to i
*ap = 10; // Indirectly sets the value of i to 10
A multiplication operator.
int i = 10*20; // Needs no explanation.
One way to look at it, is that the variable in your source/code, say
int a=0;
Makes the 'int a' refer to a value in memory, 0. If we make a new variable, this time a (potentially smaller) "int pointer", int *, and have it point to the &a (address of a)
int*p_a=&a; //(`p_a` meaning pointer to `a` see Hungarian notation)
Hungarian notation wiki
we get p_a that points to what the value &a is. Your talking about what is at the address of a now tho, and the *p_a is a pointer to whatever is at the &a (address of a).
This has uses when you want to modify a value in memory, without creating a duplicate container.
p_a itself has a footprint in memory however (potentially smaller than a itself) and when you cout<<p_a<<endl; you will write whatever the pointer address is, not whats there. *p_a however will be &a.
p_a is normally smaller than a itself, since its just a pointer to memory and not the value itself. Does that make sense? A vector of pointers will be easier to manage than a vector of values, but they will do the same thing in many regards.
If you declare a variable of some type, then you can also declare another variable pointing to it.
For example:
int a;
int* b = &a;
So in essence, for each basic type, we also have a corresponding pointer type.
For example: short and short*.
There are two ways to "look at" variable b (that's what probably confuses most beginners):
You can consider b as a variable of type int*.
You can consider *b as a variable of type int.
Hence, some people would declare int* b, whereas others would declare int *b.
But the fact of the matter is that these two declarations are identical (the spaces are meaningless).
You can use either b as a pointer to an integer value, or *b as the actual pointed integer value.
You can get (read) the pointed value: int c = *b.
And you can set (write) the pointed value: *b = 5.
A pointer can point to any memory address, and not only to the address of some variable that you have previously declared. However, you must be careful when using pointers in order to get or set the value located at the pointed memory address.
For example:
int* a = (int*)0x8000000;
Here, we have variable a pointing to memory address 0x8000000.
If this memory address is not mapped within the memory space of your program, then any read or write operation using *a will most likely cause your program to crash, due to a memory access violation.
You can safely change the value of a, but you should be very careful changing the value of *a.
yes the asterisk * have different meanings while declaring a pointer variable and while accessing data through pointer variable. for e.g
int input = 7;
int *i_ptr = &input;/*Here * indicates that i_ptr is a pointer variable
Also address is assigned to i_ptr, not to *iptr*/
cout<<*i_ptr;/* now this * is fetch the data from assigned address */
cout<<i_ptr;/*it prints address */
for e.g if you declare like int *ptr = 7; its wrong(not an error) as pointers ptr expects valid address but you provided constant(7). upto declaration it's okay but when you go for dereferencing it like *ptr it gives problem because it doesn't know what is that data/value at 7 location. So Its always advisable to assign pointers variable with valid addresses. for e.g
int input = 7;
int *i_ptr = &input;
cout<<*i_ptr;
for example
char *ptr = "Hello"; => here * is just to inform the compiler that ptr is a pointer variable not normal one &
Hello is a char array i.e valid address, so this syntax is okay. Now you can do
if(*ptr == 'H') {
/*....*/
}
else {
/*.... */
}
General syntax of pointer declaration: data-type *pointer_name;
A pointer is a variable whose value is the address of another variable, i.e., direct address of the memory location. Like any variable or constant, you must declare a pointer before you can use it to store any variable address. The data type of pointer must be same as the variable, which the pointer is pointing.
Why is it important that a pointer variable should contain the address of a variable of the same data type?
As a pointer has nothing to do with the value of another variable, why can't an integer pointer have the address of float data type variable?
Correct form:
int a = 10 ;
int *ptr = &a ;
ERROR, type mismatch
float a;
int *ptr; ptr = &a;
Because when you increase a pointer like
ptr++;
it will point to an address that is one multiplied with the size of the data type. If you do
ptr+=2;
and the data type is occupying 4 bytes which would be the case if the pointer was declared as
float *ptr;
the pointer will increase with 8 byte positions.
Before answering that, let me ask you, if it were valid, what would you do with such a pointer?
Suppose you have (inside a function)
float a;
int *ptr; ptr = &a;
*p = 1;
++*p;
return *p;
In such a case, there is no reason at all not to just use an int variable if it's an int you want.
Suppose you have (inside a function)
float a;
int *ptr; ptr = &a;
a = 3.14;
++*p;
return a;
In this sort of object aliasing, there can be a use, but allowing constructions like this is a pain for compilers. Compilers are free to assume, and some do assume, that the modification of *p has no effect on the value of a, so still return 3.14 unmodified;
If the latter case is something you're looking for, you can use union, which both makes your code clearer to other readers, and makes your code clearer to the compiler:
union {
float f;
int i;
} u;
u.f = 3.14;
++u.i;
return u.f;
So, to answer: it's to prevent you from shooting yourself in the foot. It's not allowed because there is no way such a pointer is useful. The one case where it could be useful is actually a case where it doesn't work, and there is another language construct that does handle it, and handles it correctly.
There is also the simple matter of dereferencing the pointer.
something = *pointer;
How much data should be read when the pointer is dereferenced? The compiler must know the data type in order to perform operations on the data like fetch, add, etc.
It's a safety feature. A pointer of one type pointing to a variable of another is a recipe for disaster; it has almost no legitimate purpose and almost anything you do with it is dangerous, especially if the types are of different sizes.
You can override this feature by means of casting. If you do so, you can no longer claim that you didn't know you were doing something dangerous.
It is possible for pointers to point to any data type: that's exactly what void pointers are for. You can use a void * to point to any data type1, and then you can get the original pointer back.
float f = 1.0f;
int i = 12;
void *p = &f;
p = &i;
Of course, you can't dereference a void pointer without first casting it back to the correct pointer type. It is up to you to ensure that the pointer type is correct.
// In C, this is valid: implicit conversions to void * and back.
float f = 1.0f;
void *p = &f;
float *fp = p;
printf("*fp = %f\n", *fp);
// In C++, you have to use a cast:
float *fp = static_cast<float *>(p);
Void pointers have limitations: you cannot dereference them, and you cannot do any pointer arithmetic.
1: Function pointers should not be cast to void *.
Lets understand it with an example.
int main()
{
char i = 8;
int *ptr = &i;
printf("Value of i = %d", *ptr);
return 0;
}
Ans: It will print some garbage because it dereferenced 4 byte in memory.
so if you do char *ptr = &i;, it will dereference 1 byte and so on..
It will give correct answer.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
c++ * vs & in function declaration
I know that this probably seems like an incredibly elementary question to many of you, but I have genuinely had an impossible time finding a good, thorough explanation, despite all my best Googling. I'm certain that the answer is out there, and so my search terms must be terrible.
In C++, a variety of symbols and combinations thereof are used to mark parameters (as well as arguments to those parameters). What, exactly, are their meanings?
Ex: What is the difference between void func(int *var) and void func(int **var)? What about int &var?
The same question stands for return types, as well as arguments. What does int& func(int var) mean, as compared to int* func(int var)? And in arguments, how does y = func(*x) differ from y = func(&x)?
I am more than happy to read enormous volumes on the subject if only you could point me in the right direction. Also, I'm extremely familiar with general programming concepts: OO, generics/templates, etc., just not the notation used in C/C++.
EDIT: It seems I may have given the impression that I do not know what pointers are. I wonder how that could be :)
So for clarification: I understand perfectly how pointers work. What I am not grasping, and am weirdly unable to find answers to, is the meaning of, for example 'void func(int &var)'. In the case of an assignment statement, the '&' operator would be on the right hand side, as in 'int* x = &y;', but in the above, the '&' operator is effectively on the left hand side. In other words, it is operating on the l-value, rather than the r-value. This clearly cannot have the same meaning.
I hope that I'm making more sense now?
To understand this you'll first need to understand pointers and references. I'll simply explain the type declaration syntax you're asking about assuming you already know what pointers and references are.
In C, it is said that 'declaration follows use.' That means the syntax for declaring a variable mimics using the variable: generally in a declaration you'll have a base type like int or float followed something that looks like an expression. For example in int *y the base type is int and the expression look-alike is *y. Thereafter that expression evaluates to a value with the given base type.
So int *y means that later an expression *y is an int. That implies that y must be a pointer to an int. The same holds true for function parameters, and in fact for whole function declarations:
int *foo(int **bar);
In the above int **bar says **bar is an int, implying *bar is a pointer to an int, and bar is a pointer to a pointer to an int. It also declares that *foo(arg) will be an int (given arg of the appropriate type), implying that foo(arg) results in a pointer to an int.¹ So the whole function declaration reads "foo is a function taking a pointer to a pointer to an int, and returning a pointer to an int."
C++ adds the concept of references, and messes C style declarations up a little bit in the process. Because taking the address of a variable using the address-of operator & must result in a pointer, C doesn't have any use for & in declarations; int &x would mean &x is an int, implying that x is some type where taking the address of that type results in an int.² So because this syntax is unused, C++ appropriates it for a completely different purpose.
In C++ int &x means that x is a reference to an int. Using the variable does not involve any operator to 'dereference' the reference, so it doesn't matter that the reference declarator symbol clashes with the address-of operator. The same symbol means completely different things in the two contexts, and there is never a need to use one meaning in the context where the other is allowed.
So char &foo(int &a) declares a function taking a reference to an int and returning a reference to a char. func(&x) is an expression taking the address of x and passing it to func.
1. In fact in the original C syntax for declaring functions 'declarations follow use' was even more strictly followed. For example you'd declare a function as int foo(a,b) and the types of parameters were declared elsewhere, so that the declaration would look exactly like a use, without the extra typenames.
2. Of course int *&x; could make sense in that *&x could be an int, but C doesn't actually do that.
What you're asking about are called pointers (*), and reference to (&), which I think is best explained here.
The symbols & and * are used to denote a reference and pointer type, respectively.
int means simply the type 'int',
int* means 'pointer to int',
int& means 'reference to int',
A pointer is a variable which is used to store the address of a variable.
A reference has the syntax of its base type, but the semantics of a pointer to that type. This means you don't need to dereference it in order to change the value.
To take an example, the following code blocks two are semantically equivalent:
int* a = &value;
*a = 0;
And:
int& a = value;
a = 0;
The main reasons to use pointers or references as an argument type is to avoid copying of objects and to be able to change the value of a passed argument. Both of these work because, when you pass by reference, only the address is copied, giving you access to the same memory location as was "passed" to the function.
In contrast, if a reference or pointer type is not used, a full copy of the argument will be made, and it is this copy which is available inside the function.
The symbols * and & have three meanings each in C++:
When applied to an expression, they mean "dereference" and "address-of" respectively, as you know.
When part of a type, they mean "pointer" and "reference", respectively.
Since C++ doesn't care about arbitrary spacing, the declaration int *ptr is exactly the same as the declaration int* ptr, in which you can now more clearly see that this is an object called ptr of type int*.1
When used between two expressions, they mean "multiply" and "bitwise AND", respectively.
1 - though, frustratingly, this isn't actually how the internal grammar reads it, thanks to the nasty legacy of C's type system. So avoid single-line multi-declarations involving pointers unless you want a surprise.
Ex: What is the difference between 'void func(int *var)' and 'void
func(int **var)'? What about 'int &var'?
The same question stands for return types, as well as arguments. What
does 'int& func(int var)' mean, as compared to 'int* func(int var)'?
And in arguments, how does 'y = func(*x)' differ from 'y = func(&x)'?
(1)
<return type> <function name> <parameters>
void func (int *var)
<parameter> here int *var is a pointer to integer, ie it can point to
an array or any buffer that should be handled with integer pointer
arithmetic. In simple terms , var holds the address of the respective
**actual parameter.**
eg: int arr[10];
func(arr);
int a = 33;
func(&a);
Here, &a means we are explicitly passing address of the the variable 'a'.
(2)
int m = 0;
int &var = m;
Here var means reference, ie it another alias name for variable 'm' ,
so any change 'var' makes will change the contents of variable 'm'.
var = 2; /* will change the actual contents of 'm' */
This simple example will not make sense , unless you understand the context.
Reference are usually use to pass parameter to function, so that changes made by
the function to the passed variable is visible at the caller.
int swap(int &m, int &n) {
tmp = m;
m = n;
n = tmp;
}
void main( void ) {
int x = 1, y = 2;
swap(x, y);
/* x = 2, y =1 */
}
(3)
'int& func(int var)' mean, as compared to 'int* func(int var)'?
int& func(int var) means the function returns a reference;
int* func(int var) means the function returns a pointer / address;
Both of the them has its context;
int& setNext() {
return next;
}
setNext() = previous;
where as
int* setNext() {
return &next;
}
int *inptr;
inptr = setNext();
*inptr = previous;
In the previous two lines,
int *inptr <- integer pointer declaration;
*inptr <- means we are accessing contents of the address pointed by inptr;
ie we are actually referring to 'next' variable.
The actual use is context specific. It can't be generalized.
(4)
how does 'y = func(*x)' differ from 'y = func(&x)'?
y = func(&x) is already explained.
y = func(*x) , well i'm not sure if you actually meant *x.
int swap(int *m, int *n) {
tmp = *m;
*m = *n;
*n = tmp;
}