c - 数组算术 - 指针类型索引
问题描述
在我之前的问题中: Pointer dereference array index我问过关于 struct 被取消引用的问题。(我将从那里粘贴一段代码进行回顾):
#include <stdio.h>
#include <stdlib.h>
struct Test { char c; } foo;
int main (void) {
struct Test **ar;
ar=malloc(16);
*ar=malloc(0); //prerequisite for second case (without getting some address from OS, I cannot go 'through' *ar to (*ar+1).
//Does not matter allocation of zero bytes. (only to get some valid address)
*(ar+1) = &foo;
//(**(ar+1)).c='c'; //// first case - works
(*(*ar+1)).c='c'; //// second case - also works, with prerequisite
printf("%c\n", (*(*ar+1)).c); //prints 'c'
return 0;
}
我仍然理解+1
在第一种和第二种情况下添加指针之间的关系。好吧,我在第二个中做 - 添加sizeof(struct Test*)
到地址*ar
,这就像数组索引(数组*ar
的名称指针也是如此)。但在第一种情况下?做(**(ar+1))
什么?sizeof(struct Test**)
当ar
不是数组时,如何添加(什么?)某种指针类型?*(ar+1)
不属于我的解引用地址,但是 (*ar+1)sizeof(struct Test*)
确实属于我的指针 ( ) 的解引用地址(数组成员)。那么为什么第一个案例有效呢?(从链接中,我试图通过解析被索引的类型来给出我的理解[例如 - 在第一种情况下,“步骤/索引”sizeof(struct Test**)
由sizeof(struct Test*)
) - 看看链接。
解决方案
那么为什么第一个案例有效呢?
(**(ar+1)).c='c'
在我的特定系统上根本不起作用。
(**(ar+1))
对struct Test **
类型(*(*ar+1))
执行指针算术,并对类型执行指针算术struct Test*
。
这意味着在前一种情况下,算术是由 完成的sizeof(struct Test *) bytes
,在后一种情况下是sizeof(struct Test)
字节。
编译器可能会在您的结构中添加填充,以便它最终为 4 个字节等,无论您的系统上的指针大小如何。所以他们可能会幸运地到达同一个地址。指针大小通常为 2、4 或 8 字节,具体取决于是否使用 16、32 或 64 位地址总线。
去思考像这样晦涩难懂的代码是做什么的,意义不大。[]
通常应避免显式指针算术,使用运算符获得可读代码是更好的做法。
另请注意,malloc(0)
给出“要么返回空指针,要么行为就像大小是某个非零值,但返回的指针不应用于访问对象。” 如果你得到一个空指针然后尝试算术,你有未定义的行为,任何事情都可能发生。
推荐阅读
- sql-server - 在 HashByte md5 函数中使用 varchar(8000) 列值
- javascript - 延迟加载 amchart 不会在向下滚动时呈现
- json - 无法将 Json 数组解码为列表
并得到错误类型'_InternalLinkedHashMap ' 不是类型 'List 的子类型 ' - android - 对复合对象的 LiveData 的更改
- c++ - C ++更改for循环的条件评估
- hibernate - Hibernate:超类映射到子类中的@UniqueConstraint
- node.js - 为什么我的函数在命令行中运行两次但在 vscode 中没有
- java - 学校 Java 密室逃脱计划
- python - 高维高斯平均
- model-view-controller - 使用 dropzone 使用 mvc webapi 上传图像