C中指针的字节宽度
Width in bytes of a pointer in C
我是动态和静态分配的新手,我注意到一个奇怪的行为。我制作了以下代码片段:
#include ...
int main(void){
int i ;
printf(" using amesand :%p\n", &i);
int *j = malloc(sizeof(*j)) ;
printf(" using malloc :%p\n", j)
}
然后编译并生成:
using amesand :0x7ffc0128695c
using malloc :0x6686b0
我在某处读到
all pointers have the same width within the same implementation.
谁能解释一下为什么 malloc() 返回的指针只有 3 个字节长?
使用sizeof
运算符来确定指针的宽度,例如:
int i;
printf(" using amesand :%zu\n", sizeof( &i ));
int *j = malloc(sizeof(*j));
printf(" using malloc :%zu\n", sizeof( j) );
对于此输出,地址可以具有不同的值,具体取决于相应内存的分配位置。并且使用转换说明符 %p
通常(如您的情况)生成跳过前导零的输出。
all pointers have the same width within the same implementation.
是的,至少对于严格符合 C 的程序。有一些常见的非标准扩展,其中较大的指针与普通指针混合在一起,通常带有非标准关键字 far
.
然而,这不是这里的问题,而只是您对 printf
的使用。默认情况下,它会删除前导零。不仅适用于十六进制,而且适用于任何数字。 printf("%d", 1)
打印 1
对吧?而不是 0000000001
只是因为 int
恰好是 4 个字节 = 10 个十进制数字。指针和十六进制没有什么不同,默认情况下会删除前导零,除非您以其他方式告诉函数。
如果你想打印一个与指针大小相对应的十六进制数,你可以使用 %.16p
表示 16 位 = 8 字节大指针。或者 variably/portably,像这样:
printf(" using malloc :%.*p\n", sizeof(j)*2, j);
在 x86_64 Linux 上测试的更正示例:
#include <stdio.h>
#include <stdlib.h>
int main(void){
int i ;
printf(" using amesand:\t%.*p\n", sizeof(&i)*2, &i);
int *j = malloc(sizeof(*j)) ;
printf(" using malloc:\t%.*p\n", sizeof(j)*2, j);
}
输出:
using amesand: 0x00007ffe8710871c
using malloc: 0x0000000000ed82b0
关于为什么不同的内存类型有不同的地址,看这个:
使用 %p
,您的 C 实现简单地从指针值中省略前导零。
打印“0x6686b0”并不表示指针是三个字节长;它仅表示值为 6686b016,等于 006686b016、00000000006686b016 或 000000000000000000000000000000000006686b016。前导零已被省略。
我是动态和静态分配的新手,我注意到一个奇怪的行为。我制作了以下代码片段:
#include ...
int main(void){
int i ;
printf(" using amesand :%p\n", &i);
int *j = malloc(sizeof(*j)) ;
printf(" using malloc :%p\n", j)
}
然后编译并生成:
using amesand :0x7ffc0128695c
using malloc :0x6686b0
我在某处读到
all pointers have the same width within the same implementation.
谁能解释一下为什么 malloc() 返回的指针只有 3 个字节长?
使用sizeof
运算符来确定指针的宽度,例如:
int i;
printf(" using amesand :%zu\n", sizeof( &i ));
int *j = malloc(sizeof(*j));
printf(" using malloc :%zu\n", sizeof( j) );
对于此输出,地址可以具有不同的值,具体取决于相应内存的分配位置。并且使用转换说明符 %p
通常(如您的情况)生成跳过前导零的输出。
all pointers have the same width within the same implementation.
是的,至少对于严格符合 C 的程序。有一些常见的非标准扩展,其中较大的指针与普通指针混合在一起,通常带有非标准关键字 far
.
然而,这不是这里的问题,而只是您对 printf
的使用。默认情况下,它会删除前导零。不仅适用于十六进制,而且适用于任何数字。 printf("%d", 1)
打印 1
对吧?而不是 0000000001
只是因为 int
恰好是 4 个字节 = 10 个十进制数字。指针和十六进制没有什么不同,默认情况下会删除前导零,除非您以其他方式告诉函数。
如果你想打印一个与指针大小相对应的十六进制数,你可以使用 %.16p
表示 16 位 = 8 字节大指针。或者 variably/portably,像这样:
printf(" using malloc :%.*p\n", sizeof(j)*2, j);
在 x86_64 Linux 上测试的更正示例:
#include <stdio.h>
#include <stdlib.h>
int main(void){
int i ;
printf(" using amesand:\t%.*p\n", sizeof(&i)*2, &i);
int *j = malloc(sizeof(*j)) ;
printf(" using malloc:\t%.*p\n", sizeof(j)*2, j);
}
输出:
using amesand: 0x00007ffe8710871c
using malloc: 0x0000000000ed82b0
关于为什么不同的内存类型有不同的地址,看这个:
使用 %p
,您的 C 实现简单地从指针值中省略前导零。
打印“0x6686b0”并不表示指针是三个字节长;它仅表示值为 6686b016,等于 006686b016、00000000006686b016 或 000000000000000000000000000000000006686b016。前导零已被省略。