我有一个案例,其中uint64_t*
,char*
(6个字符长)和uint16_t*
指向地址x
,{{分别为1}}和x+2
。所以如果char *指向"这个我"那么x
应指向值uint16_t*
dec,而0
应指向值uint64_t*
dec。
但是当我看到这些值时,115, 588, 096, 157, 780
我得到0分,我不明白为什么会这样。有人可以解释一下吗?
编辑(添加代码):
uint64_t
,输出为:
FILE *file = fopen("/Users/Justin/Desktop/test.txt", "rb");
uint64_t *window = malloc(8);
char *buffer = (char*)(window+2);
uint16_t *data = (uint16_t*)window;
uint16_t *read = (uint16_t*)(window+6);
fread(buffer, 6, 1, file);
printf("%p\n", window);
printf("%p\n", buffer);
printf("%p\n", data);
printf("%p\n", read);
printf("%s\n", buffer);
printf("%llu\n", *window);
答案 0 :(得分:6)
你被指针数学绊倒了。
当window
声明为uint64_t *
时,window + 2
不会将地址增加两个字节;它将它递增2 * sizeof(uint64_t)
(即十六个字节)。结果,您正在查看的内存未初始化(实际上,它位于分配的块之外)。
如果您确实希望地址增加两个字节,那么在向其添加2之前,您需要将指针强制转换为char *
:
char *buffer = ((char *) window) + 2;
答案 1 :(得分:2)
我认为你误解了+2
在这里的作用:
uint64_t *window = malloc(8);
char *buffer = (char*)(window+2);
有助于可视化我们从malloc
获取的数据,使用|
来帮助显示8字节边界:
|-------|-------|-------|-------|-------|-------|-------|-------
^
window
现在,buffer
并未在window
之前指出两个字节。它指出了前面两个uint64_t
。或者换句话说,((char*)window) + 2 * sizeof(*window)
:
|-------|-------|-------|-------|-------|-------|-------|-------
^ ^
window buffer
然后你进入
|-------|-------This i--|-------|-------|-------|-------|-------
^ ^
window buffer
如果您想提前指出两个字节,则必须将2添加到char*
:
char* buffer = ((char*)window) + 2;
答案 2 :(得分:0)
除了@duskwuff指出的指针数学问题和@Barry澄清之外,还有另一个问题。您得到的答案取决于运行此代码的计算机体系结构。
在big-endian机器上你会得到一个答案,在小端机器上你会得到不同的答案。
哦,还有一件事。使用%s编写缓冲区非常危险。如果从文件读取的数据中没有零字节,它将在内存中漫游,直到找到它为止。