#include<stdio.h>
int main()
{
char arr[] = "somestring";
char *ptr1 = arr;
char *ptr2 = ptr1 + 3;
printf("ptr2 - ptr1 = %ld\n", ptr2 - ptr1);
printf("(int*)ptr2 - (int*) ptr1 = %ld", (int*)ptr2 - (int*)ptr1);
return 0;
}
I understand
我理解
ptr2 - ptr1
gives 3 but cannot figure out why second printf prints 0.
给出3,但无法找出为什么第二个printf输出为0。
4 个解决方案
#1
8
It's because when you substract two pointers, you get the distance between the pointer in number of elements, not in bytes.
因为当你消去两个指针时,你得到的是元素之间的距离,而不是字节。
(char*)ptr2-(char*)ptr1 // distance is 3*sizeof(char), ie 3
(int*)ptr2-(int*)ptr1 // distance is 0.75*sizeof(int), rounded to 0
EDIT: I was wrong by saying that the cast forces the pointer to be aligned
编辑:我说施放强制指针对齐是错误的
#2
4
If you want to check the distance between addresses don't use (int *)
or (void *)
, ptrdiff_t
is a type able to represent the result of any valid pointer subtraction operation.
如果您想检查地址之间的距离不使用(int *)或(void *), ptrdiff_t是一种能够表示任何有效的指针减法操作的结果的类型。
#include <stdio.h>
#include <stddef.h>
int main(void)
{
char arr[] = "somestring";
char *ptr1 = arr;
char *ptr2 = ptr1 + 3;
ptrdiff_t diff = ptr2 - ptr1;
printf ("ptr2 - ptr1 = %td\n", diff);
return 0;
}
EDIT: As pointed out by @chux, use "%td"
character for ptrdiff_t
.
编辑:如@chux所指出,使用“%td”字符作为ptrdiff_t。
#3
1
Casting a char
pointer with int*
would make it aligned to the 4bytes (considering int is 4 bytes here). Though ptr1
and ptr2
are 3 bytes away, casting them to int*
, results in the same address -- hence the result.
使用int*转换字符指针将使其对齐到4bytes(这里考虑到int是4个字节)。虽然ptr1和ptr2相距3个字节,但将它们转换为int*,结果是相同的地址——因此得到了结果。
#4
0
This is because sizeof(int) == 4
这是因为sizeof(int) = 4
Each char takes 1 byte. Your array of chars looks like this in memory:
每个字符占用一个字节。你的chars数组在内存中是这样的:
[s][o][m][e][s][t][r][i][n][g][0]
When you have an array of ints, each int occupies four bytes. storing '1' and '2' conceptually looks more like this:
当您有一个ints数组时,每个int都占用4个字节。存储“1”和“2”的概念看起来更像这样:
[0][0][0][1][0][0][0][2]
Ints must therefore be aligned to 4-byte boundaries. Your compiler is aliasing the address to the lowest integer boundary. You'll note that if you use 4 instead of 3 this works as you expected.
因此,Ints必须对齐到4字节的边界。你的编译器将地址混叠到最低的整数边界。您将注意到,如果您使用4而不是3,那么它就会像您预期的那样工作。
The reason you have to perform a subtraction to get it to do it (just passing the casted pointers to printf doesn't do it) is because printf
is not strictly typed, i.e. the %ld
format does not contain the information that the parameter is an int pointer.
您必须执行减法才能实现它(只是将已转换的指针传递给printf而不这样做)的原因是printf不是严格的类型化的,即%ld格式不包含参数是int指针的信息。
#1
8
It's because when you substract two pointers, you get the distance between the pointer in number of elements, not in bytes.
因为当你消去两个指针时,你得到的是元素之间的距离,而不是字节。
(char*)ptr2-(char*)ptr1 // distance is 3*sizeof(char), ie 3
(int*)ptr2-(int*)ptr1 // distance is 0.75*sizeof(int), rounded to 0
EDIT: I was wrong by saying that the cast forces the pointer to be aligned
编辑:我说施放强制指针对齐是错误的
#2
4
If you want to check the distance between addresses don't use (int *)
or (void *)
, ptrdiff_t
is a type able to represent the result of any valid pointer subtraction operation.
如果您想检查地址之间的距离不使用(int *)或(void *), ptrdiff_t是一种能够表示任何有效的指针减法操作的结果的类型。
#include <stdio.h>
#include <stddef.h>
int main(void)
{
char arr[] = "somestring";
char *ptr1 = arr;
char *ptr2 = ptr1 + 3;
ptrdiff_t diff = ptr2 - ptr1;
printf ("ptr2 - ptr1 = %td\n", diff);
return 0;
}
EDIT: As pointed out by @chux, use "%td"
character for ptrdiff_t
.
编辑:如@chux所指出,使用“%td”字符作为ptrdiff_t。
#3
1
Casting a char
pointer with int*
would make it aligned to the 4bytes (considering int is 4 bytes here). Though ptr1
and ptr2
are 3 bytes away, casting them to int*
, results in the same address -- hence the result.
使用int*转换字符指针将使其对齐到4bytes(这里考虑到int是4个字节)。虽然ptr1和ptr2相距3个字节,但将它们转换为int*,结果是相同的地址——因此得到了结果。
#4
0
This is because sizeof(int) == 4
这是因为sizeof(int) = 4
Each char takes 1 byte. Your array of chars looks like this in memory:
每个字符占用一个字节。你的chars数组在内存中是这样的:
[s][o][m][e][s][t][r][i][n][g][0]
When you have an array of ints, each int occupies four bytes. storing '1' and '2' conceptually looks more like this:
当您有一个ints数组时,每个int都占用4个字节。存储“1”和“2”的概念看起来更像这样:
[0][0][0][1][0][0][0][2]
Ints must therefore be aligned to 4-byte boundaries. Your compiler is aliasing the address to the lowest integer boundary. You'll note that if you use 4 instead of 3 this works as you expected.
因此,Ints必须对齐到4字节的边界。你的编译器将地址混叠到最低的整数边界。您将注意到,如果您使用4而不是3,那么它就会像您预期的那样工作。
The reason you have to perform a subtraction to get it to do it (just passing the casted pointers to printf doesn't do it) is because printf
is not strictly typed, i.e. the %ld
format does not contain the information that the parameter is an int pointer.
您必须执行减法才能实现它(只是将已转换的指针传递给printf而不这样做)的原因是printf不是严格的类型化的,即%ld格式不包含参数是int指针的信息。