what does "pointer(char*)pointer2" do?

Pages: 12
Hi everyone!

so with the below code...

I understand how all of it works, except the line.

pchar=(char*)data;

to catch you up, "pchar" is a char pointer, and data is a void pointer, that in the main function can get the memory address of a variable.

then I follow it through and understand all the lines of code except the one I said above

The Entire Function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// increaser
#include <iostream>
using namespace std;

void increase (void* data, int psize)
{
  if ( psize == sizeof(char) )
  { char* pchar;
  pchar=(char*)data; // I don't understand what this is.
  ++(*pchar); }

  else if (psize == sizeof(int) )
  { int* pint;
  pint=(int*)data; // or here
  ++(*pint); }
}


so if you could explain to me what that one line of code does it would be very appreciated.

Thanks.
Last edited on
1
2
"pchar" is an int pointer
char* pchar;
What? You are contradicting yourself.

(char*)data is a cast to char pointer type. As you cannot assign void pointer dorectly to non-void one, you need to cast it appropriate type.

Your function is written for C. You shouldn't write such functions in C++. Templated function would be safer and intuitive here.

At least use safer static_cast<char*>(data) instead of c-style cast here. Safety blanket as there is gaping security hole in form of psize variable.
the (char*)expression is an old style casting operator.
it casts the type of its operand to be of another type.
in this case, this expression:
(char*)data evaluates to a char pointer that has the same value stored in data.
why do you need this?
data is of type void* and pchar is of type char*, you can't assign data to pchar unless they are of the same type, or their types are a special case:
like a double can be implicitly cast to an int.
and a base class pointer can be assigned the address of a derived class object.
you use a casting operator to solve this problem.
any way, this is an old style casting, you should use the C++ casting operators, try using this line instead:
pchar = static_cast < char* > (data);
i hope that was clear enough, for more info, see the casting operators:
http://www.cplusplus.com/doc/tutorial/typecasting/
hehehe, i was writing my own comment and i didn't see that MiiNiPaa actually answered.
i'm starting to feel that you are on a race with every body:
"who ever answers more questions win, ready, set, go go go!" ^_^.
static_cast has the same semantics as a C-style cast in (T1 *)->(T2 *) conversions if the constness of T1 and T2 are equal. Using one or the other is equivalent in OP's case.
ok, there was a discussion about using C style in a C++ program, i don't know if you noticed it helios, here it is though:
http://www.cplusplus.com/forum/beginner/103362/

i found that, when there's a C++ way to solve your problem, use it.
when there's noway but to use C code, then it would be OK to use it.

anyway, your note was useful for me, thanks.
Personally, I disagree. For something to be worth using, it must add something. const_cast, static_cast, and reinterpret_cast cost some clarity but add nothing in most situations.
They do have some value in template code to reject at compile time template instances that could incur in undefined behavior. For example, by preventing a cast that removes constness. I myself haven't seen much use for that, but I do recognize its usefulness.
Last edited on
helios wrote:
static_cast has the same semantics as a C-style cast in (T1 *)->(T2 *) conversions if the constness of T1 and T2 are equal.
No.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct x
{
    int a;
};

struct y
{
    double b;
};

int main()
{
    x* a;
    y* b = static_cast<y*>(a); //Will issue compile-time erro
    y* c = (y*)a; //Will not
}
C-style cast works like static_, const and reinterpret cast at once. And you cannot be sure that types you casting between are compatible. So do not use C-style casts in C++

EDIT: As I mentioned earlier it is a C-function. In C++ it would be better to use templates for that.
Last edited on
Okay, thanks everyone, this isn't actually mine, I was reading the c++ documentation from this website (I'm still learning to write c++), and this was in it, and I couldn't understand what was happening so I asked you guys anyway, thanks.


miinpaa, I fixed that error were I was contridicting my self, that was an accident.
Last edited on
Og The Trog you just need the first two comments, i think they are enough to answer your question.
we just had a little discussion.

and as always, hope that was useful.
Will issue compile-time erro
You're right. Huh. The documentation I read was pretty unclear.
Well, add "if the compiler accepts it" to my sentence.
I think the compiler rejecting a program belongs to grammar not semantics, though, which would make my statement technically correct. :-)

And you cannot be sure that types you casting between are compatible.
If the types were compatible, you'd use dynamic_cast. If you're casting with something else, it's because you know the types are incompatible.
If the types were compatible, you'd use dynamic_cast.
Sometimes types are convertible into each other: use static cast. Sometimes yo need to cast downward in inheritance tree: dynamic cast. Someimes types are binary compatible: use reinterpret_cast:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
struct A
{
    uint8_t d, c, b, a;
};

struct B
{
    uint32_t value;
};

int main()
{
    B* x = new  B;
    x->value = 2130706433;
    A* y = reinterpret_cast<A*>(x);
    std::cout << static_cast<int>(y->a) << '.' <<
                 static_cast<int>(y->b) << '.' <<
                 static_cast<int>(y->c) << '.' <<
                 static_cast<int>(y->d);
}
You know what you are doing here (You can use unions of course...)

If you're casting with something else, it's because you know the types are incompatible.
1
2
int x = 5;
something(static_cast<double>(x));//Calling double overload 
I have used incorret term. Not compatible, but convertible. I can be sure that conversion from one type to other do what I intended.
In each of your examples, you know with certainty the type of the thing you're casting. You're gaining no additional safety.
We gain safety against programmer error (I cannot static_cast into non-convertible type) and possible type changes in future (types I cast from/to could be some typedefs which can change in the future)
> For something to be worth using, it must add something.
> const_cast, static_cast, and reinterpret_cast cost some clarity but add nothing in most situations.

