2

Is there any type of casting (implicit, explicit) done in this line:

int *p= "hello there"; 

Moreover what is correctness of such a statement from C/C++ point of view ?

Note: it compiles on AVR-GCC and fails with other compilers.

OAH
  • 309
  • 3
  • 11
  • 5
    *error: cannot initialize a variable of type 'int *' with an lvalue of type 'const char [12]'* – chris Jun 09 '15 at 23:42
  • it is off topic and I have marked it so. – Richard Chambers Jun 09 '15 at 23:45
  • Nothing to think about, it's an error. You could intialize an array of chars, or a string, and then convert a pointer to int, for whatever reason you want. – aslg Jun 09 '15 at 23:46
  • 1
    @aslg You well can do so, if you know how to do it correctly. And in fact such stuff is used in practice for valid reasons. – πάντα ῥεῖ Jun 09 '15 at 23:48
  • 3
    Don't do it unless you need to. Things like this takes weeks or more of discovery during testing and may lead to undefined behavior. The type system was created for a reason. – Thomas Matthews Jun 09 '15 at 23:51
  • 1
    @chris this code compiles on AVR-GCC. As for the off-topic, the goal of this question is to understand what functionality is being performed by such a line and why it compiles on AVR-GCC. – OAH Jun 09 '15 at 23:54
  • @πάνταῥεῖ Yes, I did say for whatever reason, but I'm sure there are valid reasons. – aslg Jun 09 '15 at 23:57
  • 3
    @OAH try invoking your compiler in standard mode. (for gcc use `-pedantic` and a `-std` switch , not sure if avr-gcc is exactly the same) – M.M Jun 10 '15 at 00:24

3 Answers3

6

"Is there any type of casting (implicit, explicit) done in this line:"

int *p= "hello there"; 

No, there isn't any casting done.

But in C++ you can use a reinterpret_cast<int*> along with a const_cast<char*> like follows:

int *p= reinterpret_cast<int*>(const_cast<char*>("hello there")); 

See a working demo.

"Moreover what do you think about the correctness of such statement from (C,C++) point of view."

Well, that's totally left upon the user of such statement. It's certainly not recommendable to do so (because you're hitting not specified1 behavior), and dangerous if you're not a 100% sure about what you're doing.

But at least both languages support to do so.

The a bit shorter variant for C is:

int *p= (int*)"hello there";

"Note: it compiles on AVR-GCC and fails with other compilers."

Well, I don't know the version you're using for the AVR cross toolchain, but any halfway up-to-date version of GCC should give an error for this statement like

prog.cpp:3: error: cannot convert 'const char*' to 'int*' in initialization

See demo please

I'm using a fairly old version of GCC to make up that demo: g++ 4.3.2. The latest one is 5.x if I'm informed correctly, and I'm pretty sure that it's possible to build a cross toolchain for AVR with it.


1 Which is subtly different from undefined behavior. Just depends on what your hardware goes along with these pointer addresses, and the alignment settings.

Community
  • 1
  • 1
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • 2
    This may cause undefined behaviour if the char array is not correctly aligned for `int`, and it will cause undefined behaviour due to strict aliasing violation if `p` is read or written through. – M.M Jun 10 '15 at 00:22
  • 1
    @MattMcNabb: It's unspecified, not undefined (unless p is read or written through). C++ (since N3691, 2013-05-06) 5.2.9/13: "If the original pointer value represents the address A of a byte in memory and A satisfies the alignment requirement of T, then the resulting pointer value represents the same address as the original pointer value, that is, A. The result of any other such pointer conversion is *unspecified*." – rici Jun 10 '15 at 00:30
  • @MattMcNabb Of course it would. Didn't I mention you should be a 100% sure about what you're doing, if doing so? – πάντα ῥεῖ Jun 10 '15 at 00:31
  • @πάνταῥεῖ you said it was left upon the user, which suggests that it might be possible to not cause UB – M.M Jun 10 '15 at 00:33
  • @MattMcNabb There are certainly cases, you can use such code, if you're sure about what you're doing. Bit banging the bus daily my friend ;-) ... – πάντα ῥεῖ Jun 10 '15 at 00:35
  • @rici that code is in the `static_cast` section. This is a `reinterpret_cast` (5.2.10) and the "unspecified" escape clause doesn't appear there in C++14 (N3836). In fact it seems that the clause was moved from the reinterpret_cast to the static_cast section – M.M Jun 10 '15 at 00:47
  • @MattMcNabb: Comments are so short. 5.2.10/7 (reinterpret_cast) defines that conversion in terms of static_cast: "An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue v of object pointer type is converted to the object pointer type “pointer to cv T”, the result is static_cast(static_cast(v))." – rici Jun 10 '15 at 00:49
  • @rici maybe it was also unspecified in C++11 (I always took that clause to mean the converting to T and back was unspecified , but not just converting to T) – M.M Jun 10 '15 at 00:50
  • @mattmcnabb: I think it was *not specified*, which may or may not be the same as *unspecified*. :) – rici Jun 10 '15 at 01:03
  • @rici N3337 (C++11) has " The result of any other such pointer conversion is unspecified." under 5.2.10/7 – M.M Jun 10 '15 at 01:20
  • @MattMcNabb: DR 1412 (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1412) with the apparent goal of removing the restriction to standard layout types and simplify the specification. – rici Jun 10 '15 at 01:59
  • @rici right, it's an improvement but still leaves the current question's code as unspecified, it seems. I've started a new question [here](http://stackoverflow.com/questions/30745684/how-does-an-unspecified-pointer-conversion-behave-in-c14) – M.M Jun 10 '15 at 02:02
  • @MattMcNabb I've seen that already and upvoted, what do you think? I'm watching at this tag seriously ;-P ... – πάντα ῥεῖ Jun 10 '15 at 02:08
1

to answer your question (ignoring the 'why do it' comments - which are correct)

You do

int *p=(int*)"hello there";
pm100
  • 48,078
  • 23
  • 82
  • 145
1

This code is illegal in C and C++. We might guess that AVR-GCC pretends that you had written:

int *p = (int *)"hello there";

You could perhaps try to confirm this by writing:

char *q = "hello there";
int *p = q;

and seeing if p and q hold the same address. (although that would not be completely conclusive either way).

It would be better to find out how to invoke your compiler in a mode where it will report errors or warnings for illegal code. Normally for gcc, -Wall -pedantic does this, and usually you'd also specify a standard version such as -std=c99 or -std=gnu99 .


Supposing the code is treated as int *p = (int *)"hello there";. This code may cause undefined or unexpected behaviour because the char array might not be correctly aligned for int.

Also, it will cause undefined behaviour if you read or write through p due to violating the strict aliasing rule, which says that reading or writing as int is only permitted for variables declared as int, or malloc'd space which (if being read) already has had an int written.

M.M
  • 138,810
  • 21
  • 208
  • 365