Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 指针的分配?_C_Pointers - Fatal编程技术网

C 指针的分配?

C 指针的分配?,c,pointers,C,Pointers,这是一个程序的片段,它可以正常工作 有人能解释一下如何将int变量地址分配给char指针吗 这是可行的,因为char指针的大小与int指针的大小相同。但是,当应用某些指针算法时,将不会得到有效的结果。这意味着,如果要访问数组的第二个元素-p[1],则只会向p地址添加一个字节。如果p的类型是int,那么将添加4个字节(因为这是int的大小),第二个元素将被正确访问 int arr[]={1,2,3}; char* p; p=arr; 由于我的英特尔处理器是little endian,内存中的ar

这是一个程序的片段,它可以正常工作


有人能解释一下如何将int变量地址分配给char指针吗

这是可行的,因为char指针的大小与int指针的大小相同。但是,当应用某些指针算法时,将不会得到有效的结果。这意味着,如果要访问数组的第二个元素-
p[1]
,则只会向p地址添加一个字节。如果
p
的类型是int,那么将添加4个字节(因为这是int的大小),第二个元素将被正确访问

int arr[]={1,2,3};
char* p;
p=arr;
由于我的英特尔处理器是little endian,内存中的
arr[0]
存储如下:

1
0  - as you can see that is not the value from arr[1]
1
2
p[1]
相当于*(p+1),将向p指针添加一个字节,因为p的大小是char

01 00 00 00
^
p[0]
printf(“%d\n,p[1]);
给出0。请注意,如果您在big-endian机器上,打印
p[0]
的结果将不同(例如0)

但是,编译器应该警告您正在执行的操作

警告:来自不兼容指针类型的分配[由启用] 默认值]


当您将字符点分配给整数数组的地址时,可能会发生许多事情,具体取决于整数的大小。下面是32位windows操作系统下编译时数组的内存位置。您可能还希望将其强制转换为p=(char*)arr

01 00 00 02 00 00 03 00 00 00 00 00

01 00 00 00
   ^
   p[1]

您的代码无效。在C语言中,如果不进行显式转换,则无法将
int*
指针分配给
char*
指针。C语言禁止分配不兼容的指针类型。(即,它禁止在此类类型之间进行隐式转换)。您的编译器可能发出了一条诊断消息,告诉您完全相同的事情。您的代码包含约束冲突-它不是有效的C代码

这种转换在很久以前是合法的,在C语言的古老的非标准化版本中。因此,默认情况下,C编译器对这类无效代码相当宽容。它们以“警告”的形式发出诊断消息,但继续编译代码,这会误导一些人相信代码是有效的

许多C编译器为您提供了额外的选项,使它们在检测此类错误时更加明确。例如,在GCC中,您必须指定
-pedantic errors
开关,以使用“error”消息报告此约束冲突


如果编译器接受该代码,其行为与编写
p=(char*)arr
时相同,即它使
p
指向
arr
数组的开头。就这些。如果试图通过指针
p
访问数组数据,只需将
arr
占用的内存重新解释为
char
s序列。您将看到的内容将取决于许多依赖于实现的因素。(也就是说,对于您的“为什么我在那里看到
0
呢?为什么我在那里看到
2
呢?”问题,没有通用的答案。)例如,在大端和小端平台之间,重新解释的数据看起来会有所不同。

您的编译器应该警告您这是不兼容的

分配后,假设arr的地址为1000,arr[0]将位于地址1000,arr[1]将位于地址1004,arr[2]将位于地址1008

现在p指向arr,所以它指向地址1000,所以每次您想要访问arr[1]时,您都必须使用*(p+4),因为char仅为1字节(如果是小端或大端机器,也要小心)

虽然它不兼容,但您可以使用它,但使用此作业时应小心

gdb输出。

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

是的,您可以将任何类型的变量的地址分配给任何类型的指针(但是您可能会收到关于分配不兼容指针类型的警告)。这是因为任何类型的指针的大小都是相同的

例如:-

(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'
这种方法的副作用:

考虑以下示例:

int main(void)
{
    char *c;
    int *i;
    float *f;
    printf("%d %d %d",sizeof(c),sizeof(i),sizeof(f)); //  Output: 4 4 4
}

为了理解这个输出,需要考虑变量的二进制值。

让我们从i1开始:-i1的二进制值为

int main(void)
{
     int i1=127;
     int i2=128;

     char *c1=&i1;
     char *c2=&i2; 

     printf("%d %d",*c1,*c2);  //Output : 127 -128
}
通过将这个内存的地址分配给char指针,char指针c1指向第一个字节(小端方法)

现在i2的二进制值是

00000000 00000000 00000000 01111111
这里c2再次指向第一个字节,但为什么输出是-128? 因为第一个字节是10000000,所以符号位是1,这意味着数字是负数 现在执行2的补码的反向运算

00000000 00000000 00000000 10000000

你查过p[1]了吗?它不应该是“2”printf(“%d”,*p);打印2p=(int*)(p+1);这会将*p打印为0。@user3465845:您使用的编译器是什么?@user3465845:虽然行为依赖于平台,但在任何情况下,
printf(“%d”,*p)
都无法实际打印
2
。你在编什么东西。printf(“%d”,*p);以及为什么这会发生在你身上,请提供一个最少的代码示例。对我来说,它像对其他人一样打印1。@macfij:只有在小型endian机器(例如英特尔机器)上,它才会打印
1
。如果您使用的是big-endian机器(例如SPARC或Power),它会打印
0
@JonathanLeffler您是对的。我所说的“其他人”是指这条线索中的人。我假设他们也有基于英特尔的机器;印刷品2。为什么?我的编译器在printf(“%d”,*p)上打印了1。我不明白为什么要打印2.对不起,我的错。p=(char*)((int*)(p));printf(“%d,”,*p);这张照片2@user3465845:没有。在上述代码的上下文中,这没有任何机会“打印2”。如果您看到2,这意味着您对代码进行了一些更改,但没有向我们显示这些更改。这里没有人有心灵感应。
p=(char*)((int*)(p))
在这种情况下不起作用。它什么也不做。
00000000 00000000 00000000 10000000
10000000 ---> 01111111(minus one) --->10000000(one's complement)