C++ casts give programmers a chance to state their intent more clearly and for the compiler to catch unintended errors. The primary benefit of the compile-time C++ casts is decreased power in casting, allowing me to write code that is more type-safe; protecting me from unintentionally doing things I never wanted to do in the first place.

The syntax of C-style casts is syntax without semantics - it is the same for every cast operation, making it is impossible for the compiler (or programmers who read the code) to ascertain the intended purpose of the cast.

What does this mean?: x = T(y) ; (pointers or references are involved)

Is it a cast from a base class pointer to a derived class pointer?
Does the cast remove the const-ness of an object?
Or, is it a conversion of one type to a completely unrelated type?
It is impossible to tell from the syntax. We just don't know. It depends on the type T and the types of x and y. As a result, the cast is harder to comprehend, not only by people, but also by compilers which are unable to detect errors.

C style casts work this way: I tell the compiler - "shut up and do whatever is necessary to convert this expression to that, possibly totally unrelated, type. I am in control here, I know what I'm doing and I never make mistakes!".

I remember an early C++ program that I was involved with. The design was terrible - we were novices - and a lot of casting up and down the hierarchy was needed. We were not allowed to use dynamic_casts in embedded software; yeah, those were the bad old days. And we naively used C-style casts all around; we knew that C++ compile-time casts were verbose and didn't do anything that our dandy C-style casts couldn't do.

Some time later, the inheritance hierarchy was restructured, some of these casts changed from the intended static_casts (down the hierarchy) to unintended reinterpret_casts (across the hierarchy) resulting in utter chaos. The unholy mess was extremely difficult to fix. Having tied the hands of the compiler behind its back, it could give us no help. One had to pour through every line of code, remember what the original intent was, and then fix it if required - a nightmare which seemed to never end.

The C++ cast operators provide:
Syntax that can convey semantics: Though somewhat verbose, this makes casts easier to understand, locate, and maintain. The intended meaning of a cast is no longer ambiguous, making it possible for compilers to detect logical errors.

Type-safe run-time conversions: dynamic_cast

C++ cast operators enable one to write programs which have a better chance of being correct; programs that are easier to maintain and understand. For example, conversions allowed by static_cast are somewhat less likely to lead to errors than those that require reinterpret_cast. In general, it is possible to use the result of a correct static_cast without casting it back to its original type. But I have to always cast the result of a reinterpret_cast back to its original type before accessing the object if I want correct portable code.

In general I try to write code that does not require casts (this is quite easy most of the time). If I have to resort to casts, I still use the C style casts (function style casts) when conversions are between values, and the intent is unambiguous - where no alternative interpretations are possible. Even here, I would write
k = { something } ; if narrowing was a concern.

Whenever there are possible alternative interpretations as to what the conversion might mean (pointers or references are involved), I have learned the hard way to use C++ casts.

Their absence in code that performs non-implicit conversions on pointers or references tells me: "Prima facie, don't trust any code written by this programmer.".
Last edited on
I remember an early C++ program that I was involved with. The design was terrible - we were novices - and a lot of casting up and down the hierarchy was needed. We were not allowed to use dynamic_casts in embedded software; yeah, those were the bad old days. And we naively used C-style casts all around; we knew that C++ compile-time casts were verbose and didn't do anything that our dandy C-style casts couldn't do.

Some time later, the inheritance hierarchy was restructured, some of these casts changed from the intended static_casts (down the hierarchy) to unintended reinterpret_casts (across the hierarchy) resulting in utter chaos. The unholy mess was extremely difficult to fix. Having tied the hands of the compiler behind its back, it could give us no help. One had to pour through every line of code, remember what the original intent was, and then fix it if required - a nightmare which seemed to never end.
Alright, this was the good example I was looking for, not the nonsense MiiNiPaa was posting. Why did you have to make so many static downcasts, though? In my experience, that's a rather unusual operation if polymorphism is fully taken advantage of.

I hadn't considered radical changes to the class structure. I will still keep most of my C-style casts, but I'll keep static_cast in mind for downcasting.
> Why did you have to make so many static downcasts, though?
> In my experience, that's a rather unusual operation if polymorphism is fully taken advantage of.

The design was terrible - we were novices.

To make matters worse, we were forced to use a library written and maintained in far away (pre-internet) Camas over which we had no control. The design of that library was abominable - even we could make out that it was written by idiots. The restructuring of the hierarchy was caused by a new version of the library; it was a big improvement, but it broke everything that existed prior to its inception.
@JLBorges, you mean x=(T)y; , not x = T(y) ;
x = T(y) ; would be a function call

reinterpret_cast<char>(a double variable);
tell me, does that work?
no, not with my compiler, you need static_cast
1
2
class A { ... };
static_cast<A>(a int variable);

does this work?
no, because this time you need... I dont even know!
there are 4 different casts, static_cast, reinterpret_cast, const and dynamic, and every time you need a different one!
is this not might a bit difficult?
i ONLY use C-style-casts, and i never had any problem with my casts
with C-style you can cast everything, or, better, you have the power to cast everything
1
2
char function[1024];
((void(*)())(*((void*)(&function))))();//... 
Last edited on
> @JLBorges, you mean x=(T)y; , not x = T(y) ;

Where T is a type, both (T)y and T(y) mean the same thing - an explicit conversion via a C-style cast.

1
2
3
4
5
6
7
#include <iostream>

int main()
{
    const char c = 'A' ;
    std::cout << +c << ' ' << int(c) << ' ' << (int)c << ' ' << (int)(c) << '\n' ;
}

http://ideone.com/eDB1oJ

k3fgbhHxm 7M7RH32K wrote:
char function[1024];
((void(*)())(*((void*)(&function))))();//...


It may be easier for you but look how messy that is that is 7 sets of brackets and then the two () function brackets. (if I counted correctly) versus maybe one or two with a c++ cast.
Pages: 12