char errorString[20];
//See if it appears to be a 4-char-code
*(UInt32 *) (errorString + 1) = CFSwapInt32HostToBig(error);
if (isprint(errorString[1]) && isprint(errorString[2]) && isprint(errorString[3]) && isprint(errorString[4]))
{
errorString[0] = errorString[5] = '\'';
errorString[6] = '\0';
}
函数的这一部分采用字符串(error
)并检查它是否包含4-char代码。
发生了什么:*(UInt32 *) (errorString + 1)
为什么在parens内外都有指针,如何将值赋给errorString + 1
?
答案 0 :(得分:2)
errorString
可以被视为指针,因此,可以对其进行数学运算,例如,添加整数。 errorString + 1
也是一个指针。它是指向一个errorString
点旁边的位置的指针。
(UInt32 *)something
将something
强制转换为指定类型的指针,因此(UInt32 *)(errorString + 1)
现在是指向UInt32
类型数据的指针。
*
是一个解除引用运算符,因此将它应用于指针会获得指针所指向的内容(例如,如果pointer
指向一个整数,*pointer
将是一个整数)。
总而言之,此构造将尝试从指定位置提取UInt32
类型的数据。
答案 1 :(得分:1)
在表达式
中*(UInt32 *) (errorString + 1)
第一个*
是取消引用,然后第二个*
表示指针。如果我们从右到左阅读,我们有
(errorString + 1) // get a pointer to errorString + 1 of the type char*
(UInt32 *) // cast that pointer to a UInt32 *
* // dereference that pointer
答案 2 :(得分:0)
括号内的星号是指针转换的一部分 括号外的星号如果是参考
所以*(UInt32 *) (errorString + 1)
使得errorString + 1和UInt32指针
并<video playsinline> </video>
拒绝它,并将内容作为UInt32。
答案 3 :(得分:0)
让我们从头开始。
表达式 errorString
的类型为char [20]
;除非它是sizeof
或一元&
运算符的操作数,否则其类型将从char [20]
转换为char *
到&errorString[0]
,它的值将是数组的第一个元素的地址(errorString + 1
)。
表达式&errorString[1]
生成数组的第二个元素的地址(相当于char *
),其类型为(UInt32 *) (errorString + 1)
。
errorString + 1
是一个强制转换表达式,它告诉编译器将UInt32
的结果视为指向char
的指针,而不是指向*(UInt32 *) (errorString + 1)
的指针。 {1}}。
(UInt32 *) (errorString + 1)
取消引用 CFSwapInt32HostToBig()
的结果,以便将errorString + 1
的结果分配给 32位对象从地址 +---+
errorString: | | errorString[0]
+---+
| | errorString[1] <-------------+
+---+ |
| | errorString[2] |
+---+ +-- Assign result of CFSwapInt32HostToBig()
| | errorString[3] | to these four bytes
+---+ |
| | errorString[4] <-------------+
+---+
| | errorString[5]
+---+
...
+---+
| | errorString[19]
+---+
开始。
蹩脚的视觉辅助:
from itertools import groupby
r = csv.reader(open("fan.csv", "rb"))
a = [[k] + [x[1] for x in g] for k, g in groupby(r, key=lambda row: row[0])]