Confused about type conversion in C++ - c++

In C++, the following lines have me confused:
int temp = (int)(0×00);
int temp = (0×00int);
What is the difference between those 2 lines?

Both are invalid because you are using × instead of x:
test.cpp:6: error: stray '\215' in program
test.cpp:6: error: expected primary-expression before "int"
test.cpp:6: error: expected `)' before "int"
But even fixing that, the second still isn't valid C++ because you can't write 0x00int:
test.cpp:6:13: invalid suffix "int" on integer constant
The first is valid (after changing × to x) and assigns the value 0 to temp. The cast is unnecessary here though - you don't need a cast just because the constant is written in hexadecimal. You can just write:
int temp = 0x00;

Ways to cast:
int temp = (int)0x00; // Standard C-style cast
int temp = int(0x00); // Function-style cast
int temp = static_cast<int>(0x00); // C++ style cast, which is clearer and safer
int temp = reinterpret_cast<int>("Zero"); // Big-red-flag style unsafe cast
The fun thing about static_cast and reinterpret_cast is that a good compiler will warn you when you're using them wrong, at least in some scenarios.
Visual Studio 2005 for example will throw an error if you try to reinterpret_cast 0x00 to an int, because that conversion is available in a safe way. The actual message is: "Conversion is a valid standard conversion, which can be performed implicitly or by use of static_cast, C-style cast or function-style cast".

The first will assign 0 to temp
Second will result in compilation error.
When the scanner sees 0× it expects it to be followed with hexadecimal digit(s), but when it sees i which is not a valid hex digit it gives error.

The first one takes the hex value 0x00 as an int, and uses it to initialize the variable temp.
The second one is a compile error.

First line is a valid C++, which basically equate to
int temp = 0;
while the second one will fail to compile (as suggested by everyone here).

Related

Why is this error on using strtok function showing when I use a different version of GCC?

I have this piece of C++ code:
const char *Delim = "some text";
char *token;
...
token = strtok('\0', Delim); // error here
The error is as follows:
invalid conversion from 'char' to 'char*' [-fpermissive]
I tested this in GCC 5.3 and it worked. But in GCC 8.1 it fails and gives me the error.
I understand I hard-code the char value. However, the Delim variable is also hard-coded. What would be the right replacement for it to work regardless of GCC versions? And why?
Note: I tested the following to get it to compile, but I want to understand it a bit more
const char *Delim = "some text";
char *str_0 = "\0"; // still receive warning that ISO C++ forbids converting a string constant to 'char*'
car *token;
...
token = strtok(str_0, Delim);
Interestingly, the single quote did not work either:
const char *Delim = "some text";
char *str_0 = '\0'; // fails
car *token;
...
token = strtok(str_0, Delim);
It's because the char expression '\0' is no longer a null pointer constant (and thus no longer convertible to a pointer), since C++11. Your newer compiler uses a new version of C++ by default.
You're supposed to pass an actual null pointer (i.e. nullptr, or NULL in the old days) to that argument, not '\0'. In the past your code only worked because of a weird kind of implicit conversion that eventually got removed. It's possible that this conversion masked a misunderstanding of what passing a null pointer there means (it means "continue the previous tokenisation session please", not "use '\0' as delimiter").
So:
token = strtok(nullptr, Delim);
I also recommend that you tell GCC exactly which version of C++ you're writing, with the -std flag.
char *str_0 = "\0"; // still receive warning that ISO C++ forbids converting a string constant to 'char*'
This has been advised against for a long time, and illegal for almost a decade. String literals should be stored in a const char*, not a char*. They're immutable (constant).
Regardless, this variant of the code does a different thing; you're now tokenising the string str_0, not continuing tokenising the original string.
Finally, I think you may have got the arguments backwards in your mind. Delim is supposed to be a list of delimiters, not an input string. It's hard to know for sure without a concrete example of your problem, but "some text" doesn't even look like a placeholder for a list of delimiters.
Please review some strtok documentation, or the section on it in your favourite book, to refresh your memory on how it's supposed to be used.

why it cannot convert char* to char

In c++ we can write
1 char *s="hello"
but the below lines of program produces an error ( cannot convert char* to char)
2 char *s;
*s="hello";
I am confused here, what is difference between 1 and 2
why this error is coming?
In C++, a string literal is a constant array of characters, not just an array of characters like in C. Anyways, to assign to such a variable (Which is best avoided), you do not have to dereference the pointer. Dereferencing it accesses the first element, which is just a char. A char cannot hold an array of characters inside it, causing an error. This is more the reason why you should be using std::string.
Some compilers such as GCC provide extensions to make such code possible since it is not standards compliant code, and it would look like:
char* s = "hello";
s = "new string";
This generates the following warning in GCC (But still gets the expected result):
warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
Clang also has the same behavior with the same output (Also generating a warning)
A string is an array of characters. The start of a string therefore is const char *.
Therefore to reference a string, you can use const char * s = "hello";
However if you dereference a const char*, you get a const char. This isn't a string i.e. *s gives you 'h'.
In your code *s="hello";, you are saying "assign at the dereferened s the value "hello"". Dereferencing s is a character only, to which you are trying to assign a string.
The problem is the second asterisk in your second example.
The first code is this
char *s="hello";
The equivalent code is this
char *s;
s="hello";
No * before s in the second line.
Now as everyone is pointing out neither of these are legal C++. The correct code is
const char *s="hello";
or
const char *s;
s="hello";
Because string literals are constant, and so you need a pointer to const char.
I am confused here, what is difference between 1 and 2 why this error is coming?
As many others * in C++ means different things in different context:
char *s; // * here means that s type is a pointer to char, not just char
*s; // in this context * means dereference s, result of exression is char
int a = 5 * 2; // in this context * means multiply
so case 1 and 2 may look similar to you but they mean very different things hence the error.

printing a set containing strings on graphics.h in c++

I am trying to print the elements of a set containing strings on graphics.h console using outtext() function,but i get this error:
cannot convert 'std::string {aka std::basic_string}' to 'char*' for argument '1' to 'void outtext(char*)'|
this the piece of code that gives error:
for(i=0;i<20;i++){
for(j=0;j<20;j++){
outtext(str[i][j]);
}
}
the template for the outtext function in the graphics.h header is like this:
void outtext(char *textstring);
i have used c_str() like this:
for(i=0;i<20;i++){
for(j=0;j<20;j++){
outtext(str[i][j].c_str());
}
}
but this time it gives this error:
error: invalid conversion from 'const char*' to 'char*' [-fpermissive]|
You can try this one as well:
char *cstr = new char[21]; // just in case string length is maxed at 20, leave 1 character for '\0'
for (int i = 0; i<20; i++) {
for (int j = 0; j<20; j++) {
strcpy_s(cstr, str[i][j].length() + 1, str[i][j].c_str());
outtext(cstr);
}
}
delete[] cstr;
Just added a char* string to temporarily hold the converted std::string value. The tricky part is that char* strings normally have the terminating character \0 which std::string don't have, so you have to add 1 more character to the size of each "row" of str.
I take it this question is about the 30 years old BGI graphics library and Borland C++. The root of the problem is that this library was poorly written, as it didn't implement const correctness.
The Turbo C++ compiler did not follow anything remotely close to any C++ standard, so you are mostly out of luck. If you had a proper C++ compiler you could use const_cast, but I very much doubt this is available to you.
The only solution left is the dirty, bad way:
outtext((char*)str[i][j].c_str()); // bad practice
You should never cast away const like this in neither C nor C++.
If you can change the prototype of the output function then it is better to change void outtext(char *textstring); to void outtext(const char *textstring); because there is no need for the output function to modifiy the string. Otherwise you could use const_cast before passing to the function like outtext(const_cast<char*>(str[i][j].c_str())) or copy the string to another char* and passed the copied value.

cannot convert from 'const char [3]' to 'char *' x100000 (Qt Creator C++ Windows 32)

Everything was working fine just five minutes ago when I tapped f5 and got 102 errors:
error: C2440: 'initializing' : cannot convert from 'const char [17]' to 'char *'
Conversion from string literal loses const qualifier (see /Zc:strictStrings)
That specific one is at line 30:
char* hexchars = "0123456789ABCDEF";
I haven't touched the file the errors are in for at least a week. I'd normally say I accidentally changed something in the compile args or something, but I haven't opened settings since much before it started erroring.
Any ideas? I must have absentmindedly changed some setting but I really can't remember thinking "uh oh what did I just do?"
When you use code like this
char *astring2 = "some letters";
C++ (and C) puts that into read only memory. You can not modify the contents of a char pointer initialized with a literal even if it is not const.
Also you can not change the address of the pointer because it will cause a memory leak due to the rule above.
This, however, does not follow that rule UNLESS you make it const:
char astring[] = "some letters that can be changed";
char *ptrToString = astring; //work
astring2 = astring //not work
String literals are of type char const[N] since C++ was first standardized. At this point C didn't support const and a lot of code assigned string literals to char*. As a result a special rule was present in C++ which allowed initialization of char* from string literals. This rule was immediately deprecated.
C99 introduced a const keyword, too. When C++11 was standardized the deprecated rules was pulled and it is no illegal to initialize a char* from a string literal as it should have been right from the stand. The expectation was that C++ compilers warned about the deprecated assignment since years (and all vendors stated they did), i.e., users had years of lead-time to fix their code.
The obvious fix is to initialize a char const* instead of a char* from a string literal.
If you really need a pointer to a mutable array of chars you can create it and get it initialized using
char array[] = "string literal";

invalid conversions, unspecified behaviour and char arrays?

I am trying to do http://www.spoj.com/problems/SHLIGHTS/, for which I have designed a solution. I am very new to C++(about 14 days), and I am facing a lot of problems. Earlier I used Python, and there was nothing of these errors, anyways, I wrote this..
#include <iostream>
#include <string>
#include <cstdio>
using namespace std;
//example is GBGBBB
//t=0, GBGBBB then t=1,BGBGBB then t=2 BBGBGB, then t=3 BBBGBG
//search for GB and replace it with BG
//we need a function that replaces things
string swapSEQ(string SEQ)
{
unsigned int sizeSEQ=SEQ.size();
unsigned int curr(0);
while (curr<sizeSEQ-1)
{
if (SEQ[curr]=="G" and SEQ[curr+1]=="B")
{
SEQ[curr]="B";SEQ[curr+1]="G";curr+=2;
}
else {++curr;}
}
return SEQ;
}
int main()
{
unsigned int numCases;
scanf("%d",&numCases);
// cin>>numCases;
for (unsigned int currentCase=0;currentCase<numCases;++currentCase)
{
string SEQ;
//scanf("%s",&SEQ);
cin>>SEQ;
string swapped=swapSEQ(SEQ);
unsigned long long t=0;
while (swapped!=SEQ)
{
swapped=swapSEQ(SEQ);++t;
}
printf("%lld\n",t);
}
return 0;
}
I know that's a lot of details, but that's it. SPOJ shows blank lines after inputs and outputs, but after reading the description, I understand we have to do things in single lines. Here's what I get with my g++4.7 compiler(LINUX)
SHLIGHTS.cpp: In function ‘std::string swapSEQ(std::string)’:
SHLIGHTS.cpp:17:18: error: comparison with string literal results in unspecified behaviour [-Werror=address]
SHLIGHTS.cpp:17:18: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
SHLIGHTS.cpp:17:37: error: comparison with string literal results in unspecified behaviour [-Werror=address]
SHLIGHTS.cpp:17:37: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
SHLIGHTS.cpp:17:52: error: invalid conversion from ‘const char*’ to ‘char’ [-fpermissive]
SHLIGHTS.cpp:17:66: error: invalid conversion from ‘const char*’ to ‘char’ [-fpermissive]
cc1plus: all warnings being treated as errors
*What is happening? There's something about pointers, const char and unspecified behaviour.
**I know pointers are sort of variables that point to memory locations, nothing more.
**I've used scanf at some places and cin at others(if I replace scanf by cin, I get the same errors)
**Is it something about the fact that I returned a string that took as argument?
**Where did I use a pointer?
**Am I wrong about this- strings in c++ are char arrays? If no, then where is the invalid conversion?
Thanks in advance, and apologies for anything wrong. If it's too long, please answer any of the doubts.
You need to compare SEQ[curr] with 'G' not "G" since it's a char and not a string.
You should use operator && instead of and.
Something with your logic is worng. At one index of a string you can have only 1 char. So writing if (SEQ[curr] == 'G' && SEQ[curr] == 'B' is same as writing if (false).
It is not an error, but please don't abuse your code by writing more than one commend at a line.
If you writing is C++ please use cin , not scanf.
Why are you creating sizeSEQ if you never use it? Don't!
you should use 'G' instead of "G" and so on. When you access a char array (e.g. arr[5]) you obtain a char, which you can compare with a char literal (being: 'G') and not with a cstring (e.g. "G" or "Google").
The compiler is your friend, it points out that the problem is:
comparison with string literal