int arr[]={1,2,3};
char* p;
p=arr;
这是程序的一个片段,它可以工作。
任何人都可以解释如何将int变量地址分配给char指针?
答案 0 :(得分:0)
这样可行,因为char指针的大小与int指针的大小相同。但是,当应用某些指针算法时,您将无法获得有效结果。这意味着如果您想访问数组的第二个元素 - p[1]
,那么只有一个字节会添加到p地址。如果p
的类型为int,则会添加4个字节(因为这是int的大小),第二个元素将被正确访问。
#include <stdio.h>
int main(void)
{
int arr[] = {1,2,3};
char* p;
p = arr;
printf("%d\n", p[0]);
printf("%d\n", p[1]);
int* pp = arr;
printf("%d\n", pp[0]);
printf("%d\n", pp[1]);
return 0;
}
输出:
1
0 - as you can see that is not the value from arr[1]
1
2
由于我的英特尔处理器是小端,内存中的arr[0]
存储如下:
01 00 00 00
^
p[0]
等于*(p + 1)的 p[1]
将向p指针添加一个字节,因为p的大小为char。
01 00 00 00
^
p[1]
和printf("%d\n, p[1]);
给出0.请注意,如果您使用的是大端机器,则打印p[0]
的结果会有所不同(例如0)。
但是,您的编译器应该警告您正在做什么。
警告:从不兼容的指针类型分配[启用 默认]
答案 1 :(得分:0)
将char点指定给整数数组的地址时,可能会发生很多事情,具体取决于整数的大小。下面是在32位Windows OS下编译的数组的内存位置。您可能还想将其转换为p =(char *)arr。
01 00 00 00 02 00 00 00 03 00 00 00
int arr[]={1,2,3};
// arr[0] = 1;
// arr[1] = 2;
// arr[2] = 3;
char* p;
p=(char*)arr;
// p[0] = 1
// p[1] = 0
// p[2] = 0
// p[3] = 0
// p[4] = 2
// p[5] = 0
// p[6] = 0
// p[7] = 0
// p[8] = 3
// p[9] = 0
// p[10] = 0
// p[11] = 0
答案 2 :(得分:0)
您的代码无效。在C语言中,如果没有显式转换,则int *
指针不能分配给char *
指针。 C语言禁止分配不兼容的指针类型。 (即它禁止在这些类型之间进行隐式转换)。您的编译器可能会发出一条诊断消息,告诉您完全相同的事情。您的代码包含约束违规 - 它不是有效的C代码。
很久以前,这种转换在C语言的古老非标准化版本中是合法的。出于这个原因,默认情况下,C编译器对于这种无效代码是相当宽容的。他们发出诊断消息作为&#34;警告&#34;,但继续编译代码,这误导了一些人相信代码是有效的。
许多C编译器为您提供了其他选项,使其在检测此类错误时更加明确。例如,在GCC中,您必须指定-pedantic-errors
开关以使用&#34;错误&#34;报告此约束违规。消息。
如果编译器接受了代码,其行为与编写p = (char *) arr
时的行为相同,即它使p
指向arr
数组的开头。这就是它的全部内容。如果您尝试通过指针p
访问数组数据,则只需重新解释 arr
占用的内存作为char
的序列。您将看到的将取决于许多依赖于实现的因素。 (即你没有通用的答案&#34;为什么我看到0
?为什么我在那里看到2
?&#34;问题。)例如,重新解释的数据会看起来 big-endian 和 little-endian 平台之间存在差异。
答案 3 :(得分:0)
您的编译器应该警告您这是不兼容的。
分配后,让我们说arr的地址是1000,arr [0]将在地址1000,arr [1]将在地址1004,arr [2]将在地址1008
现在p指向arr,所以它指向地址1000,所以每次你想访问arr [1]你都必须使用*(p + 4),因为char只有1个字节(同样要小心如果它是一个小端或大端机)
虽然它不兼容,但你可以使用它,但是当你使用这个任务时你应该小心。
gdb输出。
(gdb) p *p
$8 = 1 '\001'
(gdb) p *(p+1)
$9 = 0 '\000'
(gdb) p *(p+2)
$10 = 0 '\000'
(gdb) p *(p+3)
$11 = 0 '\000'
(gdb) p *(p+4)
$12 = 2 '\002'
(gdb) p *(p+5)
$13 = 0 '\000'
(gdb) p *(p+6)
$14 = 0 '\000'
(gdb) p *(p+7)
$15 = 0 '\000'
(gdb) p *(p+8)
$16 = 3 '\003'
答案 4 :(得分:0)
是的,您可以将任何类型的变量地址分配给任何类型的指针(但是您可能会收到有关分配不兼容指针类型的警告)。这是因为任何类型的sizeof指针都是相同的。
例如: -
int main(void)
{
char *c;
int *i;
float *f;
printf("%d %d %d",sizeof(c),sizeof(i),sizeof(f)); // Output: 4 4 4
}
这样的副作用:
考虑以下示例:
int main(void)
{
int i1=127;
int i2=128;
char *c1=&i1;
char *c2=&i2;
printf("%d %d",*c1,*c2); //Output : 127 -128
}
为了理解这个输出,你需要考虑变量的二进制值。
让我们从i1开始: - i1的二进制值是
00000000 00000000 00000000 01111111
并通过将此内存的地址分配给char指针使char指针c1指向第一个字节(Little Endian方法)。
现在i2的二进制值是
00000000 00000000 00000000 10000000
这里再次c2指向第一个字节,但为什么输出是-128? 因为第一个字节是10000000,符号位是1,这意味着数字是负数 现在执行2的补码
的反向操作10000000 ---> 01111111(minus one) --->10000000(one's complement)