当运行此代码:指针在C,整数指针字符指针
int arr[3] = {2,3,4};
char *p;
p = (char*)arr;
printf("%d", *p);
p = p+1;
printf("%d", *p);
输出是2和0。第二个结果是稍微混乱。有人可以解释为什么发生这种情况?
当运行此代码:指针在C,整数指针字符指针
int arr[3] = {2,3,4};
char *p;
p = (char*)arr;
printf("%d", *p);
p = p+1;
printf("%d", *p);
输出是2和0。第二个结果是稍微混乱。有人可以解释为什么发生这种情况?
让我们打破这:
int arr[3] = {2,3,4};
创建的3个整数的数组。假设你的系统是32位小尾数,这是它的外观在内存:
02 00 00 00 03 00 00 00 04 00 00 00
char *p; p = (char*)arr;
p
现在指向arr
但它是一个指针char*
。换句话说,p
指向02
。
printf("%d", *p);
您打印为int
由p
引用的位置。所以,当你提领p
(写*p
)您正在访问的char
(因为p
是类型char*
的)由p
引用。这是02
。
p = p+1;
p
现在指向00
刚02
后,因为p
是char*
。所以当你加1时,它会在内存中移动1 * sizeof(char) = 1 * 1 = 1
字节。
printf("%d", *p);
您打印为int
由p
引用的位置。因此,当您使用取消引用p
(通过书写*p
)您正在访问p
引用的char
(因为p
的类型为char*
)。这是00
。
如果你想打印3
而不是0
你有你的指针类型更改为int*
而不是char*
,通过在内存1 * sizeof(int) = 1 * 4 = 4
字节使指针移动。
非常感谢!!! :-) – user1124236 2011-12-31 11:28:05
我还要强调,当读取'int'类型的值时,就好像它们是'char是合法的,确切的结果取决于实施。在别处编译时可能会得到另一个结果。 @Cicada必须对平台做出假设才能提供答案。 – Kos 2011-12-31 11:30:43
假设int是32位,如果平台是32位或64位(甚至16位),则无关紧要。在一个翻转的笔记上,对endianness的思考对我来说发生得非常晚,我曾经假设只存在小端类型。来自6502,z80和8088,令人惊讶的是这些数字可以用不同的方式表示。 – bestsss 2011-12-31 17:20:19
你得到的结果将取决于你的实现和它的字节顺序的大小int
。
假设32位整型,8位字符和豆蔻端环境(比如86),arr
会是这样的记忆:
<arr[0]> <arr[1]> <arr[2]>
02 00 00 00 03 00 00 00 04 00 00 00
^^ ^
p p+1 ... p+4
如果你把一个字符指针到内存的开始,打印出第一个元素,应输出2
。如果增加该指针,则会输出0。您需要将其增加几次以“看”3.
请注意,在具有相同类型大小的大端环境中,您的程序将输出两个零,因为布局可能是:
<arr[0]> <arr[1]> <arr[2]>
00 00 00 02 00 00 00 03 00 00 00 04
^^ ^
p p+1 ... p+4
这里是一个贴,可以让你了解这个问题更好:http://codepad.org/ClrrwjKY
正如你所看到的,连续整数的值出现三个零分开。这是因为一个整数是4个字节长,而一个char只有1个字节长。因此,当int数组转换为char时,可以逐字节(或char by char)而不是四个字节(int by int)迭代它。
这是因为所谓的endianness。
当你创建了int arr[3] = {2, 3, 4};
它就会在内存中创建一个数组如下
Big endian:
0 1 2 3 4 5 6 7 8 9 10 11
+---+---+---+--------+---+---+---+--------+---+---+---+--------+
| | | | ..0010 | | | | ..0011 | | | | ..0100 |
+---+---+---+--------+---+---+---+--------+---+---+---+--------+
<-- 2 --><-- 3 --><-- 4 -->
Little endian:
0 1 2 3 4 5 6 7 8 9 10 11
+--------+---+---+---+---------+---+---+---+--------+---+---+---+
| ..0010 | | | | ..0011 | | | | ..0100 | | | |
+--------+---+---+---+---------+---+---+---+--------+---+---+---+
<-- 2 --><-- 3 --><-- 4 -->
要了解更多,你需要修改你的程序如下:
int main(void)
{
int arr[3] = {2, 3, 4};
char *p = (char*) arr;
int i;
int size = (int)sizeof(arr);
for (i=0; i<size ; i++) {
printf("%d", *p);
p++;
}
return 0;
}
而且,检查您硬件的字节顺序,您可以使用以下功能。仅由1 作为阵列
void endian(void)
{
int i = 1;
if (*(char *) &i == 1)
printf("Little endian \n");
else
printf("Big endian \n");
return;
}
这里为“p”为一个字符指针.. P + 1倍的增量p的电流值是整数,以便通过一个访问数组一个的每个值,就必须通过2. 递增字符数组如果整数数组的地址因此1000 ,
arr[0] is at 1000
arr[1] is at 1002
arr[2] is at 1004
和改编的值是ARR [0]的地址; 所以最初
p=arr=1000
当p递增,p是1001而ARR [1]是1002
..所以为了访问所有的值你就必须增加p的值的两倍每次..
这是功课吗?如果是这样 - 相应地标记它。 – littleadv 2011-12-31 11:08:28
当你*运行这段代码时发生了什么?推理:在发布问题之前,向我们展示您尝试过的内容以及结果是个好主意。 – 2011-12-31 11:11:10
输出是2和0.第二个结果有点混乱。因此,这个问题。我是一位心脏外科医生,他正在努力帮助我的儿子完成作业。不幸的是,上帝并没有让我们所有人都成为C专家。 – user1124236 2011-12-31 11:12:57