ASCII和printf

时间:2010-10-07 10:59:54

标签: c ascii printf

我对C中的int和chars有一点(大,愚蠢?)的问题。我从学习中记得“chars是小整数和反之​​亦然”,这对我来说没问题。如果我需要使用小数字,最好的方法是使用char类型。

但是在这样的代码中:

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
  int i= atoi(argv[1]);
  printf("%d -> %c\n",i,i);
  return 0;
}

我可以使用我想要的每个数字作为参数。所以0-127我获得了预期的结果(标准的ASCII表),但即使有更大或更负的数字,它似乎也有用......

以下是一些例子:

-181 -> K
-182 -> J
300 -> ,
301 -> -

为什么呢?在我看来,它在ascii表周围循环,但我不明白如何。

7 个答案:

答案 0 :(得分:5)

当您传递对应于“%c”转换说明符的int时,int将转换为unsigned char然后写入。

当您传递的值超出无符号范围(0到UCHAR_MAX)时,它们将被转换为不同的值。您正在使用的系统可能具有UCHAR_MAX == 255。

将int转换为unsigned char:

  • 如果该值大于 UCHAR_MAX,(UCHAR_MAX + 1)是 从数值中减去多少 根据需要将它带入 范围0到UCHAR_MAX。
  • 同样,如果 值小于零,(UCHAR_MAX + 1) 被添加到该值多次 根据需要将其带入范围 0到UCHAR_MAX。

因此:

(unsigned char)-181 == (-181 + (255+1)) == 75 == 'K'
(unsigned char)-182 == (-182 + (255+1)) == 74 == 'J'
(unsigned char)300  == (300 - (255+1))  == 44 == ','
(unsigned char)301  == (301 - (255+1))  == 45 == '-'

答案 1 :(得分:2)

%c format参数将相应的值解释为字符,而不是整数。但是,当你对printf撒谎并在你告诉它是一个char时传递一个int时,它对值的内部操作(为了获得一个char,作为一个char通常作为一个int传递,无论如何,使用varargs)恰好产生你看到的价值观。

答案 2 :(得分:1)

我的猜测是%c获取所提供值的第一个字节并将其格式化为字符。在诸如运行Windows的PC之类的小端系统上,该字节将代表传入的任何值的最低有效字节,因此连续数字将始终显示为不同的字符。

答案 3 :(得分:0)

编辑:请忽略这个“答案”。

因为你在小端机器上:) 无论如何,这是一种未定义的行为。尝试将代码更改为printf("%d -> %c, %c\n",i,i,'4');,然后看看会发生什么......

答案 4 :(得分:0)

你告诉它这个数字是一个字母,所以尽管它太大了,但它会尝试各种方式来对待它。 看看你得到了什么,因为J和K按顺序排列,我会说它使用整数%128来确保它符合法定范围。

答案 5 :(得分:0)

当我们在printf语句中使用%c时,它只能访问整数的第一个字节。 因此,大于256的任何东西都被视为n%256。

例如 i / p = 321产生op = A

答案 6 :(得分:-1)

atoi所做的是将字符串转换为数值,以便“1234”获得1234而不仅仅是字符串序数的序列。

示例:

char *x = "1234";  // x[0] = 49, x[1] = 50, x[2] = 51, x[3] = 52 (see the ASCII table)
int y = atoi(x); // y = 1234
int z = (int)x[0];  // z = 49 which is not what one would want