您的位置:首页 > 房产 > 家装 > 网络规划与设计开题报告_企业网站的建立之前必须首先确定_磁力云搜索引擎入口_陕西网络推广介绍

网络规划与设计开题报告_企业网站的建立之前必须首先确定_磁力云搜索引擎入口_陕西网络推广介绍

2025/3/13 17:17:19 来源:https://blog.csdn.net/qq_34142812/article/details/143215149  浏览:    关键词:网络规划与设计开题报告_企业网站的建立之前必须首先确定_磁力云搜索引擎入口_陕西网络推广介绍
网络规划与设计开题报告_企业网站的建立之前必须首先确定_磁力云搜索引擎入口_陕西网络推广介绍

C语言中的指针

文章目录

  • C语言中的指针
    • 一、变量和地址
    • 二、指针变量
    • 三、函数地址
    • 四、在函数中交换变量内容
    • 五、const 修饰的指针
    • 1.指针常量
    • 2.常量指针
    • 3.指向常量的常指针


一、变量和地址

1.C语言中,每次新定义一个变量,都会在相应的存储空间中为该变量分配一块空间,用于存储对应的数据。

例如,定义 int a = 10; 便会在栈空间中划出一个物理空间用于存储整型数字10。

下面以STM32 Cortex3的环境为例,新建一个变量a的汇编代码如下:

