我有以下代码。
#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
没有指针运算,所有地址都相同但是当我进行指针运算时我得到不同的地址。
请帮助我做指针运算的正确方法。
如果您使用
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;
}
没有指针运算,所有地址都相同但是当我进行指针运算时我得到不同的地址。
C 使用指向的指针的基类型来计算偏移量。
char
的大小为 1,因此将 26 添加到 char *
类型的指针会将 (1 * 26) 添加到指针中的地址。 int
的大小为(比方说)4,因此将 26 添加到 int *
会增加 (4 * 26)。你得到不同的地址,因为你将指针投射到不同大小的不同类型。
请帮助我做指针运算的正确方法。
正确的做法是省略演员表;一般来说,在计算中使用它之前将指针转换为不同的类型是没有意义的,因为你没有改变内存中值的大小或类型。
请帮助我做指针运算的正确方法。
停止投射。 (转换为
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`.