c2-C语言--指针

2023-12-14 20:47:42

1.用一级指针遍历一维数组
结论
buf[i]<===>*(buf + i) <===> *(p + i)<===> p[i]
?

#include <stdio.h>

int main(){
    int buf[5] = {10,20 ,30 ,40,50};
//buf[0]  --- int
// buf  --&buf[0]  =----int *
    int *p =buf;//&buf[0]  --- &*(buf+0)
    printf("%p\n",p);
    printf("%p\n",&buf[0]);

    printf("%p\n",p+1);//0x7ffc2eb07e74  偏4

    printf("%p\n",(&buf+1));//0x7ffc2eb07e84 偏20


    return 0;

}

一维数组 &a[O]和&a之间的关系
?

a[O]为int类型,故&a[O]+1一次偏移一个int类型的大小,4 bytes。
a为int [5]类型,故&a +1一次偏移一个int [5]类型的大小,20 bytes。
?

内存模型

1.定义数组是在栈区申请空间,栈区的空间有读写的权限,可以修改数据。
?

2定义指针保存字符串,指针变量是在栈区申请的空间,字符串是在常量区分配。

指针保存的是内存中常量区空间的地址,常量区空间只有读权限,没有写权限,不能更改数据。
?

内核空间和用户空间
对于32位环境,理论上程序可以拥有4GB的虚拟地址空间,我们在C语言中使用到的变量、函数、字符串等都会对应内存中的一块区域。但是,在这4GB的地址空间中,要拿出一部分给操作系统内核使用,应用程序无法直接访问这一段内存,这一部分内存地址被称为内核空间(Kernel Space) 。
而Linux默认情况下会将高地址的1GB空间分配给内核。也就是说,应用程序只能使用剩下的3GB的地址空间,称为用户空间(User Space)。下图是Linux下32位环境的一种经典内存模型:

一级指针的特点

1.在32bit的操作系统中,所有的指针类型都是占4bytes .
2.大端模式:低地址存高位
小端模式:低地址存低位
3.不同类型的指针的,同对一块内存对齐的时候,读取的位它保存对象的大小的.
char *p;
short *q;

int*m;

*p ;//1

*q; //2

*m;//4
?

我的总结;

对齐的时候

移动的时候

应该是说指针偏移:

当不同类型的指针指向同一块内存,并且对齐要求得到满足时,读取指针所指向对象的大小是由指针的类型决定的。指针的类型决定了指针的步长,即指针在内存中移动的字节数。

例如,假设有一个`int`类型的指针`int* p`和一个`char`类型的指针`char* q`,它们都指向相同的内存块,且内存对齐要求得到满足。那么,使用`*p`来读取该内存块中所保存的对象时,将会按照`int`类型的大小来读取,即读取4个字节;而使用`*q`来读取同一块内存时,则按照`char`类型的大小来读取,即读取1个字节。

这是由于指针在进行间接访问时会根据自身的类型确定要读取的字节数。指针类型与所指向对象的大小息息相关,不同类型的指针具有不同的步长,因此读取的字节数目也会不同。

不同类型的指针,在移动的时候,每次移动的大小也是它保存对象的大小
?

指针数组

不要只看答案:? 思考 ,? 为什么 这么巧妙:?? 可以处理的额:刚好 是在哎 指针 数组里面,? 刚好 成员 移动一个 就是 对方的地址;

二级指针 来保存? 指针数组的首地址

二级指针可以用来保存指针数组的首地址。指针数组是一个数组,其中每个元素都是一个指针。而二级指针是一个指针,它可以指向其他指针的地址。

假设有一个指针数组`int* arr[]`,它存储了一组`int`类型的指针。如果我们要保存指针数组的首地址,可以使用一个二级指针进行存储。

示例代码如下所示:

```c++
int* arr[5]; // 假设有一个指针数组
int** ptr = arr; // 使用二级指针保存指针数组的首地址
```

在上述代码中,`arr`是一个指针数组,每个元素都是`int*`类型的指针。`ptr`是一个二级指针,它被赋值为`arr`,即保存了指针数组的首地址。

通过使用二级指针,我们可以在需要的时候获取到指针数组的首地址,并通过间接操作来访问或修改指针数组中的元素。

扩展小知识:

3 写出int 、bool、 float 、指针变量与 “零值”比较的if 语句

//int与零值比较
if ( n == 0 )
if ( n != 0 )

//bool与零值比较
if (flag) // 表示flag为真
if (!flag) // 表示flag为假

//float与零值比较
const float EPSINON = 0.00001;
if ((x >= - EPSINON) && (x <= EPSINON) //其中EPSINON是允许的误差(即精度)。

//指针变量与零值比较
if (p == NULL)
if (p != NULL)

再扩充:

4 结构体可以直接赋值吗

  • 声明时可以直接初始化,
  • 同一结构体的不同对象之间也可以直接赋值,但是当结构体中含有指针“成员”时一定要小心。
    注意:当有多个指针指向同一段内存时,某个指针释放这段内存可能会导致其他指针的非法操作。因此在释放前一定要确保其他指针不再使用这段内存空间

文章来源:https://blog.csdn.net/weixin_48434590/article/details/134914978
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。