c 和 指针(笔记)

1)数组指针,指向数组的指针,以一个n维数组为一个单位。
int matrix[3][5];
int (*p)[10];
p是一个指向10个整形元素的数组指针。当你把p和一个整数相加时,这个整数值首先根据10个整形值的长度进行调整,然后再执行加法。所以,我们可以使用这个指针一行一行地在matrix中移动。如下:
(p + i)  行变化,结果是一个数组指针
*(p +i)+j  定位到i行的第j列,结果是指针,指向整形。
*(*(p+i) +j ) 取i行j列的元素




2)作为函数参数的多维数组
首先看一下一维数组作为函数参数
int vector[10];
....
func1(vector);
参数为指向整形的指针,所以函数的原型可以为:
func1(int vec[]);
func1(int *vec);
但是多维数组却不是这样,请看
int matrix[3][5];
...
func2(matrix);//这里的matrix的类型是指向包含5个整形元素的数组的指针。
它的原型可以为:
void func2(int (*mat)[10]);
void func2( int ma[][10]);
对于多维数组,只有第一维数组的长度可以忽略,所以下面这样写是是不正确的:
void func2(int **mat);//代表指向整形指针的指针,它和指向整形数组的指针并不是一回事。


3)指针数组
其实弄懂指针主要知道它的优先级,常用的,从高优先级到低有:() [] ++ -- * 其中++,--操作数必须是左值。
下面请看:
int *api[10];
首先,定位到变量api,最高优先级[],说明api是一个数组,并有10个元素。
其次,看它的次优先级,*作为修饰,说明api是指针数组。存放的东西是 int *类型的 指针。


4)结构与联合
区分结构标签,类型名,结构变量
struct  tag{
member-list;
}variable-list;
tag:结构标签
variable-list:变量列表
typedef struct tag structType
此时structType就是该结构体的类型名 定义一个结构体变量可方便如下
structType var; 


有时候结构体里面会有结构体类型作为成员,这样就有谁先定义的问题。
解决这个问题就用不完整声明,如下:
struct A;//不完整声明
struct B{
struct A;
....
};


struct A{
    struct B;
};


结构的存储分配
系统禁止编译器在一个结构的起始位置跳过几个字节来满足边界对齐要求,因此所有结构的起始存储位置必须是结构中
边界要求最严格的数据类型所要求的位置。如下:
struct TAG{
char a;
int b;
char c;
};
如果int的长度为四,边界要求最严格的是int,所以为了满足边界对齐要求,a占据一个字节,跳过三个字节。
结构如:+--- ++++ +---  //+代表使用 -代表未使用
如果让边界要求最严格的成员首先出现,边界要求最弱的最后出现
struct TAG{
int b;
char a;              存储结构: ++++ ++--
char c;              只占用了八个内存空间,可以用sizeof测出来
};


sizeof 操作符能够得出一个结构提的整体长度,包括因边界对齐而跳过的那些字节。
宏offsetof(定义于stddf.h)可以计算某个结构指定成员开始的位置距离结构体开始存储的位置偏移几个字节。
offsetof( type,member ) //eg:上面的:b是4,a是5,c是6


5)内存中尽管地址相同但是类型不同就会被解释成不同的东西。eg 数组首地址和数组第一个元素的地址。
结构体首地址和结构体第一个成员的地址。


6)位段 可移植的程序避免使用位段,这里先跳过。位置:c和指针的p209


7)联合 联合的所有成员引用的是内存中的相同位置。
在不同的时刻把不同的东西存储于同一个位置
如果联合的各个成员具有不同的长度,那么联合的长度是最长成员的长度。




7)指针和数组不相同的一个例子。-->指针里的内容是一个地址,数组头本身是一个地址,内容是数组第一个元素。
下面的声明取自某个源文件
int a[10];
int *b = a;
但是在另一个源文件中,发现了如下代码
extern int *a;
extern int b[];
int x,y;
x = a[3];
y = b[3];
分析当两条语句执行时会发生什么。
::在第一个赋值中,编译器认为a是一个指针变量,所以它提取存储那里的指针值,并加上12(3和整形的长度相乘),然后对这个
结果执行间接访问操作。但a实际上是一个数组的起始地址,所以提取得到的是第一个整形元素。它与12相加,结果是整形,但却被
解释为一个地址,再进行间接访问。所以访问的结果是未知的。
::在第二个赋值语句中,编译器认为b是一个数组名,所以它把12加到b的存储地址,然后间接访问操作从那里获得值。事实上
b是一个指针变量,指针变量本身的存储地址是未知的,然后加上12自然得到的结果也是未知的。































  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值