数组与C中的指针有多大不同?

时间:2016-10-18 12:20:56

标签: c arrays

在以下程序中,

#include<stdio.h>
int main(){
  int a = 1025;
  int *p;
  p = &a;

  char *p0;
  p0 = (char *)p;


  //print("\n%d %d", *p0, *(p0+1));
  printf("\n%d and %d", *p0, p0[1]);

}

输出:

1和4

char&amp; int是C中的算术类型,为了理解类型转换后的输出,我需要理解1025的二进制表示,即00000000 00000000 00000100 00000001Intel arch的小字节序将采用第一个字节00000001

问题:

对于用java编写的上述程序,数组表示法不能用于访问int的每个字节。

在上面的C程序中,数组表示法可以替代地用于访问int的每个字节。

根据这个程序,C中指针的数组有多大不同?

4 个答案:

答案 0 :(得分:1)

array - 内存中实际存在的一系列连续元素。它有一个地址,通常被认为是数组第一个元素的地址。

指针 - 包含地址的变量。指针中包含的地址可能会也可能不会指向实际内存。

以这种方式思考 - 您的家有一个地址。它存在某处,你可以把东西放进去 - 它是一个数组。您可以在信封上放置任何地址并尝试邮寄。由于很多原因,它可能会或可能不会正确交付 - 写在信封上的街道地址是指针。你不能在写作中存储任何东西。

答案 1 :(得分:0)

  

对于用java编写的上述程序,数组表示法不能用于访问int的每个字节。

你是对的

  

在上面的C程序中,数组表示法可以替代地用于访问int的每个字节。

是的,您可以声明char指针,将其指向int的第一个字节,然后使用数组表示法访问int变量的每个字节。

您可以使用相同的方式声明数组

char arr[3]={1,2,3};

并将其用作指针

char *prt;
prt = arr;

这相当于

ptr = & ( arr[0] ); // The address of the first element of arr
  

根据这个程序,C中指针的数组有多大不同?

为简化(根据此程序),数组是指向数组第一个元素的指针。

p0是一个指向数组的指针,其数据为p0[0]p0[1],...

澄清更多信息:

您可以将变量声明为指针或数组。

在您的代码中,您不会声明数组。

但是当您使用p0[1]时,您将p0视为数组。

<强>最后:

我引用......

  

了解类型转换后的输出

请参阅https://stackoverflow.com/a/6752688/1579327

将较大类型转换为较小类型的结果是未定义的(取决于实现)iF较小的类型是有符号的,而较大类型的值不适合较小的类型。

答案 2 :(得分:0)

严格回答标题中的问题 - 数组不是指针:

  • int arr[10]

    • 使用的内存量为sizeof(int)*10字节

    • arr&arr的值必须相同

    • arr指向有效的内存地址,但不能设置为指向任何其他内存地址(即,它用作常量“标签”)

  • int* ptr = malloc(sizeof(int)*10)

    • 使用的内存量为sizeof(int*) + sizeof(int)*10字节

    • ptr&ptr的值不一定相同(事实上,它们大多不同)

    • ptr可以设置为指向有效和无效的内存地址(即,您可以在运行时更改它的次数)

答案 3 :(得分:0)

即使它们不是同一个东西, 是C中数组和指针之间的密切关系。数组下标操作a[i]是根据指针算法定义的:

a[i] == *(a + i)

即,从该地址获取数组基类型的地址 a,偏移i 元素,取消引用结果。例如,如果aint的数组,则表达式a + 1将计算到下一个整数对象的地址,该地址将存储在{{1}可能是2,4或8个字节之外的任何地方。

数组不是指针;但是,除非它是a或一元sizeof运算符的操作数,或者是字符串文字用于初始化声明中的另一个数组,表达式类型&#34; N元素数组&&#34;将被转换(&#34;衰减&#34;)到类型为#34的表达式;指向T&#34;的指针,并且表达式的值将是该表达式中第一个元素的地址阵列。

所以,给定代码

T

在语句int a[10]; a[2] = 2; 中,表达式 a[2] = 2不是a或一元sizeof运算符的操作数,因此它被转换(&#34;衰变&#34;)从类型&int [10],它评估为int *的第一个元素的地址。然后,我们从该地址偏移2个a类型的元素,并将值2分配给该位置。请注意,此转换适用于表达式 int,而不是它所引用的数组对象。

那么与你的代码有什么关系?

在C中,非位域对象由一个或多个字节的连续序列组成。根据定义,a类型的对象占用1个字节,因此任何多字节类型的对象(charintlongfloat等等)可以视为double(或char)的数组。

图片可能会有所帮助 - 我拿了你的代码并使用了我编写的一个小工具来将每个对象的内容转储到内存中:

unsigned char

Item Address 00 01 02 03 ---- ------- -- -- -- -- a 0x7ffffa8a29cc 01 04 00 00 .... p 0x7ffffa8a29c0 cc 29 8a fa .).. 0x7ffffa8a29c4 ff 7f 00 00 .... p0 0x7ffffa8a29b8 cc 29 8a fa .).. 0x7ffffa8a29bc ff 7f 00 00 .... 的二进制表示形式为1025。如您所见,对象0x0401宽度为4个字节,包含字节序列a。这是在x86系统上,它是little-endian,因此至少有效字节在序列中排在第一位。

{0x01, 0x04, 0x00, 0x00}p都存储p0的地址。我在64位系统上,因此指针值为8字节宽。

a计算*p0中第一个字节的值,在本例中为a0x01等同于p0[1],并计算*(p0 + 1)后面的第二个字符值的值,在本例中为p0