MOVS  r0,#0x0A      ;0x0A赋值给R0寄存器中。
STR   r0,[sp,#0x08] ; 将R0寄存器中的数据存储到地址为sp+0x14的存储空间中,sp为栈底地址。

因此 整型变量a对应的是 0x200010BC地址存储空间内存放的整数10

可以使用 “&” 取地址符,来获取变量a对应的地址,此处&a的值为:0x200010BC。
在这里插入图片描述

图1 变量和地址

上图中的打印内容:

[main] &a = 200010bc, p = 0x200010bc, &p = 0x200010b0
[main] &b = 200010b8, &c = 200010b4

在该例子中,SP寄存器保存的值为 0x200010A8。

总结:每定义一个变量,都会在内存中开辟一块存储空间用于存放变量的内容,这块存储空间有一个唯一的访问地址

二、指针变量

指针变量:是指保存的地址的变量,该变量所对应的存储空间保存的是地址。

指针和指针变量是一个意思。

例如声明并定义一个指向整型的指针变量:

int* p = NULL;
p = &a;

指针变量和普通的变量一样,只是指针变量保存的是地址;我们定义一个指针变量,该指针变量也会在内存中开辟一块存储空间用于保存变量的内容。结合图1中所展示的那样,指针变量p保存的是整型变量a的存储地址,而变量p的地址是0x200010B0。同整型变量a那样,使用 “&p” 可以得到p的地址为:0x200010B0。

在图1中,我们定义了整型变量a,赋值a = 10,于是我们便可以使用a代替整型数字10。对于指针变量也是如此,既然我们已经给指针变量p赋值了,明确此处使用变量p表示a的地址,也就是0x200010bc。可以发现,指针(变量)所表示的就是地址,也可以通常所说的指针就是地址

当我们知道一个变量的地址之后,便可以获取到这个地址中所表示的内容。

在上面的例子中,我们定义了指向整型的指针p,p为a的地址,可以使用 “ * ” 解引用符号进行解引用操作,可以理解为对这个指针进行解码,解码得到该地址里保存的内容。

printf("*p = %d \r\n",*p);   // 可以得到*p = 10。

指针可以指向各种数据类型,包括结构体,也可以是函数,指针变量等。其中,指向指针变量的指针被称为二维指针,因为该指针变量中保存的是另一个指针变量的地址。

int** q = &p;    // 定义指针变量q二维指针,q保存的内容是p的地址,而p是指向int类型的指针变量。

以下面该程序段为例:

	int a = 19;int *p = NULL;p = &a;int** q = NULL;q = &p;printf("&a = %p, a = 0x%x\r\n", &a,a);printf("&p = %p, p = 0x%x,  *p = 0x%x \r\n", &p,p,*p);printf("&q = %p, q = 0x%x,  *q = 0x%x \r\n", &q,q,*q); 

打印结果如下:

&a = 200010b8, a = 0x13
&p = 200010b4, p = 0x200010b8,  *p = 0x13 
&q = 200010b0, q = 0x200010b4,  *q = 0x200010b8 

其中,q的值为指针变量p的地址,而p的值则是变量a的地址。

三、函数地址

函数的地址:函数地址是指函数代码在内存中的位置,可以通过函数名直接获取。

在编译之后,函数代码会保存在内存中的特定地址上,当需要使用到该函数时,会跳转到该函数的位置执行,函数也是存在地址的。在C/C++中,函数名就表示函数的地址。同样的,也可以定义一个变量来保存函数地址,该变量被称为函数指针。

例如声明一个函数指针pFunc,该函数指针指向型如 void a(int a, int b) 类型的函数。

void (*pFunc)(int, int);   		// 不使用别名
typedef void(*FUNC)(int,int);	// 使用typedef时

下面以图2为例,swap_para函数的函数名就为函数开始地址。
在这里插入图片描述

图2 函数地址

四、在函数中交换变量内容

通过值传递的函数:

void swap(int a, int b)
{int c = 0; c = b;b = a;a = c;
}

我们知道,使用上面的函数来交换两个参数的值是不能实现的。

因为在调用swap(c,d)函数时,是将实际参数c和d的值传递给形式参数a和b,在函数swap中新定义两个变量a和b用于保存实参的值,并进行a和b值的交换。swap函数结束之后,栈空间会被回收,形式参数a和b所在的空间便会被回收。因此,实际的参数,c和d的值也不会发生给改变。如果,要改变c和d的值,只能通过改变c和d地址内容来操作,也就是采用指针的方式。

下面是采用指针方式更改后的函数:

void swap(int* addr_a, int* addr_b) 
{int c = 0;c = *addr_a;*addr_a = *addr_b;*addr_b = c;
}

在调用的时候,需要传入要交换的变量c和d的地址,如:swap(&c, &d); 在这个函数中,由于交换了变量c和变量d中地址的内容,因而,这种指针方式便能成功更改参数的内容。

五、const 修饰的指针

使用const修饰变量时,用于保护变量的值不能被修改。

const int a = 10;  // 必须初始化,之后a的值不能被更改
// const int a;  // 错误!!!,a没有初始化。
const int arr[5] = {1,2,3,4,5};

修饰指针时,需要区分是限定指针本身为 const 还是限定指针指向的值为 const。

可以使用助记的方法:把一个声明从右向左读

1.指针常量

特点: 指向常量的指针,指向的值不能被改变,指针p本身的值可以改变。

const char *p;  ( * 读成 pointer to ) 
/* p is a pointer to const char  */
此处表明:p指向的值不能被改变,但是p的值可以更改。换句话说,不能使用*p来改变p中的内容。
因为C++里面没有const*的运算符,所以const只能属于前面的类型。C++标准规定,const关键字放在类型或变量名之前等价的,
上面的等价与:
char const *p;

2.常量指针

特点:指针p本身的值不能更改,但指向的值可以改变。 p必须指向同一个地址,但是该地址里面的值可以改变。

char * const p;    
/* p is a const pointer to char */
此时表明:p是一个常量指针,p的值是固定的,不能被更改;但是可以使用*p来修改p中的值。

3.指向常量的常指针

特点:指针p本身的值不能更改,且所指向的值也不能更改。

const char * const p;  
/* p is a const pointer to const char */

简而言之,const 放在 * 左侧任意位置,限定了指针指向的数据不能更改;const 放在 * 右侧,限定了指针本身不能更改

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com