[C语言]学习笔记一:指针

**[C语言]**学习笔记一:指针

“&”:取地址操作符
printf中的“*”:取值操作符

一、指针和指针变量:

通常我们所说的指针,就是地址的意思。C 语言中有专门的指针变量用于存放指针,跟普通变量不同,指针变量存储的是一个地址。

指针相当于门牌,指针变量相当于门牌号。

指针变量也有类型,它的类型就是存放的地址指向的数据类型。

EXAMPLE1

#include <stdio.h>

int main()
{
         char a = 'f';
         int f = 123;
         
         char *pa = &a;//&为取地址符,把a的地址赋给*pa
         int *pb = &f;
         printf("a = %c\n",*pa);//取pa指针变量中的存储的a地址对应的值’f';通过*解引用,即*pa和变量a代表同一个值
         printf("f = %d\n",*pb);
         
         *pa = 'C';
         *pa += 1;
         
         printf("now, a = %c\n", *pa);//*为取值操作符
         printf("now, f = %d\n", *pb);
         
         printf("sizeof pa = %d\n", sizeof(pa));//读取pa的长度,64位计算机中一个指针存放8位地址
         printf("sizeof pb = %d\n", sizeof(pb));
         
         return 0;
}


## RESULT
		a = f
		f = 123
		now, a = D
		now, f = 123
		sizeof pa = 8
		sizeof pb = 8

!!

1、指针变量只能存放地址吗?
答:是的

2、取址运算符(&)作用于一个常数,然后试图打印该常数在内存中的地址,这样做可取吗?

include <stdio.h>

int main()
{
        printf("%p\n", &110);

        return 0;
}

答:这样做不可取!事实上这涉及到左值和右值的问题
把程序编译一下,报错信息已经提示你了:test.c:5: error: lvalue required as unary ‘&’ operand(c]
意思是:取址操作符(&)的作用对象应该是一个左值,而常数是右值。

LVALUE & RVALUE

lvalue : locator value(特定位置的值),用于识别或定位一个存储位置的标识符。(注意:左值同时还必须是可改变的)。
rvalue : value of an expression(表达式的值),还可以理解为 readable value,即任何可读取的值都被认为是右值(非左值)。

#include <stdio.h>

int main()
{
        int a = 5;

        ++(a++);

        return 0;
}
(a++) 是先将变量 a 的值(5)做为整个表达式的值返回,再将 a 自增 1(类似于 a = a + 1)。

所以这里 ++(a++); 相当于 ++(5), a = a + 1;

那当然要报错啦,5 是一个常量,当然不能给你 5 = 5 + 1~

EXAMPLE2

#include <stdio.h>

int main(void)
{
        int a, b, c, t;
        int *pa, *pb, *pc;
        
        printf("请输入三个数:");
        scanf("%d%d%d", &a, &b, &c);
        
        pa = &a;//把a的地址放入pa中
        pb = &b;
        pc = &c;
        
        if (a > b)
        {
                t = *pa;//把指针变量pa指向的地址给t;
                *pa = *pb;
                *pb = t;
        }
        
        if (a > c)
        {
                t = *pa;
                *pa = *pc;
                *pc = t;
        }
        
        if (b > c)
        {
                t = *pb;
                *pb = *pc;
                *pc = t;
        }
        
        printf("%d <= %d <= %d\n", *pa, *pb, *pc);//把存放在指针变量pa中的地址进行取值并输出;
        printf("%d <= %d <= %d\n", a, b, c);
        
        return 0;
}

这个其实很简单
就是1,2,3三个位置和a,b,c三个数比较,先ab比,大的放位置2,小的放位置1;ac比,大的放位置3,小的放位置1,最后bc比。

二、指针和数组

1、*p是取值,*p=&a表示将该地址表示的数值赋予p,即a=p,&a访问的是a的地址,也就是p

2、数组名就是数组第一个元素的地址,也是数组的首地址。

3、指向数组的指针

int a[] = {1, 2, 3, 4, 5};
int *p = a; // 语句1
int *p = &a[0]; // 语句2

