【问题标题】:pointer arithmetic (char*) &a[1] - (char *)&a[0] == 4指针算术 (char*) &a[1] - (char *)&a[0] == 4
【发布时间】:2013-12-10 05:14:03
【问题描述】:

如果a是一个int数组,(char*) &a[1] - (char *)&a[0]等于4,而&a[1] - &a[0]等于1。这是为什么呢?

【问题讨论】:

  • 4 字节对齐?在第一种情况下进行指针转换后,您将获得正确的信息。
  • 指针算法是根据所指向对象的大小来计算的。
  • 所以一旦它被转换,编译器认为这两个元素是字节分开的,这种差异意味着它们之间有 4 个字符,所以它返回一个 4。而在非转换的情况下,编译器认为这两个元素相隔 4 个字节,但它们相隔 1 个 int 元素,所以它返回 1?
  • 是指针运算,就像指针减法一样。

标签: c pointers casting


【解决方案1】:

指针数学运算取决于其指向的数据结构的大小。这是因为如果我这样做:

int array[10] ;
int * p = array ;

p ++ ;

我希望 p 指向第二个 int,而不是两个元素之间的内存。

所以&a[1] 与&a[0] 相距四个字节,但问它&a[1] - &a[0] 询问它相距多少ints。当您将其转换为 char 时,您要求根据 char 的大小进行数学运算。

【讨论】:

    【解决方案2】:

    当你这样做时

    &a[1] - &a[0]
    

    因为 a 是一个 int 数组,所以假定一个隐式 (int *) 指针,即

    (int *)&a[1] - (int *)&a[0]
    

    因此,由于两者都是指向 int 的类型指针,因此它们的差值为 1。

    但是当你这样做时-

    (char*) &a[1] - (char *)&a[2]
    

    假设在您的编译器上 int 是 4 个字节而 char 是 1 个字节,那么差异将是 4,因为 a 的每个元素都是 int 并且有四个字节。

    【讨论】:

      【解决方案3】:

      这是程序员将指针视为只是地址的常见问题。这是错误的做法。为了让编译器创建适当的低级代码,它必须了解更多关于指针的信息,而不仅仅是它指向的内存位置。该附加信息是指针指向的对象的大小。这一切都包含在指针类型中,并且对于指针算法是必需的。例如:

      int a[25] ;
      int *i_ptr = a;
      
      printf("address of 1st element %d\n", a);
      printf("address of 1st element %d\n", &a[0]);
      
      // address of first element + sizeof(int)
      printf("address of 2nd element %d\n", a+1);
      
      // address of first element + sizeof(int)    
      printf("address of 2nd element %d\n", &a[1]);
      
      // this one is tricky
      // address of first element + sizeof(25*int) ie sizeof(the whole array)
      printf("address of JUST AFTER THE ARRAY %d\n", &a+1);
      

      Last 非常棘手,大多数程序员甚至都不知道它。虽然 a 指向数组的第一个元素并且具有数组元素的类型 &a 是完全不同的东西。它还保留数组的第一个元素的地址(即数组开始),但它的类型不同,这表明编译器对其的指针运算将基于数组大小而不是元素大小。

      给予:

      address of 1st element 2881388               +0
      address of 1st element 2881388               +0
      address of 2nd element 2881392               +4
      address of 2nd element 2881392               +4
      address of JUST AFTER THE ARRAY 2881488    +100
      

      每次您使用 & 运算符获取某物的地址时,它都有与之关联的类型,以便以后使用该类型的指针进行计算。

      请记住,有一个指针 void * 没有与之关联的任何类型信息,您无法对其执行算术运算。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-23
        • 2017-09-05
        • 2013-06-03
        • 2011-08-31
        • 1970-01-01
        • 2013-08-24
        • 2021-02-01
        • 1970-01-01
        相关资源
        最近更新 更多