【问题标题】:Char casting explained?字符转换解释?
【发布时间】:2014-07-01 14:04:36
【问题描述】:

我正在编写一些代码,无法理解这个演员阵容。据我了解,我们正在尝试将指向 unsigned char 数组的指针转换为其他内容。我不太清楚(*c_grid) 是什么意思,(*)[dim_x] 是干什么用的。

unsigned char (*c_grid)[dim_x] = (unsigned char (*)[dim_x])grid_in;

P.S.:回家之后我可以以c_grid[i][j] 的身份访问c_grid 元素?

【问题讨论】:

  • c_grid 是指向unsigned chars 的数组(大小为dim_x)的指针。这也是右侧的类型转换所做的

标签: c++ c pointers casting


【解决方案1】:

c_grid 是指向dim_x 类型为unsigned char 的元素数组的指针。 (unsigned char (*)[dim_x])grid_in 转换为与 c_grid 相同的类型,即指向 dim_x 类型为 unsigned char 的元素的数组的指针。

c_grid 是指向数组的指针。那是什么意思?

当你声明时

int a[10];
int *p = a; 

然后您可以使用p[i] 访问数组a 的其余元素。同样的规则适用于二维数组。
如果grid_in 是一个二维数组并且c_grid 是指向其第一个元素的指针(grid_in 的每个元素都是长度为dim_x 的一维数组),那么当您将c_grid 增加1 时,它将指向二维数组grid_in 的下一行。所以,你可以说c_grid[0] 是指向第一行的指针,c_grid[i] 是指向ith 行的指针。

要访问ithc_grid指向的jth元素,你只需要c_grid[i][j]

【讨论】:

  • 这里的答案并不能真正教你指针在 C 中是如何工作的。你真的应该读一本书或查看真正解释它们如何工作的在线资源。这个网站真的是用来回答具体问题的。
  • @hacks,我似乎不明白如何计算 c_grid[i][j],因为在我的理解中 (unsigned char (*)[dim_x])
  • @DenysS.;更新了答案。
  • @DenysS.;你还有问题吗?
  • @DenysS.;顺便说一句,您可以see this 直观地解释指向数组的指针是什么?
【解决方案2】:

在 C 声明符中,* 运算符关联从右到左,类似于一元运算符,而数组声明符将左到右关联到更高的优先级。也就是说,char ***a[1][1],如果我们加上全括号,就是:char (*(*(*((a[1])[1]))))。后缀[] 类型构造运算符首先应用,从左到右,然后是一元* 运算符从右到左。这意味着a 是一个“指向指向 char 的指针的指针数组”。

括号可用于覆盖关联和优先级。例如:char (***a)[1][1]。现在 a 是“指向指向 char 数组的指针的指针”。 * 运算符从右到左应用,然后是后缀运算符。

也可以使用其他括号,例如 char **(*a)[1][1],其中 a 现在是指向数组的指针,或 char **(*a[1])[1],其中 a 是指针数组。

语法决定了类型的“形状”。

强制转换表达式类似于声明,只是声明的名称被简单地删除。例如,要将char **(*a[1])[1] 转换为适合强制类型转换的类型表达式,我们取出achar **(*[1])[1]

声明符语法的设计方式是,当我们从声明符中取出声明的标识符时,如果我们将其放回去,该名称的去向仍然很明显。它只能放在一个地方。

鉴于char **(*[1])[1] 已从其中删除a,我们可以在哪里重新插入a

char *a*(*[1])[1]   // not here
char **a(*[1])[1]   // not here
char **(a*[1])[1]   // not here
char **(*a[1])[1]   // aha! this rings a bell
char **(*[a 1])[1]  // certainly not here
char **(*[1 a])[1]  // nope
char **(*[1]a)[1]   // wrong
char **(*[1])a[1]   // wrong
char **(*[1])[a 1]  // wrong
char **(*[1])[1 a]  // wrong
char **(*[1])[1]a   // wrong

一旦你习惯了语法,就会很明显。标识符必须紧跟声明说明符(在本例中为 char)或紧跟开括号 (* 运算符。右边只能跟[或者什么都没有。

所以第一个替换立即看起来错误,因为a 后面跟着*,第二个替换看起来错误,因为a 后面跟着(

【讨论】:

  • 感谢您提供如此广泛的答案,它澄清了一些方面,但我仍然不明白为什么在转换 grid_in 之后我们可以以二维数组方式访问 c_grid 元素,即使我们从未声明它成为这样。
  • @DenysS 这是可能的,因为底层内存没有任何C类型的概念;这只是我们强加给它的一种观点。在 C 语言中,我们可以颠覆类型系统,以存储以一种方式声明的对象,并像使用另一种类型一样使用它。然而,这种“类型双关”的大多数实例并未由 C 语言标准定义(“未定义行为”)。
  • @DenysS 请注意,当我们使用malloc 动态分配对象时,我们通常会将指针转换为void * 以外的类型,并有效地为该内存分配一个类型。因此,动态分配需要能够将任意内存视为具有某种类型。
猜你喜欢
  • 2012-07-10
  • 2019-05-18
  • 2010-12-27
  • 2012-09-28
  • 2020-10-09
  • 2013-09-27
  • 1970-01-01
  • 2021-01-02
  • 2021-01-06
相关资源
最近更新 更多