黑马程序员——C语言基础篇---指针

本文详细介绍了C语言中的指针概念,包括指针的定义、赋值与取值、如何通过指针修改变量值,以及使用指针的注意事项。通过实例讲解了指针与数组、字符串的结合,以及返回指针的函数和指向函数的指针的用法。此外,文章还讨论了全局变量、静态变量和extern的作用,为读者提供了全面的指针操作和内存管理的理解。

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

------Java培训、Android培训、iOS培训、.Net培训 期待与您交流! -------

指针在C语言中的重要性不言而喻,本篇将通过一些实例来带你掌握指针的使用方法。

先来看看我们的第一段小代码,通过这个来了解一下指针的基本使用

#include <stdio.h>
int main()
{
    int a = 20;
    int *p;
    p = &a;
    printf("%d\n",*p);
    return 0;
}

1.指针的定义

    类名标识符  *指针变量名;

2.指针赋值和取值

在int *p;这句代码里,* 是指针的标志;指针里存储的是变量的地址,也就是p = &a;,这时,我们通常说指针p指向了变量a;当需要将值取出来时,使用*p,表示访问指针p所指向的存储空间(a的地址)并将其值取出。

上面的指针是先定义后赋值,当然在定义指针的同时赋值也是可以的,int *p =&a;。

3.利用指针修改变量的值

要想通过指针改变a的值,只需要 *p = 10;这句就可以,表示访问变量p所指向的变量(a),并将它的值进行修改。

4.使用指针的注意点

(1)p是指针名,存放的是地址,如果写 p= 1000;这样是错误的,可以取出和修改变量值的是 *p。

        int *p;    *p = 100;  这样写编译和链接时不会出错,但是运行时会报错,原因是:p并没有指向任何存储空间,是个空指针,怎么利用*p修改值呢?

(2)打印p的值

printf("%p-%d\n",p,*p);

结果

0x7fff5f09ec38-20

p的值是它存储的地址,可以利用%p来输出

(3)指针类型

指针的类型是不可以胡乱定义的,int型数据对应int型指针,如果乱用里面的值是不对的

(4)清空指针

p = 0;或p = NULL;


指针应用实例

1. 指针与数组

/*
 1>	设计一个函数:int arraySum(int *p, int n),求一维数组a前n个数的和。
 */

int arraySum(int *p, int n)
{
    int sum = 0;
    for (int i = 0; i < n; i++)
    {
        sum += p[i];
    }
    return sum;
}
int main()
{
    int a[5] = {1,2,3,4,5};
    int sum = arraySum(a,3);
    printf("%d\n",sum);
    return 0;
}
这个函数需要传入的实参是个int型的指针,也就是形参需要传入地址,而数组a就表示数组的地址,所以这里直接用arraySum(a,3),不用加 &符。
数组与指针的关系密切,在访问数组元素时,指针可以像数组一样来访问数组元素,上述代码中的p[i],这一句等价于 *(p+i)
下图是上述代码的一个简单内存示意图。


2. 指针与字符串

前篇日志中有讲到字符串,这里就讲一下两种不同的字符串定义方法及用法。
(1)利用数组定义字符串
char in[]="itclass";
这样定义的是字符串,结尾是有'\0'的,而非字符数组。
它的特点是:这是一个字符串变量,里面的字符可以修改
使用场合:如果需要频繁的修改字符串,可以使用这种方法来定义
(2)利用指针定义字符串
char *in="itclass";
它的特点是:这是一个字符串常量,里面的内容不可修改(这个我已经试验过了,编译和链接的时候不会出错,但是,运行时会报错),它在使用时存储在缓存里,不用重新开辟内存。
    char *in = "hello";
    char *h = "hello";
    printf("%p\n%p\n",in,h);
看上面的代码,结果是

0x10fb25f86

0x10fb25f86

这也就说明利用定义不同名字的指针指向一个同一个字符串常量,并没有开辟新的空间,他们指向的是同一存储空间。

适用场合:字符串的内容不需要修改,而且这个字符串经常使用,不用频繁的开辟和销毁内存空间,节省内存,性能上更好

我们来做一个小练习

