C语言指针

指针的概念

  1. 编号:计算机所有的数据必须放在内存中,不同类型的数据占用的字节数不同,为了正确的访问这些数据,为每个字节都编上号码(每个字节的编号唯一),根据编号可以准确的找到某个字节。(int 占用4字节, char占用1字节
  2. 我们将内存中字节的编号成为地址或指针地址从0开始依次增加。
  3. 如何输出一个地址?
#include <stdio.h>
int main(void){
    int a = 100;
    char str[20] = "hello world";
    printf("%#X, %#X\n", &a, str);
    return 0;

}

关于代码的几点说明:(1).%#X : 表示以十六进制形式输出, 并附带前缀 0X (2)a是一个存放整数的变量,前需要加&来获得他的地址; str本身就表示字符串的首地址,不需要加&。
(在C中,我们有一个控制符%p, 专门用来以十六进制形式输出地址,但输出格式不统一,有的带0x前缀,有的不带);

赠送两张图片:

在这里插入图片描述
在这里插入图片描述

  1. 数据和代码都以二进制的形式存储在内存中,计算机无法从格式上区分某块内存到底存储的是数据还是代码。
    当程序被加载到内存后,操作系统会给不同的内存块指定不同的权限,拥有读取和执行权限的内存块就是代码,而拥有读取和写入权限(也可能只有读取权限)的内存块就是数据。

  2. CPU 只能通过地址来取得内存中的代码和数据(CPU访问时需要的是地址,而非变量名或函数名),程序在执行过程中会告知 CPU 要执行的代码以及要读写的数据的地址。

指针变量的定义和使用

  1. 数据在内存中的地址也称为指针,如果一个变量存储了一份数据的指针,就称其为指针变量。(指针变量的值就是某份数据的地址)

在这里插入图片描述

  1. 定义:
    int a = 100;
    int *p_a = &a;
    几点说明:(1)两行代码的含义:*表示p_a是一个指针变量, 将变量a的地址赋予它,此时p_a就指向了a。(2) &(取地址符)用来取a的地址 (3)因为a为int型,所以定义指向它的指针变量时,我们用的int定义。可以是float、char等等。

  2. 定义指针变量时,我们需要带*(表明这个变量为指针变量), 而给指针变量赋值时,不用加*

  3. 通过指针变量来取得数据:
    这里的* 称为指针运算符,用来取得某个地址上的数据。
    例如:

#include <stdio.h>
int main(){
    int a = 15;
    int *p = &a;
    printf("%d, %d\n", a, *p);  //两种方式都可以输出a的值
    return 0;
}

输出为:15,15

  1. 下面两段代码是等价的,但要注意,第二段中第二行代码不能加*
int *p = &a;
*p = 100;
int *p;
p = &a;
*p = 100;

在这里插入图片描述

  1. 指针不能进行乘除、取余等运算。
    可以进行加减、比较等。加减:的结果根数据类型的长度有关。(如int型的指针变量加一,表示指针变量加四)

数组、字符串指针

  1. 数组是一系列具有相同类型的数据的集合,整个数组占用的是一块内存。

  2. 定义数组时,数组名可以认为是一个指针,指向数组的第0个元素。(在C中,我们将第0个元素的地址称为数组的首地址)我们可以认为数组名就为数组首地址,但两者并不等价。

  3. 字符数组终究还是一个数组,关于数组指针的规则同样适用于指针数组。另一种表示字符串的方法:(直接适用一个指针指向字符串)

char *str = "http://c.biancheng.net";
char *str;
str = "http://c.biancheng.net";

str指向的是字符串的第0个字符,(我们通常将第0个字符的地址称为字符串的首地址)

在这里插入图片描述
两种方式最根本的区别是在内存中的存储区域不一样,字符数组存储在全局数据区或栈区(有读取和写入的权限); 第二种形式的字符串存储在常量区(只有读取权限,没写入权限)。

#include <stdio.h>
int main(){
    char *str = "Hello World!";
    str = "I love C!";  //正确
    str[3] = 'P';  //错误
    return 0;
}
/*
第4行代码是正确的,可以更改指针变量本身的指向;第5行代码是错误的,不能修改字符串中的字符。
*/

C指针变量作为函数参数

  1. 最为经典的就是交换两个变量的值:
#include <stdio.h>
void swap(int a, int b){
    int temp;  //临时变量
    temp = a;
    a = b;
    b = temp;
}
int main(){
    int a = 66, b = 99;
    swap(a, b);
    printf("a = %d, b = %d\n", a, b);
    return 0;
}
#include <stdio.h>
void swap(int *p1, int *p2){
    int temp;  //临时变量
    temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}
int main(){
    int a = 66, b = 99;
    swap(&a, &b);
    printf("a = %d, b = %d\n", a, b);
    return 0;
}

在上述代码段种,第二个swap函数才能真正意义上的交换两数的值。

  1. 用数组作函数参数:(下面的例子定义了一个函数max,用来查找数组中最大的元素。)
#include <stdio.h>
int max(int *intArr, int len){
    int i, maxValue = intArr[0];  //假设第0个元素是最大值
    for(i=1; i<len; i++){
        if(maxValue < intArr[i]){
            maxValue = intArr[i];
        }
    }
   
    return maxValue;
}
int main(){
    int nums[6], i;
    int len = sizeof(nums)/sizeof(int);
    //读取用户输入的数据并赋值给数组元素
    for(i=0; i<len; i++){
        scanf("%d", nums+i);
    }
    printf("Max value is %d!\n", max(nums, len));
    return 0;
}

注意:intArr 仅仅是一个数组指针,在函数内部无法通过指针获得数组长度,必须将数组长度作为函数参数传递到函数内部。
用数组做函数参数时,也可满足上述需求。

int max(int intArr[], int len){
    int i, maxValue = intArr[0];  //假设第0个元素是最大值
    for(i=1; i<len; i++){
        if(maxValue < intArr[i]){
            maxValue = intArr[i];
        }
    }
    return maxValue;
}

C语言指针作为函数返回值

C语言允许函数的返回值是一个指针(地址),我们将这样的函数称为指针函数。
下面示例中定义一个函数strlong,用来返回两个字符串中较长的一个。(自认为这个函数意义不大,但重在体会返回值和str指针变量)

#include <stdio.h>
#include <string.h>
char *strlong(char *str1, char *str2){
    if(strlen(str1) >= strlen(str2)){
        return str1;
    }else{
        return str2;
    }
}
int main(){
    char str1[30], str2[30], *str;
    gets(str1);
    gets(str2);
    str = strlong(str1, str2);
    printf("Longer string: %s\n", str);
    return 0;
}

用指针作为函数返回值时需要注意的一点是,函数运行结束后会销毁在它内部定义的所有局部数据,包括局部变量、局部数组和形式参数,函数返回的指针请尽量不要指向这些数据,C语言没有任何机制来保证这些数据会一直有效,它们在后续使用过程中可能会引发运行时错误。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Xuhx&

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值