将数组中的两个相邻字符存储到int中

时间:2013-01-07 02:52:59

标签: c pointers

我有这个字符数组

char array[] = {1,2,3};     //FL, FH, Size

我试图使用指针访问它,以便我将FLFH值一起存储在整数变量中。

我做了这个

int val =0;
val = *(int*)array;
printf("value of p is %d\n",val);

我期待结果是12,但它是一个8位数字,我认为可能是价值的地址或其他东西。谁能告诉我,我在这里做错了什么?

4 个答案:

答案 0 :(得分:4)

它永远不会给你十二个。

您正在获取两个单字节值,并将它们视为包含一个双字节实体。当你一起看它们时,你就会重新解释它们的价值。整数1看起来像这样:位000000012,如下所示:00000010。编译器知道它们有多大,因此允许您作为个体访问它们,但它们按顺序排列在数组中,在内存中彼此相邻。

将两个字节一起检查,就像它们是int一样,你有:0000000100000010,其值不是12;这是513。

为了您的进一步阅读,您正在做的是一种"type punning"

答案 1 :(得分:3)

这是一个糟糕的主意,可读性和便携性。如果这是你的意思,请使用array[0] * 10 + array[1],并相信窥视孔优化器可以加快速度。如果必须通过指针访问该值,请使用char指针并编写p[0] * 10 + p[1],这很容易理解,完全合法且便携。

你的代码可能不起作用的原因很多,这强烈暗示你要做的事情是愚蠢的,或者至少是你的代码。

第一个是字节范围从0到255,而不是从0到9,所以如果你使用这种技术,并且工作,你将获得1 * 256 + 2 = 258,而不是1 * 10 + 2 = 12.你永远不会得到12.计算机无法正常工作。这就是为什么你必须调用像atoi()这样的函数来将"12"之类的字符串转换为数字12,然后再对其进行算术运算。

如果你有四个字节的整数,这也是你得到一些大数字的原因:你认为你得到1 * 256 + 2,但你实际得到((1 * 256 + 2)* 256 + 3)* 256 + ???。另外,正如克里斯在评论中所说,在这种情况下你的数组太小了,无论如何,???在上一个公式中。

您可以尝试使用short代替int,看看是否效果更好; short可能是一个2字节的整数。但这并不能保证,因此它仍然不能移植到short s长于两个字节的系统。更好的做法是找出系统上与两个字节整数相对应的实际类型(也许是short,或许是其他的东西),然后键入像INT2这样的类型,并使用INT2取代int

另一个潜在的问题是你的系统可能使用小端字节顺序,在这种情况下,你的数组中的字节顺序错误,以表示你想要的双字节机器整数,你的技巧永远不会工作。即使可以在您的机器上运行,如果您必须在小端机器上运行代码,它也会中断。 (你在这个帖子的其他地方的评论表明这正是发生的事情。)

所以就这么简单。

答案 2 :(得分:3)

您没有得到预期的结果,因为字节是在8位边界上布局的,因此相邻的二进制字节值按 256 10 缩放,不是 10 <子> 10

此外,如果你转换某种东西并取消引用它,编译器会编译它,但从技术上讲你的程序是不合格的。 *

一个问题是对齐。如果使用开放代码更改类型,则可能无法从右边界开始,并且可能不够大。你可以用联盟解决所有问题。它仍然是不一致的,结果没有指定,但实际上它是可靠的,甚至有些可移植,如果你不介意根据字节顺序和int大小的不同结果。

union a {
  char  c[3];
  int   i;
  short s;
} a;

这也可能是<stdint.h>的一个很好的应用,但这是另一个问题的主题。


* 你可能想知道为什么演员阵容存在......这是因为(A)尽管被标准禁止,但是在现有的C程序中广泛使用了类型惩罚,特别是操作软件,以及(B)大多数符合要求的用途定义了通用接口,但总是(或者,通常通常)在撤消引用之前将其转换回原始类型。

答案 3 :(得分:-1)

也许可以尝试: -

char array[] = {1,2,3};     //FL, FH, Size
int val =0;
val = *(short*)array;
printf("value of p is %X\n",val);

这假设您正在尝试将char数组重新解释为int。虽然不同的平台可能会得到与预期不同的结果。