*  编写一个int string_len(char *s),返回字符串s的字符长度

#include <stdio.h>
#include <string.h>
int string_len(char *s)
{
    return strlen(s);
}
int main()
{
    char *in = "这里是字符串小练习";
    int len = string_len(in);
    printf("%d\n",len);
    return 0;
}

结果是:27

注意了一个汉字占3个字节,'\0'不计算长度

3. 返回指针的函数

指针也是C语言中的一种数据类型,因此一个函数的返回值肯定可以是指针类型的
#include <stdio.h>
char *test()
{
    return "返回指针的函数练习";
}
int main()
{
    char *c = test();
    printf("%s\n",c);
    return 0;
}

4. 指向函数的指针

函数作为一段程序,在内存中也要占据部分存储空间,它也有一个起始地址,即函数的入口地址。函数有自己的地址,那就好办了,我们的指针变量就是用来存储地址的。因此,可以利用一个指针指向一个函数。其中,函数名就代表着函数的地址。
定义:函数的返回值类型 (*指针变量名)(形参1, 形参2, ...);
不多说了,还是通过一个练习来上手吧。
* 求两个数的和与差
#include <stdio.h>

typedef int (*myint)(int,int);

int sum(int a, int b)
{
    return a + b;
}
int minus(int a ,int b)
{
    return a - b;
}
int main()
{
    //定义指向函数的指针
    myint p;
    myint p1;
    p = sum;
    p1 = minus;
    printf("和是%d,差是%d\n",(*p)(10,5),(*p1)(10,5));
    return 0;
}
结果是:

和是15,差是5

typedef int (*myint)(int,int); 这一句是自定义一个可以传入两个参数的指针类型。
函数名表示函数的地址,p = sum;就表示p指向了函数sum,调用时要注意格式(*p)(10,5),(*p)表示访问p指向的函数,当然如果没有返回值的时候可以直接使用p(),但是有返回值的时候一定是(*指针名)(参数)
指向函数的指针在使用上和后面OC中的block的用法很类似,学好这个block就掌握了,关于指针差不多就这些了,最后要进行前面提到过,但是忘记细说的知识点的小小补充。
知识点补充:
(1)typedef

类型起别名,包括基本类型和结构体类型,枚类型等等

typedef  类型 别名
这个在上述代码中就有使用,使用很简单,就举一个例子吧
typedef struct Person
{
    int age;
} * PersonPoint;

是定一个指向结构体指的新类型,在使用时,直接利用PersonPoint p;就可以定义一个指向该结构体的指针p

(2)条件编译

条件编译,满足条件的才会编译,效率更高

#include <stdio.h>
#define A 10
int main()
{
#if (A == 10)
    printf("A是10\n");
#elif (A == 5)
    printf("A是5\n");
#else
    printf("A是其他值\n");
#endif
    return 0;
}
条件编译和宏定义结合使用,在实际开发中,编写头文件时非常有用

#ifndef LISI_H
#define LISI_H
int sum(int a,int b);
#endif
作用是:只编译一次,提高编译的效率,要注意定义的宏名通常以文件名命名
(3) externstatic

        对函数:
        extern的作用:
        完整的定义外部函数
        完整的声明外部函数
        但是默认情况下,所有的函数都是外部函数,所以可以省略
        整个项目中都不允许有同名的外部函数
        static的作用
        定义内部函数(只能在本文件调用,其他文件无法无法调用)
        声明内部函数
        不可省略

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        对变量:
        全局变量分两种:
        外部变量:定义的变量能被本文件和其他文件访问(默认情况下,所有的全局变量都是外部变量)
        内部变量:定义的变量只能被本文件访问
        全局变量不管定义多少个,都不会报错,所有的都是同一个
        不同文件的同名外部变量,都代表同一个变量
        extern(定义外部变量不加extern)的作用:

        声明外部变量     

        static的作用
        定义内部变量


        static 修饰的局部变量,

        生命周期变长,程序结束时销毁
        但是它的作用域并没有改变
        对性能优化有益,经常使用的变量可以如此定义
好了,C语言的基础篇到这里就结束了,下面要开始OC篇了




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值