0

I tried this method to convert a char digit to an integer digit ('3'->3) and it seems to work.

char c='x';
int i=atoi(&c);

My question is, will this always work?

Is there always a NULL character after the first character?

There is another way to do this using implicit typecast, but I am not sure it is a good practice. Actually, I am pretty surprised there are no warnings even using -Wall and -Wextra.

int i = c - '0';

Note I am using GCC 4.8.2 and MinGW.

Slazer
  • 4,750
  • 7
  • 33
  • 60
  • 4
    This is pretty much undefined behaviour. It works because probably out of bounds accessed memory has value 0. – 101010 Oct 21 '15 at 12:47
  • 2
    For the second case, C and C++ [guarantees the order of digit characters](http://stackoverflow.com/q/32586834/1708801) – Shafik Yaghmour Oct 21 '15 at 12:47
  • You are confusing strings and chars. A `char` is always a single character. – dandan78 Oct 21 '15 at 12:47
  • 1
    Please pick one of C and C++. – fuz Oct 21 '15 at 12:54
  • @FUZxxl Is there a difference? I am interested in both. – Slazer Oct 21 '15 at 12:55
  • @Slazer There might be, I don't know. Point is, asking about “something in C/C++” is not much different from “something in Ada/Pascal/PHP.” Few people are knowledgeable about tiny language details in *both* of C and C++, so policy is that you ask a question only for one language at a time. If you are interested in an answer for both, then ask two questions, you can refer to the first one in your second. – fuz Oct 21 '15 at 13:17
  • I am not a downvoter but as the question reads now, it sure seems like a C question. Are you compiling as C++? If so you should note that but why add the C tag? Are you compiling for both, if so you should also specify that in your question. There are cases where the answer in C and C++ will be very different which can lead to some confusing answers. Although I don't know if I agree with @FUZxxl that this particular question should be two questions. – Shafik Yaghmour Oct 21 '15 at 13:30

3 Answers3

5

This compiles but it's undefined behavior.

A char is just a character. No null byte following. std::atoi expects a null byte, though, so invoking std::atoi(&c) compiles but yields undefined behavior. This line,

int i = std::atoi("x");

is well-defined, though, because the string "x" is a char[2] and null-terminated.

int i = c - '0';

is alright because1 the C++11 standard and the C99 standard2 guarantee the order of character digits.


1 as @ShafikYaghmour noted in the comments to your question

2 Thanks to @ShafikYaghmour again!

Community
  • 1
  • 1
cadaniluk
  • 15,027
  • 2
  • 39
  • 67
  • 5
    @Slazer That's undefined behaviour. It may work, but it can also make dæmons fly out of your nose. – fuz Oct 21 '15 at 12:55
  • @Slazer Ah, I see, that's what you mean. Will clarify that. – cadaniluk Oct 21 '15 at 12:56
  • Well it may work and it works in my case. So the statement "This will not work at all" is false. I understand what undefined behaviour is, though. – Slazer Oct 21 '15 at 12:56
  • @Slazer OK, fixed it. – cadaniluk Oct 21 '15 at 13:00
  • Its quite ridiculous there is no such function is C/C++ library. The stoi() mentioned by David Haim is perfect, except only for strings. It even has exceptions! – Slazer Oct 21 '15 at 13:19
  • 1
    The [C version of the question](http://stackoverflow.com/q/781668/1708801) on order of digits. – Shafik Yaghmour Oct 21 '15 at 13:20
  • @ShafikYaghmour Thank you very much! – cadaniluk Oct 21 '15 at 13:26
  • I just wonder how come that there is no warning because of the typecast (even with -Wall and -Wextra)? Because my first try was simply write {char c; int i=c;} which would give me ASCII values instead of digits. A warning would definitely be in order here. – Slazer Oct 21 '15 at 13:30
1

atoi expects null terminated C-string.

since you didn't provide it (you provided a pointer to character) this is undefined behaviour.

for the second line of code - this generally works if you can guarantee that the character is indeed a digit. for example , the character # will yield a result but may not the result you'd expect.

some solution is to use std::stoi:

try{ int x = std::stoi(std::string() + c) } catch(...) {/*handle*/}
David Haim
  • 25,446
  • 3
  • 44
  • 78
  • Using a string seems to me too heavy for such a simple task. The exception functionality seems nice, though. – Slazer Oct 21 '15 at 13:13
0

This will work as long as next to the memory space where c is allocated is a \0. In other words, it's just luck. You should use int i = c - '0'

But be aware that every character will be mapped to int (f.e. int i = 'a' - '0')

To avoid this you could do something like:

int i = c=>'0' && c<='9' ? c-'0' : -1; //-1 represents not valid values
Mr. E
  • 2,070
  • 11
  • 23
  • 1
    Most likely because you claimed that an undefined program will work. The actual value (possibly) stored in `&c + 1` doesn't matter, as accessing it has undefined behaviour. – molbdnilo Oct 21 '15 at 13:05
  • But it's the explanation of why his program worked (at least when OP tested it). Undefined behaviour != not working, in the best case it won't work, in the worst it will work when you test it and crash later (Like this) – Mr. E Oct 21 '15 at 13:23