Why does C++ allow an integer to be assigned to a string?
Because string is assignable from char
, and int
is implicitly convertible to char
.
why an integer can be assigned to a string variable?
This is because we have the following assignment operator:
basic_string& operator=( CharT ch )
see cppreference.
In this case int converts to char.
This was subject to a defect report 2372: Assignment from int to std::string which was closed as not a defect (NAD). It says:
The following code works in C++:
int i = 300;
std::string threeHundred;
threeHundred = i;
"Works" == "Compiles and doesn't have an undefined behavior". But it
may not be obvious and in fact misleading what it does. This
assignment converts an int to char and then uses string's assignment
from char. While the assignment from char can be considered a feature,
being able to assign from an int looks like a safety gap. Someone may
believe C++ works like "dynamically typed" languages and expect a
lexical conversion to take place.Ideally the assignment from char could be deprecated and later
removed, but as a less intrusive alternative one could consider adding
a SFINAEd deleted function template:template <typename IntT> // enable if is_integral<IntT>::value
basic_string& operator=(IntT) = delete;
and the resolution was:
This should be addressed by a paper addressed to LEWG
Assign an integer value to a string in C
char string[100];
sprintf(string, "The tile in %d,%d is occupied: ", row, col);
In C, why can't an integer value be assigned to an int* the same way a string value can be assigned to a char*?
In fact, you can do so using a compound literal, a feature added to the language by the 1999 ISO C standard.
A string literal is of type char[N]
, where N
is the length of the string plus 1. Like any array expression, it's implicitly converted, in most but not all contexts, to a pointer to the array's first element. So this:
char *mystr = "hello";
assigns to the pointer mystr
the address of the initial element of an array whose contents are "hello"
(followed by a terminating '\0'
null character).
Incidentally, it's safer to write:
const char *mystr = "hello";
There are no such implicit conversions for integers -- but you can do this:
int *ptr = &(int){42};
(int){42}
is a compound literal, which creates an anonymous int
object initialized to 42
; &
takes the address of that object.
But be careful: The array created by a string literal always has static storage duration, but the object created by a compound literal can have either static or automatic storage duration, depending on where it appears. That means that if the value of ptr
is returned from a function, the object with the value 42
will cease to exist while the pointer still points to it.
As for:
int *myint = 5;
that attempts to assign the value 5
to an object of type int*
. (Strictly speaking it's an initialization rather than an assignment, but the effect is the same). Since there's no implicit conversion from int
to int*
(other than the special case of 0
being treated as a null pointer constant), this is invalid.
What happens when I assign a string to an int?
int a = "abcd";
This is illegal in C.
Well, sort of. The C standard doesn't actually use the term "illegal" for this kind of thing. To be painfully precise, it's a constraint violation, which means that any conforming compiler must issue a diagnostic message (which might be a non-fatal warning).
The expression "abcd"
is an array expression, of type char[5]
(4 for the letters plus 1 for the terminating \0'
). In most contexts, including this one (if it were valid), an array expression is implicitly converted to a pointer to the array's first element. After that conversion, the value is of type char*
, and it's a pointer to the 'a'
.
There is no implicit conversion from char*
to int
, which is why this initialization is invalid. You could add a cast, which is an explicit conversion:
int a = (int)"abcd";
This would store in a
the memory address of the string, converted from char*
to int
. On many systems, this conversion, though it's legal, yields garbage; for example, on the system I'm typing this on, a char*
is 64 bits and an int
is only 32 bits.
Compilers for older versions of the C language (prior to 1989) were more lax about implicit conversions, often allowing integers and pointers to be assigned to each other. More modern compilers, even though they'll diagnose this error if you ask them to, might (or might not) still generate code to perform the implicit conversion. (Strictly speaking the behavior is undefined, but an implicit conversion is common.)
If your compiler rejects
int a = "abcd";
it's doing its job. If it merely warns you about it, it's still doing its job as far as the C standard is concerned, but it's really not doing you any favors by generating that implicit conversion.
Bottom line: The value assigned to a
is garbage, and if your compiler doesn't complain about it, find out what options you need to give it to make it do so.
As for the output of your printf
calls:
printf("a as string witn & = %s\n", &a);
%s
requires a char*
argument that points to a string. &a
is of type int*
, and does not point to a string. The behavior is undefined. Most likely printf
will print garbage bytes starting at the beginning of a
until it happens to encounter a null byte (or crashes).
Don't do that.
printf("a as int witn no & = %d\n", a);
If your program hasn't already crashed at this point, this prints the value of a
. That value is garbage, which might typically be the converted value of the address of the string literal, or just the low-order 32 bits of that address.
printf("a as int witn & = %d\n", &a);
%d
requires an argument of type int
. &a
is of type int*
. Undefined behavior. This might print the memory address of a
as a decimal integer. Don't do that. If you really want to print the address of a
, the correct way to do it is:
printf("&a = %p\n", (void*)&a);
Why it is possible to assign string to character pointer in C but not an integer value to an integer pointer
If you have a character array as for example
char s[] = "Stackoverflow";
then the array designator used in expressions it is converted to pointer to its first element. So you may write
char *ptr = s;
The pointer ptr
now points to the first character of the array s
.
String literals in C are also represented like character arrays and stored in memory like character arrays with the static storage duration.
So for example the string literal "Stackoverflow"
has the type char[14]
(including the terminating zero).
So then you write
char *ptr = "Stackoverflow";
then this statement in fact the same if there would be
static char unnamed[] = "Stackoverflow";
char *ptr = unnamed;
As for this statement
int *p = 22 ;
then the integer literal is not converted to a pointer to itself. It represents literally the number 22 and nothing more.
So the compiler issues a message because if you want that the pointer indeed contained the integer value 22 then you have to use a casting.
The expression
22 == 22
always yields true
.
While this expression
"Stackoverflow" == "Stackoverflow"
is not necessary yields true
because depending on compiler options the compiler can place coincidental string literals in different memory areas. And in this expression it is the pointers to the first characters of the string literals that are compared.
Take into account that if you are going to output an integer object pointed to by a pointer you need to use dereferencing. So in any case instead of
printf("%d",p);
you should write
printf("%d", *p);
Or if you want to output the value stored in a pointer you have to use another format specifier
printf("%p", p);
Assigning a string to a variable of type int
In fact, that assignment is a constraint violation, requiring a diagnostic (possibly just a warning) from any conforming C implementation. The C language standard does not define the behavior of the program.
EDIT : The constraint is in section 6.5.16.1 of the C99 standard, which describes the allowed operands for a simple assignment. The older C90 standard has essentially the same rules. Pre-ANSI C (as described in K&R1, published in 1978) did allow this particular kind of implicit conversion, but it's been invalid since the 1989 version of the language.
What probably happens if it does compile is that
int a="Hello World";
is treated as it if were
int a = (int)"Hello World";
The cast takes a pointer value and converts to int. The meaning of such a conversion is implementation-defined; if char*
and int
are of different sizes, it can lose information.
Some conversions may be done explicitly, for example between different arithmetic types. This one may not.
Your compiler should complain about this. Crank up the warning levels until it does. (Tell us what compiler you're using, and we can tell you how to do that.)
EDIT :
The printf
call:
printf(a);
has undefined behavior in C90, and is a constraint violation, requiring a diagnostic, in C99, because you're calling a variadic function with no visible prototype. If you want to call printf
, you must have a
#include <stdio.h>
(In some circumstances, the compiler won't tell you abut this, but it's still incorrect.) And given a visible declaration, since printf
's first parameter is of type char*
and you're passing it an int
.
And if your compiler doesn't complain about
double a="Hello World";
you should get a better compiler. That (probably) tries to convert a pointer value to type double
, which doesn't make any sense at all.
Ambigous integer assignment to string c++
Shouldn't
basic_string& operator=( CharT ch );
be explicit ? That is,
why is this :s = 97
allowed?s
is a string, then why should an
integer be assigned to it by implicit conversion?
From explicit specifier:
The explicit specifier specifies that a constructor or conversion
function (since C++11) doesn't allow implicit conversions or
copy-initialization. It may only appear within the decl-specifier-seq
of the declaration of such a function within its class definition.
So, you cannot make an assignment operator explicit.
Can this
s = 97
implicit conversion be avoided/stopped?
Generally speaking, no, because it is perfectly legal for std::string. When you call:
basic_string& operator=( CharT ch );
with 97
then 97
which has a type of int is converted into char
and operator= is performed.
So, why is g++ enable to compile this and clang doesn't?
Most probably, you try to compile your program with clang without C++11 support.
Assign string to int in C
int i = "hello world";
With that you assigning the address of the string literal "hello world"
in memory to the int
object i
, which is in most cases undefined behavior because the value of a memory location is in many cases beyond the area an object of type int
can hold.
This undefined value is then printed by:
printf("%d", i);
Nonetheless the compiler should give you a warning when doing that without an explicit cast, f.e. as I compiled your code by gcc it gave:
warning: initialization of 'int' from 'char *' makes integer from pointer without a cast [-Wint-conversion]
Do never ignore compiler warnings.
Assigning a string to a varible previously declared as int
Besides your question might be a duplicate, let me append something missing of the read worthy answer https://stackoverflow.com/a/430414/3537677
C is strongly/statically typed but weakly checked
This is one of the biggest core language features which sets C apart from other languages like C++. (Which people are used to mistake a simply "C with classes"
Meaning although C has a strong type system in the context of needing and using it for knowing sizes of types at compile time, the C languages does not have a type system in order to check them for misuse. So compilers are neither mandated to check it nor are they allowed to error your code, because its legal C code. Modern compilers will issue a warning dough.
C compilers are only ensuring "their type system" for the mentioned size management. Meaning, if you just type int i = 42;
this variable has so called automatic storage duration or what many people are calling more or less correctly "the stack". It means the compiler will take care of getting space for the variable and cleaning it up. If it can not know the size of it, but needs it then it will indeed generate an error. But this can be circumvented by doing things at run-time and using of types without any type whats so ever, i.e. pointers and void*
aka void-pointers.
Regarding your code
Your code seems to be an old, non standard C compiler judging by the #include<conio.h>
and void
returning main. With a few modifications one can compile your code, but by calling printf
with an illegal format string, you are causing so called undefined behaviour (UB), meaning it might work on your machine, but crashes on mine.
Related Topics
Taking the Address of a Temporary Object
Practical Use of Zero-Length Bitfields
Template Partial Ordering - Why Does Partial Deduction Succeed Here
"String Could Not Resolved" Error in Eclipse for C++ (Eclipse Can't Resolve Standard Library)
Passing a Variable as a Template Argument
Calling a Function for Each Variadic Template Argument and an Array
Dynamic Aligned Memory Allocation in C++11
Why Is It Illegal to Take the Address of an Rvalue Temporary
How to Set a Timeout on Blocking Sockets in Boost Asio
How to Store Objects of Differing Types in a C++ Container
Implementing a No-Op Std::Ostream
C++ Compiler Error C2280 "Attempting to Reference a Deleted Function" in Visual Studio 2013 and 2015
A How to Create a Matrix in C++
Nonstatic Member as a Default Argument of a Nonstatic Member Function