0

I've seen a question What does (int*) &var mean? with such code

  char i;
  int* p = (int*) &i;

When I was trying to understand from here this part

#define     vertexmark(vx)   ((int *) (vx))[m->vertexmarkindex] 
#define     setvertexmark(vx, value)   ((int *) (vx))[m->vertexmarkindex] = value

It seems quite similar but the second piece of code is still confusing for me. Can somebody please explain what is goin on?

Also I'm curious with modern C++11 this type of C-style cast should be replaced with reinterpret_cast?

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
Bruice
  • 63
  • 6
  • Yes, you should use `reinterpret_cast<>` instead, if only because it will prevent you from accidentally casting constness away. –  Jul 16 '21 at 13:58
  • The code you are examining comes from a repository aimed at simulating biological functions. The code is written with the purpose of supporting multi-scale, highly demanding computations. As such, it employs techniques that focus on getting the most out of the executable, with readability and portability less of a concern. Essentially, it's like the code for a standard library implementation. There's plenty of macros and hacks that you'd be best advised to avoid in general purpose software due to other legitimate concerns. But it's not "bad practice" or "bad code", it's all purposeful. – StoryTeller - Unslander Monica Jul 16 '21 at 14:04
  • See [C-style cast](https://en.cppreference.com/w/cpp/language/explicit_cast) for an explanation of what C++ does with `( new_type ) expression`. `reinterpret_cast` is one of the possible outcomes. – rustyx Jul 16 '21 at 14:10
  • In general, a C-style cast does a bit more than `reinterpret_cast` does - which explains why `reinterpret_cast` is preferred (where needed) over a C-style cast (it is safer in some cases and, where it is equivalent, is considered better practice anyway). With your first example, `int *p = (int *)&i` is exactly equivalent to `int *p = reinterpret_cast(&i)`. With the macros, there may be a difference between the C-style cast and a `reinterpret_cast`, depending on what type (including `const` qualification, etc) `m->vertexmarkindex` has. – Peter Jul 16 '21 at 14:10

3 Answers3

2

Is (int*) &var same as reinterpret_cast?

It depends on the type of var. For some types it is same and for others it isn't. In the example case, it is same.

Here is an example where it isn't same:

const char i{};
int* p1 = (int*) &i;                  // well-formed (but dangerous)
int* p2 = reinterpret_cast<int*>(&i); // ill-formed

Also I'm curious with modern C++11 this type of C-style cast should be replaced with reinterpret_cast?

Yes, and it's not about modernity or C++11. Even if you're using C++98 you should avoid using C-style casts. You should also avoid macros like that in favour of using functions.

eerorika
  • 232,697
  • 12
  • 197
  • 326
0

These are old-style C casts, and your linter rules may urge you to turn them into either reinterpret_cast or static_cast.

In the code you wrote, in English, "take the address of i" which is a pointer to a char "but treat it like a pointer to an int". It prevents the compiler complaining. "I know it's wrong, but I meant to do that."

In the #defines you listed, we don't know what type vx really is. Maybe it's being passed as a void * or something. But they're basically assuming it's an int array, and they're taking the m->vertexmarkindex element from it.

The second one is a setter.

Frankly, this smells like poor design to me, but without digging further, we're not sure. I presume it's from a very old C library.

Joseph Larson
  • 8,530
  • 1
  • 19
  • 36
0

It seems quite similar but the second piece of code is still confusing for me. Can somebody please explain what is goin on?

let's deconstruct this a bit:

((int *) (vx))[m->vertexmarkindex] = value

(vx): The macro's argument is wrapped into a set of parenthesis. This is to allow the macro to be used with a compound expression. Without it, setvertexmark(ptr + 3, 0); would become ((int *)ptr + 3)[m->vertexmarkindex] = 0;, which would lead to the wrong offset.

From that point on, ((int *) ptr) is simply reinterpreting a buffer into an array of integers, and [m->vertexmarkindex] is just array indexing as usual.