指针运算的正确方法

问题描述 投票:0回答:3

我有以下代码。

#include<stdio.h>
typedef struct cache_malloc {
    int     size;
    int     flags;
    struct cache_malloc *fwd;
    struct cache_malloc *bak;
} cache_malloc_t;

int main()
{
  cache_malloc_t cmp;
  cache_malloc_t *new = &cmp;
  new->size = 10;
  new->flags = 1;
  
  printf("======without Arithematic======\n");
  printf("(char *)new = %p \n",  (((char *)new)));
  printf("(void *)new = %p \n",  (((void *)new)));
  printf("(int *)new = %p \n",  (((int *)new)));

  printf("======with Arithematic======\n");
  printf("(char *)new = %p \n",  ((((char *)new)+ 26)));
  printf("(void *)new = %p \n",  ((((void *)new)+ 26)));
  printf("(int *)new = %p \n",  ((((int *)new) + 26)));

  return 0;
}

输出如下所示

======without Arithematic======
(char *)new = 0xffd65dcc 
(void *)new = 0xffd65dcc 
(int *)new = 0xffd65dcc 
======with Arithematic======
(char *)new = 0xffd65de6 
(void *)new = 0xffd65de6 
(int *)new = 0xffd65e34 

没有指针运算,所有地址都相同但是当我进行指针运算时我得到不同的地址。

请帮助我做指针运算的正确方法。

c pointers
3个回答
3
投票

如果您使用

printf
,您所有的
void *
都会调用未定义的行为(UB),因为您需要转换为
%p

type *ptr;
type *ptr1 = ptr + x;

当你做指针运算时,你添加的数字与指针的类型有关。所以实际地址差异(以

char
s为单位)将是
sizeof(type) * x

typedef struct cache_malloc {
    int     size;
    int     flags;
    struct cache_malloc *fwd;
    struct cache_malloc *bak;
} cache_malloc_t;

int main()
{
  cache_malloc_t cmp;
  cache_malloc_t *new = &cmp;
  new->size = 10;
  new->flags = 1;
  
  printf("======without Arithematic======\n");

  printf("======with Arithematic======\n");
  printf("(char *)new = %p \n",  (void *)((((char *)new)+ 26)));
  printf("(double *)new = %p \n",  (void *)((((double *)new)+ 26)));
  printf("(int *)new = %p \n",   (void *)((((int *)new) + 26)));

  uintptr_t uptr = (uintptr_t) new;

  printf("======test======\n");
  printf("char   %zx \n",  uptr + 26 * sizeof(char));
  printf("double %zx \n",  uptr + 26 * sizeof(double));
  printf("int    %zx \n",  uptr + 26 * sizeof(int));

  return 0;
}

https://godbolt.org/z/jffxqYKr5


2
投票

没有指针运算,所有地址都相同但是当我进行指针运算时我得到不同的地址。

C 使用指向的指针的基类型来计算偏移量。

char
的大小为 1,因此将 26 添加到
char *
类型的指针会将 (1 * 26) 添加到指针中的地址。
int
的大小为(比方说)4,因此将 26 添加到
int *
会增加 (4 * 26)。你得到不同的地址,因为你将指针投射到不同大小的不同类型。

请帮助我做指针运算的正确方法。

正确的做法是省略演员表;一般来说,在计算中使用它之前将指针转换为不同的类型是没有意义的,因为你没有改变内存中值的大小或类型。


2
投票

请帮助我做指针运算的正确方法。

  • 停止投射。 (转换为

    void *
    以打印合理的异常。)

  • 不要在

    +
    指针上尝试
    -
    void *

  • 可以在

    (u)intptr_t
    整数上使用数学,只是不要指望代码可以可靠地将整数转换为有效指针。
    (u)intptr_t
    根本不需要做 指针算术 甚至打印指针的值。

  • 只使用

    +
    ,
    -
    导致指针在(或过去)同一对象(例如数组)中。

int a;
int *p = &a;
printf("%p\n", (void*) &a);
printf("%p\n", (void*) p);
printf("%p\n", (void*) (&a + 1));
printf("%p\n", (void*) (p + 1));
// Not OK
printf("%d\n", p[1]);  // Not OK to de-reference `p + 1`.
int b[100];
int *q = &b[50];
printf("%p\n", (void*) &b);
printf("%p\n", (void*) q);
printf("%p\n", (void*) (&b + 100));
printf("%p\n", (void*) (q + 50));
printf("%p\n", (void*) (q - 50));
// Not OK
printf("%p\n", (void*) (q + 51));
printf("%p\n", (void*) (q - 51));
printf("%d\n", q[100]);  // Not OK to de-reference `p + 1`.
© www.soinside.com 2019 - 2024. All rights reserved.