【问题标题】:How to convert multi-character constant to integer in C?如何在C中将多字符常量转换为整数?
【发布时间】:2016-06-24 11:12:35
【问题描述】:

如何将 x 中的多字符常量转换为整数?

例如,我尝试将'13' 设置为('3' + '1' << 3),但它无法正常工作。 我不是指"0123",而是'0123'。它可以编译,但我不知道编译器在打印时是如何获得八进制结果 6014231063 的。我不是在寻找atoi,它只是将其转换为当前数字。例如int x = '1' 将在十进制数字系统中打印 49。现在我对打印int x = '0123' 感兴趣。这个任务来自编程竞赛,所以答案不应该是意外行为。

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;
}

【问题讨论】:

  • int x = '0123'; 虽然晦涩难懂,但不是您想要的 --> int x = 123;
  • “它不能正常工作。”缺乏细节。你看到了什么,你期待什么?当我运行代码时,我得到了我所看到的可能和你一样,也可能不一样。
  • ...或者int test = atoi("0123");
  • @WeatherVane 老实说,我认为int x = '0123'; 甚至不会编译。确实晦涩难懂。
  • 您好,这是多字符常量。我的意思不是“0123”,而是“0123”。它可以编译,但我不知道如何将其转换为 int。我不是在寻找仅将其转换为当前数字的 atoi。例如 int x = '1' 将在十进制数字系统中打印 49。现在我对打印 int x = '0123' 感兴趣。答案是八进制数字系统中的 6014231063,但是如何得到呢?这是来自一场编程比赛。

标签: c++ c char


【解决方案1】:

如何在 C 中将多字符常量转换为整数?

'0123'int 中。

int x = '0123'; 

'0123' 是一个字符常量。在 C 中,这是常量的一种形式,它的类型为int。它很少使用,因为它的值是实现定义的。根据字节顺序和字符编码(例如 ASCII),通常如下:

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

进一步:用它编写有用的可移植代码是一个挑战。许多编码样式在与超过 1 个字符一起使用时会禁止它。

【讨论】:

  • @SteveSummit:也许吧,但这是 OP 要求的。
  • 其实0123就是c-char-sequence'0123' 是一个字符常量。 (这是 C 术语;C++ 可能使用不同的术语。)此外,标准中没有任何内容表明序列中的字符数限制为 sizeof (int)
  • @Keith Thompson 我的意思是,可以导出的唯一值的数量一定不超过sizeof(int) 个字符。 IAC,多字符常量的细节足够松散,以防止它们的一般便携使用:C 的遗产与二合字母和三合字母生活在同一条荒凉的街道上。在=-foo(...) 的转储旁边。
  • 不可能在可移植代码中使用它,因为该值是(明确地)implementation-defined,根据定义它是不可移植的。恕我直言,有向图并不孤单;它们简单易用。三元组已被弃用,可能会在未来的某些标准中消失。
  • @rici 嗯,如果char 是无符号的或有符号的是实现定义的,但char 使用的范围很广。 I-D 本身并不等同于不可携带。也许张贴“如何可移植地使用多字符常量”可能会引起可接受的使用?
【解决方案2】:

'0123' 是一个多字符常量/文字(C 称其为常量,C++ 称其为文字)。在这两种语言中,它都是int 类型并且具有实现定义 值。

可能'0123' 具有典型值

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

(假设 CHAR_BIT==8,并记住 '0' 等的值本身是实现定义的)。

因为值是实现定义的,多字符常量很少有用,在可移植代码中几乎没用。该标准甚至不保证 '0123''1234' 具有不同的值。

但要回答您的问题,'0123' 已经属于 int 类型,因此无需转换。您可以以任何您喜欢的方式存储、操作或打印该值。

例如,在我的系统上这个程序:

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

打印(在编译时警告之后):

0x30313233

这与上面的公式是一致的——但在另一种实现下结果可能会有所不同。

“实现定义的”值意味着需要一个实现来记录它。 gcc 的行为(对于 5.3 版)是 documented here:

预处理器和编译器解释 同样的方法;即诸如‘\a’之类的转义序列被赋予它们的值 会在目标机器上。

编译器计算多字符字符常量 a 一次一个字符,将前一个值左移 每个目标字符的位数,然后在 新字符被截断为目标字符的宽度。决赛 位模式被赋予类型int,因此被签名,不管 单个字符是否已签名(从 GCC 3.1 及更早版本)。如果有更多的字符 比目标 int 更合适的常量,编译器发出一个 警告,并忽略多余的前导字符。

例如,'ab' 对于具有 8 位 char 的目标将是 解释为
(int) ((unsigned char) 'a' * 256 + (unsigned char)'b'),
'\234a'
(int) ((unsigned char) '\234' * 256 + (unsigned char) a').

【讨论】:

  • 每天都要学习新东西。我能问一下它们是做什么用的吗?
  • @Bob__:理想情况下,什么都没有。但我已经看到它们被用作一种人类可读的唯一数字(仅当值实际上是唯一的时才有效)。
  • Apple 曾经广泛使用它们(也许现在仍然如此)。但不仅仅是 Apple 使用带有四字节标签的文件和数据格式。你会发现到处都是“标记”的格式:图像格式、字体格式、视频格式……对四个字节使用四个 ascii 字符是避免需要大量符号常量的简单方法。跨度>
  • @rici 添加详细信息:.png 文件使用 4 字符标签 - 尽管以非常指定的顺序。同意避免使用符号常量。
  • @chux: .png 是一种图像格式,¿不是吗?尽管 GIF 和 TIFF 文件(更早出现)也是带有四字节标记的标记格式。
【解决方案3】:

您可以尝试创建这样的函数:

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;
}

我刚刚写了那个内联,所以它可能不是 100% 正确,但它应该是正确的想法。只需将字符乘以 10 的幂(最右边 - 10^0,最左边 - 10^(strinSize-1)。

希望有帮助:)

【讨论】:

  • 为什么要这么麻烦?为什么不直接使用atoi
  • 嗨,我不是在寻找 atoi,我知道这是如何工作的。查看任务是“0123”,而不是“0123”。它不是字符串,它是多字符常量。
  • 不知道这样的东西真的存在,但听起来确实像 OP 想要的!编辑:显然不是 OP 想要的
【解决方案4】:

嗯,你可以试试这个:

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

对我来说,这会打印出30313233,正如我所料。

在这里它被分解了,就像你试图做的那样:

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

这些打印输出表明,多字符字符常量在某种意义上是由字符'0''1''2''3' 全部卡在一起的。但是这个多字符字符常量与 integer 123 之间没有任何有意义的关系。 (我们可以编写一些代码来移位和屏蔽 8 位,然后减去 '0' 以将字符转换为数字,然后乘以 10 并添加,就像 atoi 一样,但这并没有任何意义。)

【讨论】:

  • 好吧,this 打印 808530483,但我没想到...
  • 你是怎么得到 30313233 的?这是我感兴趣的。
  • 投反对票,因为它提供的答案与史蒂夫本人投反对票的答案非常相似!公平竞争。
  • @SergeyA:我试图帮助 OP 了解如何将整数分开,这似乎是他想要做的,但他已经接受了其他答案,所以我想我很困惑. C'est la vie。
  • 我在这里看到了有用的信息,尤其是 OP 的帖子/评论中的八进制部分。
猜你喜欢
  • 2017-04-04
  • 2018-10-03
  • 2021-10-22
  • 2016-01-20
  • 1970-01-01
  • 2011-10-31
  • 1970-01-01
  • 2011-01-21
  • 1970-01-01
相关资源
最近更新 更多