因为数组名即数组第一个元素的地址,所以语句 1 和语句 2 是等价的,都是将数组 a 的首地址存放到指针变量 p 中。

4、指针的运算

当指针指向数组元素的时候,我们可以对指针变量进行加减运算,这样做的意义相当于指向距离指针所在位置向前或向后第 n 个元素。

比如 p+1 表示指向 p 指针指向的元素的下一个元素;p-1 则表示指向上一个元素。

需要郑重强调的是:p+1 并不是简单地将地址加 1(int是地址+4等等…),而是指向数组的下一个元素。

char a[] = "FishC";
char *p = a;
printf("*p = %c, *(p+1) = %c“,*p,*(p+1))

*p = F, *(p+1) = i

访问数组元素的方法:
①下标法访问
②指针法访问(先不定义指针也可以访问)
*p = a
*(p+i)=a[i]

PS:

获取字符串长度用xx=strlen();

0、str[3] 用指针法如何表示?

*(str + 3)

1、假设整型指针变量 p 存放的地址值是 0x11008888,那么请问 p + 1,p + 2,p + 4 和 p + 8 的地址分别是?

ans:

p + 1 == 0x11008888 + 4 == 0x1100888C
p + 2 == 0x11008888 + 8 == 0x11008890
p + 4 == 0x11008888 + 16 == 0x11008898
p + 8 == 0x11008888 + 32 == 0x110088A8

2、

……
while (n-- && (*target2++ = *target1++) != '\0')
                ;
…… 

3、请问 str[20] 是否可以写成 20[str]?
答:可以。
因为在访问数组的元素的时候,数组名被解释为数组第一个元素的地址。
所以 str[20] == *(str + 20) == *(20 + str) == [20]str

4、使用 fgets 函数(使用文档 -> 传送门)读取用户输入的字符串(英文),并用指针法来计算字符串的字符个数。

#include<stdio.h>
#define MAX 1024
int main()
{
		char str[MAX];
		char *target = str;//指针法访问数组元素 
		int length = 0;
		printf("请输入一个字符串:");
		fgets(str,MAX,stdin);
		
		while (*target++ != '\0')//指针指向数组名,即数组第一个元素,然后每次循环都指向下一位 
		{
			length++; 
		}
		
		printf("您总共输入了%d个字符",length-1);
		return 0;
}

指针数组和数组指针

1、区别:数组名只是一个地址,而指针是一个左值
lvalue : locator value(特定位置的值),用于识别或定位一个存储位置的标识符。(注意:左值同时还必须是可改变的)。
而数组名只是一个地址常量,它不可以被修改,所以数组名不是左值。
所以不能把数组名作为循环判断条件。

2、指针数组

int *p1[5];

指针数组是一个数组,每个数组元素存放一个指针变量。
在这里插入图片描述
!! 重点

#include <stdio.h>

int main()
{
        char *p1[5] = {
                "让编程改变世界 -- 鱼C工作室",
                "Just do it -- NIKE",
                "一切皆有可能 -- 李宁",
                "永不止步 -- 安踏",
                "One more thing... -- 苹果"
        };
        int i;

        for (i = 0; i < 5; i++)
        {
                printf("%s\n", p1[i]);\\不加*是因为要打印的是一个数组元素,加*取值运算符是取数组元素中地址所存放的值(字符)。
        }

        return 0;
}

3、指针数组

int*p1)[5];

在这里插入图片描述
指针数组是一个指针,它指向的是一个数组。

#include <stdio.h>

int main()
{
        int temp[5] = {1, 2, 3, 4, 5};
        int (*p2)[5] = &temp;**//必须加&,表示指向整个数组的指针,即取整个数组的地址。不加&的话表示只取数组的第一个元素的地址**
        int i;

        for (i = 0; i < 5; i++)
        {
                printf("%d\n", *(*p2 + i));//数组本身是一个指针,指向的是数组的第一个元素。因此指向数组的指针需要取两次值才能得到数组的第一个元素值。
        }

        return 0;
}

[fishc@localhost s1e23]$ gcc test4.c && ./a.out
1
2
3
4
5
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值