How to convert multi-character constant to integer in C?

与世无争的帅哥 提交于 2021-02-08 06:44:52

问题


How to convert multi-character constant in x to integer?

I tried for example '13' as ('3' + '1' << 3), but it doesn't work properly. I don't mean "0123", but '0123'. It compiles, but I don't how did compiler gets the octal result 6014231063 when printing it. I am not looking for atoi which just converts this to present number. For example int x = '1' would print 49 in decimal number system. Now I am interested what would print int x = '0123'. This task is from programming competition, so the answer shouldn't be unexpected behavior.

int main(void) { 
  int x = '0123';  
  printf("%o\n", x);
  printf("%d\n", x >> 24);
  printf("%d\n", x << 8 >> 24);
  printf("%d\n", x & 0xff);  
  return 0;
}

回答1:


How to convert multi-character constant to integer in C?

'0123' in an int.

int x = '0123'; 

'0123' is a character-constant. In C, this is one of the forms of a constant and it has the type of int. It is rarely used as its value is implementation-defined. It's usually the following depending on endianness and character codding (e.g. ASCII):

(('0'*256 + '1')*256 + `2`)*256 + '3' = 858927408 = 0x33323130
(('3'*256 + '2')*256 + `1`)*256 + '0' = 808530483 = 0x30313233

Further: It is a challenge to write useful portable code with it. Many coding styles bar it when used with more than 1 character.




回答2:


'0123' is a multi-character constant/literal (C calls it a constant, C++ calls it a literal). In both languages, it is of type int and has an implementation-defined value.

It's probably typical for '0123' to have the value

('0' << 24) + ('1' << 16) + ('2' << 8) + '3'

(assuming CHAR_BIT==8, and keeping in mind that the values of '0' et al are themselves implementation-defined).

Because the value is implementation-defined, multi-character constants are rarely useful, and nearly useless in portable code. The standard doesn't even guarantee that '0123' and '1234' have distinct values.

But to answer your question, '0123' is already of type int, so no conversion is necessary. You can store, manipulate, or print that value in any way you like.

For example, on my system this program:

#include <stdio.h>
int main(void) {
    printf("0x%x\n", (unsigned int)'0123');
}

prints (after a compile-time warning):

0x30313233

which is consistent with the formula above -- but the result might differ under another implementation.

The "implementation-defined" value means that an implementation is required to document it. gcc's behavior (for version 5.3) is documented here:

The preprocessor and compiler interpret character constants in the same way; i.e. escape sequences such as ‘\a’ are given the values they would have on the target machine.

The compiler evaluates a multi-character character constant a character at a time, shifting the previous value left by the number of bits per target character, and then or-ing in the bit-pattern of the new character truncated to the width of a target character. The final bit-pattern is given type int, and is therefore signed, regardless of whether single characters are signed or not (a slight change from versions 3.1 and earlier of GCC). If there are more characters in the constant than would fit in the target int the compiler issues a warning, and the excess leading characters are ignored.

For example, 'ab' for a target with an 8-bit char would be interpreted as
(int) ((unsigned char) 'a' * 256 + (unsigned char)'b'),
and '\234a' as
(int) ((unsigned char) '\234' * 256 + (unsigned char) a').




回答3:


You could try something in the lines of creating a function like this:

int StringLiteralToInt(const char* string, int numbeOfCharacters)
{
    int result = 0;
    for(int ch = 0; ch < numberOfCharacters; ch++)
    {
        float powerTen = pow(10, numbeOfCharacters - (ch+1));
        result += (int)string[ch] * (int)powerTen;
    }
    return result;
}

I just wrote that inline, so it might not be 100% right, but it should be the right idea. Just multiply the chars by a power of ten (right most - 10^0, left most - 10^(strinSize-1).

Hope that helps :)




回答4:


Well, you could try this:

int main()
{ 
    int x = '0123';  
    printf("%x\n", x);
}

For me this prints 30313233, as I expect.

Here it is broken apart, as it looks like you were trying to do:

    printf("%o ", (x >> 24) & 0xff);
    printf("%o ", (x >> 16) & 0xff);
    printf("%o ", (x >> 8) & 0xff);
    printf("%o\n", x & 0xff);

These printouts show that the multi-character character constant is, in some sense, made up of the characters '0', '1', '2', and '3' all jammed together. But there is really no sense in which this multi-character character constant has any meaningful relationship to the integer 123. (We could write some code to shift and mask by 8 bits, then subtract '0' to convert from character to digit, then multiply by 10 and add, just like atoi, but it wouldn't really mean anything.)



来源:https://stackoverflow.com/questions/35902421/how-to-convert-multi-character-constant-to-integer-in-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!