Why Does C++ Allow an Integer to Be Assigned to a String

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



Leave a reply



Submit