谁对谁的名字总是记不住
1
2
|
int* const b; /* 指针常量 */
const int* a; /* 常量指针 */
|
观察一下形式,发现*号在左,const在右,从左往右读,指针常量。
反之const在左,*在右,从左往右读,常量指针。
之前一直都觉得:数组名就是数组开始地址的指针,包括我面试也是这么回答,现在学习到这是错误的或者说不严谨的。
在C/C++中。数组就是数组,指针就是指针,这是两个不同的类型。
数组就是数组,指针就是指针
在llvm中间代码中,也是会分为数组类型和指针类型的:
1
2
3
4
5
6
7
8
9
10
11
|
/// ElementType:数组元素的类型
/// NumElements:数组元素的个数
/// static ArrayType *llvm::ArrayType::get(Type *ElementType, uint64_t NumElements);
/// 例如:int [10];
llvm::ArrayType *arrType1D = llvm::ArrayType::get(Type::getInt32Ty(TheContext), 10);
/// ElementType: 指针指向的元素类型
/// AddressSpace:地址空间,0表示默认地址空间
/// static PointerType *llvm::PointerType::get(Type *ElementType, unsigned AddressSpace);
/// 例如:int *
llvm::Type *pointer = llvm::PointerType::get(Type::getInt32Ty(TheContext), 0);
|
1
2
3
|
int a[3] = {1, 2, 3};
int b[3];
b = a; /* 表达式必须是可以修改的左值 */
|
在第三条赋值语句中,左侧的b是一个数组类型,不是一个左值,C/C++规定的左值只有标量和结构体,而数组名不可以作为左值放在赋值表达式左侧。
同样既然不是左值,那就无法对其进行运算:
1
2
|
int a[3] = {1, 2, 3};
a++; /* "++"需要左值 */
|
在表达式中,数组名被临时的当作指针常量,那么
肯定是不允许的,因为指针常量不允许改变自己的指向。同理:
也是不被允许的。
结构体数组的好处是:
- 可以直接进行赋值
- 可以作为表达式返回
- 可以作为参数传递
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
/* 定义报文结构:128字节的报文 */
typedef struct Packt {
char packet[128]; /* 结构体数组 */
}Packet;
/* 出参: p_ptr */
void GetPacket1(Packet* p_ptr) {
Packet res = { "123" };
*p_ptr = res;
}
/* 返回值类型:Packet */
Packet GetPacket2() {
Packet res = { "456" };
return res;
}
int main() {
Packet a = { "this is a packet" };
/* 直接赋值 */
Packet b = a;
cout << b.packet << endl; /* this is a packet */
/* 使用参数赋值 */
GetPacket1(&b);
cout << b.packet << endl; /* 123 */
/* 使用返回值赋值 */
b = GetPacket2();
cout << b.packet << endl; /* 456 */
return 0;
}
|
但是这并没有直接操作结构体中的数组,操作的是结构体实例,而实例是一个左值。
直接操作里面的数组依然是不被允许的:
1
2
3
4
5
6
7
8
9
|
int main() {
Packet a = { "this is a packet" };
/* 直接操作结构体里的数组 */
Packet b;
b.packet = a.packet; /* 表达式必须是可修改的左值 */
b.packet = { 1, 2, 3 }; /* 表达式必须是可修改的左值 */
return 0;
}
|
只要声明结构体的时候使用了初始化,即使没有为所有成员都指定初始化,结构体的所有成员都会被初始化。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
typedef struct MyStruct {
int len;
int pkt[10];
short a;
long long int b;
}MyStruct;
int main() {
MyStruct a; /* 无初始化,所有成员都不会被初始化 */
PrintStruct(&a);
MyStruct b = { 0 }; /* 部分,但所有成员都会被初始化 */
PrintStruct(&b);
MyStruct c = { 1,{1,2,3} }; /* 同上 */
PrintStruct(&c);
return 0;
}
|

声明在global或者用static的结构体,属于BSS段,就像其他变量一样,自动初始化为0,除非手动初始化。