AutoLeaders控制组——c语言指针学习笔记

本文详细介绍了C语言中的指针概念,包括指针定义、基本操作(赋值、0地址)、函数与指针(修改变量、交换值、返回多个值)、const的使用、指针与数组、指针运算(+1、计算、比较)以及类型转换等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档



前言

`关于变量的地址

首先不同的变量占据着不同大小的空间,例如double便占据了8个字节,我们可以通过以下代码检查每个变量的大小,例如求int的大小 int a = 0; printf("%lu", sizeof(&a));可以得出int占据8个字节。而变量的字节,就存放在内存的某个位置,那个位置就是变量的地址。

如何获得变量的地址呢?

&为取地址符,我们可以通过int i; printf("%p", &i);来输出地址的数值,使用了%p,且自带16进制的0x标志。

数组的地址

前面所学的数组的地址,由测试可得,由数组的第一个元素的地址决定,也就是说,数组的第一个元素的地址就是数组的地址,而之后地址增加的步长又由数组元素的字长决定。

一、指针的定义

如果在程序中声明一个变量并使用地址作为该变量的值,那么这个变量就是指针变量。指针是一种特殊的变量,它存储了一个内存地址。这个内存地址指向另一个变量的位置。通过指针,我们可以直接访问和修改被指向的变量的值。
定义指针变量的一般形式为:
*类型名 指针变量名;如:

int *p;

类型名指定指针变量所指向变量的类型,必须是有效的数据类型,如:int,float,char等。指针变量名是指针变量的名称,必须是一个合法的标识符。*注意这里,我们并不是把*加给了int,而是加给了p,因此,p是一个int。

二、指针的基本介绍

1.赋值

在定义指针后,我们还需要将其初始化为某个有效的内存地址,否则它会指向一个未知的位置或者空地址。可以使用取地址运算符&来获取变量的地址,并将其赋值给指针变量,如下所示:

int num = 10;
int *p = #

上述代码中,&num获取变量num的地址,并将其赋值给指针变量p。现在,指针p指向了变量num的内存地址。通过指针,我们可以对被指向的变量进行操作。例如,可以使用*来获取指针所指向变量的值,如下所示:

int value = *p;

上述代码中,*p表示获取指针p所指向的变量的值,并将其赋值给变量value。

2.0地址

0地址通常用于表示空指针。空指针指向内存中的无效或未定义位置,它不指向任何有效的对象或函数。空指针用于初始化指针变量、检查指针是否为空,或者作为函数的返回值。

三、函数与指针

1.修改变量

我们可以用函数调用指针参数,得到地址后,可以用指针直接修改指向的变量。如下所示:

#include <stdio.h>

void f(int *p)
{
	printf("%p\n", p);
	*p=4;
}

int main()
{
	int i = 3;
	f(&i);
	printf("%d", i);
	return 0;
}

在这里我们用函数取得了i的地址,将i的值从3通过函数调用指针改成了4,修改了i的值。

2.交换两个变量的值

要完成两个变量的值的交换,我们可以传两个变量的地址进去,将两个变量的地址进行交换

#include <stdio.h>

// 函数原型
void swap(int *a, int *b);

int main() {
    int x = 5;
    int y = 10;

    printf("交换前:\n");
    printf("x = %d\n", x);
    printf("y = %d\n", y);

    // 调用交换函数
    swap(&x, &y);

    printf("交换后:\n");
    printf("x = %d\n", x);
    printf("y = %d\n", y);

    return 0;
}

// 定义交换函数
void swap(int *a, int *b) {
    int t = *a;
    *a = *b;
    *b = t;
}

运行之后,x和y的值便交换过来了,变成了x=10,y=5。在函数内部,我们首先将指针所指向的值存储到临时变量t中,然后交换两个变量的值。通过将x和y的地址传递给swap函数,我们实现了变量值的交换。

3.帮助函数返回多个值

1.场景一

当传入的参数实际上是需要保存带回结果的变量时

#include <stdio.h>

void f(int a, int b, int *x, int *y);

int main(void)
{
    int a = 1;
    int b = 2;
    int result1, result2;
    f(a, b, &result1, &result2);
    printf("%d %d", result1, result2);
    return 0;
}

void f(int a, int b, int *x, int *y)
{
    *x = a + b;
    *y = b - a;
}

我们把其中不止一个要接收的结果的变量的地址传进去,让函数帮我把这些变量填好,把值传回来。这些参数的作用就是把的结果带出来。

2.场景二

当函数返回运算的状态,结果通过指针返回时

int f(int a, int b, int *result) {
    *result = a + b;  // 将计算结果通过指针result返回
    return 0;  // 返回计算状态,通常0表示正常完成
}

int main() {
    int x = 5, y = 3, sum, status;

    s = f(x, y, &sum);  // 调用f函数,并将sum的地址传递给函数

    if (s == 0) {
        printf("The sum is: %d\n", sum);
    } else {
        printf("Error\n");
    }

    return 0;
}

我们可以让函数返回不属于有效范围内的值表示你所需要的意义(如-1或0等等),如上面返回计算状态,用0表示正常完成。

四、指针与const

1.当指针是const时

int *const q = &i;,q不能被改变,也就是指针指向某一个值的事实不能被改变了。这时候改变i的值是可以的,即*q=1;,是可以的;但是改变q,即q++;,是禁止的。

2.当所指是const时

const int *p = &i;,不能通过p去修改i,也就是说不能通过指针去修改变量,如*p=1;是禁止的。

3.const和*的位置关系

const在*前面代表所指不能被修改,反之则指针不能被修改。

五、指针与数组

数组可以说是特殊的指针,在函数参数表里的数组其实就是指针,即sizeof(a[]) == sizeof(int*),数组本身便表达地址,但是数组的单元表达的是变量,需要用&取地址。
[]运算符可以对数组和指针做。
*运算符可以取出指针指向的值和列表的第一个值。
数组变量是const的指针,不能被赋值。

六、指针运算

1.指针+1

指针加一并不是实际数值在加一,而是存储单元加一。也就是表示指针指向下一个变量

#include <stdio.h>

int main() 
{
	int ai[]={0,1,2,3,4,5,6,7,8,9,};
	int *q = ai;
	printf("%p\n", q);
	printf("%p\n", q+1);
	return 0;
}

运行结果是
000000000062FDF0
000000000062FDF4
可以看出因为int的sizeof(int)=4,所以地址加4。因此通过指针和数组的关系可以知道,*(p+1)等价于a[],如果指针不是指向一片连续分配的空间,那么这种运算没有意义。

2.指针计算

指针可以进行以下计算:
-加减整数

-递增递减(q++)

  • 取出q所指的那个数据来,顺便把q移到下一个位置
  • ++的优先级比*还要高
  • 常用于数组类的连续空间操作

-两个指针相减

  • 结果是地址的差除以sizeof大小

3.指针的比较

各种比较符都可以对指针做,去比较他们的地址,如<,>,<=,>=,==,!=。

七、指针的类型转换

-void*表示不知道指向什么东西的指针

  • 计算时和char*相同但不相通

-指针也可以转换类型

  • int *q=&i; void*p = (void*)q;这并没有改变q变量的类型,只是通过不同的眼光通过q看他所指的变量。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值