理解不同C指针赋值之间的差异
我试图理解两种指针赋值之间的区别理解不同C指针赋值之间的差异,c,pointers,variable-assignment,C,Pointers,Variable Assignment,我试图理解两种指针赋值之间的区别 uint8_t pInputByte[byteCount]; uint8_t* pNextInputBytes = pInputByte; 在本例中,由于pInputByte[byteCount]是一个数组,第二行是否将该数组的地址写入pnputbyte?为了澄清只调用数组变量名而不返回其地址 我的另一个问题是,如果我们按照以下方式编写,操作会有什么不同 uint8_t pInputByte[byteCount]; uint8_t* pNextInputByt
uint8_t pInputByte[byteCount];
uint8_t* pNextInputBytes = pInputByte;
在本例中,由于pInputByte[byteCount]是一个数组,第二行是否将该数组的地址写入pnputbyte?为了澄清只调用数组变量名而不返回其地址
我的另一个问题是,如果我们按照以下方式编写,操作会有什么不同
uint8_t pInputByte[byteCount];
uint8_t* pNextInputBytes;
pNextInputBytes = &pInputByte;
表达式中使用的数组指示符(很少有例外)转换为指向其第一个元素的指针 来自C标准(6.3.2.1左值、数组和函数指示符) 3除非它是sizeof运算符或一元数的操作数& 运算符,或是用于初始化数组的字符串文字 类型为“”的数组“”的表达式转换为 类型为“指向类型的指针”且指向初始值的表达式 数组对象的元素,并且不是左值。如果数组对象 已注册存储类,行为未定义 因此,在本宣言中
uint8_t* pNextInputBytes = pInputByte;
用作初始值设定项的数组被转换为指向其第一个元素的指针,其类型为int*
。此值被分配给声明的指针
在这份声明中
pNextInputBytes = &pInputByte;
这里应用了一元运算符&用于数组类型的对象。因此表达式&pInputByte
的类型是uinmt8\u t(*)[byteCount]
。但在赋值的左侧有一个类型为uint8\u t*
的对象。没有从一种类型到另一种类型的隐式转换。因此编译器将发出一个错误
相反,你可以写作
uint8_t pInputByte[byteCount];
uint8_t (*pNextInputBytes )[byteCount];
pNextInputBytes = &pInputByte;
为了更清楚,请为数组类型引入typedef名称
typedef uint8_t T[byteCount];
然后可以按照以下方式声明数组和指向数组的指针
T pInputByte;
T *pNextInputBytes = &pInputByte;
现在,如果要用指针声明中的typedef名称T替换定义的类型,那么您将得到
uint8_t ( *pNextInputBytes )[byteCount] = &pInputByte;
要查看两个指针之间的差异,其中一个指针的类型为uint8\u t*
,另一个指针的类型为uint8\u t(*)[字节数]
,请编写以下演示程序
#include <stdio.h>
#include <stdint.h>
int main(void)
{
size_t byteCount = 10;
uint8_t pInputByte[byteCount];
uint8_t *pNextInputBytes1 = pInputByte;
uint8_t ( *pNextInputBytes2 )[byteCount] = &pInputByte;
printf( "sizeof( *pNextInputBytes1 ) = %zu\n", sizeof( *pNextInputBytes1 ) );
printf( "sizeof( *pNextInputBytes2 ) = %zu\n", sizeof( *pNextInputBytes2 ) );
return 0;
}
请注意,数组名称中使用的前缀p
会使代码的读取器感到困惑。1。
在这种情况下,由于
pInputByte[byteCount]
是一个数组,第二行是否将该数组的地址写入pnputbyte
不是数组的地址,而是数组第一个元素的地址。但基本上你是对的
为了澄清只调用数组变量名而不返回其地址
当数组未与索引元素[i]
一起使用时,该数组将衰减为指向第一个元素的指针,并返回该第一个元素的地址,除非用户在注释中提到,当它是索引元素时。引用自ISO/IEC 9899:2011(C11)
2. 我的另一个问题是,如果我们按照以下方式编写,操作会有什么不同: 第三条线是问题。您需要省略符号和运算符
&
,以便在没有任何警告的情况下正确编译它:
pNextInputBytes = pInputByte;
但是,如果你把打字错误混在一起,两种代码是等价的,是的
顺便说一下,当
p
代表“指针”(我只能推测)时,您不应该在pInputByte
前面加上p
uint8\u t pInputByte[byteCount];
uint8_t*pnputbytes=pInputByte代码>
uint8\u t pInputByte[byteCount];
uint8_t*pn字节;
pnputbytes=&pInputByte代码>
在本例中,我们获取数组的地址,但它指向整个数组。i、 e.如果pInputByte[5],则&pInputByte将指向5个元素的整个数组。因此,当您尝试像(pndeputbytes+1)那样递增时,地址实际上会跳5个地址。这在多维数组中很有用。假设双数组[5][4]是二维数组。这里,“array”是指向4 int数组的指针,但是“&array”是指向5行数组的指针,4 int数组“第二个应该得到一个编译器警告,因为
uint8\u t*
与uint8\u t(*)[]
非常不同。后者是指向数组的指针,而不是指向值的指针。此外,数组声明为您分配内存,裸指针需要分配或分配现有值(这是您在第一个示例中正确执行的操作)。“不与索引元素一起使用的数组[i]
衰减为指向第一个元素的指针。它返回第一个元素的地址。“--这是不正确的。该标准并没有说当一个数组被索引时没有数组衰减,而是说@exnihilo感谢您的提示。我已经把它编辑好了。
uint8_t pInputByte[byteCount];
uint8_t* pNextInputBytes = pInputByte;
uint8_t pInputByte[byteCount];
uint8_t* pNextInputBytes;
pNextInputBytes = &pInputByte;
pNextInputBytes = pInputByte;