C语言—指针基础

如果想更详细的了解指针的知识点可以观看我的另外一篇博客。

指针高级:https://blog.csdn.net/qq_46485161/article/details/115037692

地址和指针的概念

为了说清楚什么是指针,必须弄清楚数据在内存中是如何存储的,又是如何读取的。

内存区的每一个字节有一个编号,这就是“地址” 。如果在程序中定义了一个变量,在对程序进行编译时,系统就会给这个变量分配内存单元。

1、按变量地址存取变量值的方式称为“直接访问”方式 ,例如:

printf(%d″,i);
scanf(%d″,&i);
k=i+j;

2、另一种存取变量值的方式称为“间接访问”的方式。即,将变量i的地址存放在另一个变量中。

在C语言中,指针变量是一种特殊的变量,它是存放地址的。假设我们定义了一个指针变量i_pointer用来存放整型变量的地址,它被分配地址为(3010)、(3011)的两个字节。可以通过语句:i_pointer =&i;
将i的地址(2000)存放到i_pointer中。这时, i_pointer的值就是(2000) ,即变量i所占用单元的起始地址。要存取变量i的值,可以采用间接方式:先找到存放“i的地址”的变量i_pointer ,从中取出i的地址(2000),然后到2000 、 2001字节取出i的值

指针和指针变量

指针和指针变量的定义
一个变量的地址称为该变量的“指针”。
例如,地址2000是变量i的指针。
如果有一个变量专门用来存放另一变量的地址(即指针),则它称为“指针变量”。
上述的i_pointer就是一个指针变量。

指针变量的值(即指针变量中存放的值)是地址(即指针)。
请区分“指针”和“指针变量”这两个概念。

变量的指针和指向变量的指针变量
1、定义一个指针变量
定义指针变量的一般形式为
基类型 *指针变量名;
int *ptr;

说明
指针变量的类型:指明了该指针指向的内存空间所存储的数据类型。
定义中的“”表示所定义的变量是指针变量。变量名是ptr,而非ptr。

注意:指针变量中只能存放地址(指针),不要将一个整数(或任何其他非地址类型的数据)赋给一个指针变量

给指针赋值

1、通过 & 运算符为指针赋值,例如:
ptr_var = &var;
2、通过另一个指向相同类型数据项的指针变量对指针进行赋值,例如:
ptr_var2 = ptr_var;
3、给指针变量赋值为符号常量NULL
例如:float *ptr_var3=NULL;
说明:NULL是一个空指针,表示该指针变量的值没有意义。作用是为了避免对没有被初始化的指针变量的非法引用。NULL 的定义在“stdio.h”中。
4、通过指针为变量赋值
例如:

	int *ptr_var = NULL;
	int var = 100;
	ptr_var = &var;
	*ptr_var = 10;	/*等价于var = 10;*/
	/*如果ptr_var指向var,则把10赋给var*/

指针运算符

&是一元运算符,它返回操作数的内存地址
例如:

int var=12,*ptr;
ptr = &var;

*是 &的反运算符,它也是一元运算符,返回指针指向的内存位置中的值
例如:

int var=12,*ptr=&var;
int temp = *ptr;	//等价于temp=var;

对“&”和“”运算符说明:
(“&”和“
”两个运算符的优先级别相同,但按自右而左方向结合)

如果已执行了语句 pointer_1=&a; pointer_2=&a ;
(1) pointer_2 =&* pointer_1 ?
先进行* pointer_1的运算,它就是变量a,再执行&运算。&* pointer_1与&a相同,即变量a的地址,就是将&a(a的地址)赋给pointer_2

(2) &a? &a?
先进行&a运算,得a的地址,再进行
运算。即&a所指向的变量,也就是变量a。
&a和pointer_1的作用是一样的,它们都等价于变量a。即&a与a等价。

(3) (pointer_1)++ 和 pointer_1++
pointer_1++:++和为同一优先级别,而结合方向为自右而左,因此它相当于
(pointer_1++)。由于++在pointer_1的右侧,是“后加”,因此先对pointer_1的原值进行
运算,得到a的值,然后使pointer_1的值改变,这样pointer_1不再指向a了。
(*pointer_1)++: *pointer_1相当a,所以整个表达式相当于a++

指针的算术运算

两种形式:指针±整数 或者 指针 - 指针
注:①指针与整型值加减的结果是指针,表示使该指针指向该指针下移或上移存储单元个数(整型值)之后的内存地址。存储单元的大小就是该指针的数据类型所需的内存大小。
②指针与指针的减运算要求相减的两个指针属于同一类型,其结果是整数,表示两个指针之间的数据的个数。
例如:

//假定var存储在地址1000中,因为整数的长度是 4 个字,ptr_var节的值将是1004
int var, *ptr_var;
ptr_var = &var;
ptr_var ++;	

指针递增时,将指向其类型的下一个元素的内存位置,反之亦然
在这里插入图片描述

指针比较

前提:两个指针都指向相同类型的变量
假设ptr_a和ptr_b分别指向a和b
在这里插入图片描述

指针按地址传递

指针可以作为参数
把实参的地址传给形参
允许函数访问内存位置
被调函数能够修改主调程序的参数的值
示例:

#include <stdio.h>
void swap(int *pi1, int *pi2)
{
    
    
int temp;
temp = *pi1;
*pi1 = *pi2;
*pi2 = temp;
}

void main()
{
    
    
int iNum1, iNum2;
iNum1 = 10;
iNum2 = 20;
swap(&iNum1, &iNum2);
printf(“iNum1=%d,iNum2=%d” ,iNum1,iNum2);
}

指针与一维数组

一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。指针变量既然可以指向变量,当然也可以指向数组和数组元素。

所谓数组的指针(数组的名称)是指数组的起始地址,也就是第一个元素的地址。数组的指针是个常量指针

数组元素的地址可以用两种方式表示:
①在数组元素前面加“&”符号, 例如:&ary[2]
②数组名 + 下标 ,例如:ary + 2

示例:

#include <stdio.h>

int main()
{
    
    
	static int ary[10] = {
    
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
	int i;
	int *p=NULL;
  	for (i = 0; i < 10; i ++)
	{
    
    
		printf("\ni=%d,ary[i]=%d,*(ary+i)=%d  ",i,ary[i],*(ary + i));
		printf("  &ary[i]= %X,ary+i=%X",&ary[i],ary+i);
	}
	for (p = ary; p < ary+10 ; p++)
	{
    
    	/*能否使用ary++?*/
		printf("\naddress:%x,value:%d",p,*p);
	}
	return 0;
}

数组作参数传递

一维数组元素作参数传递时,按值传递

整个数组(数组名)当参数传递时,按地址传递,有以下三种等价的写法:

void TestArray(char ary[ ]);
void TestArray(char ary[LEN]);
void TestArray(char *ary);

整型数组作为返回值

归纳起来,如果有一个实参数组,想在函数中改变此数组中的元素的值,实参与形参的对应关系有以下4种情况:
① 形参和实参都用数组名,如:

void f(int x[],int n)
{
    
     ····
}
void main()
{
    
    
	int a[10];
	·····
	f(a,10)
}

②实参用数组名,形参用指针变量。如:

void f(int *x,int n)
{
    
     ····
}
void main()
{
    
    
	int a[10];
	·····
	f(a,10)
}

③实参形参都用指针变量。例如:

void f(int *x,int n)
{
    
     ····
}
void main()
{
    
    
	int a[10]*p=a;
	·····
	f(a,10)
}

④实参为指针变量,形参为数组名。如:

void f(int x[],int n)
{
    
     ····
}
void main()
{
    
    
	int a[10]*p=a;
	·····
	f(a,10)
}

指向字符串常量的字符指针

可以声明字符指针直接指向字符串常量,例如char* pStr=“Welcome”;字符指针pStr将指向字符常量“Welcome”。“Welcome”为字符串常量,因此其值不能修改。

可以使用字符指针来存储和访问字符串
声明字符指针语法:char* pStr;
声明字符串:char str[10]=“hello”;
使用字符指针指向字符串:pStr=str;
可以使用字符指针访问字符串,例如pStr[0]=‘a’; 该代码将第一个字符修改为’a’

void main()
{
    
    
	char* pStr;
	char str[10]="hello";
	pStr=str;
	pStr[0]='a';
	printf("pStr = %s\n",pStr);
}  ==>pStr = aello

字符数组与字符指针的区别

在这里插入图片描述

字符数组作为返回值

#include <stdio.h>
char *print()
{
    
    
	char acStr[]="hello world";
	return acStr;>返回整个数组(数组首地址)
}
void main()
{
    
    
	char *pcStr;
    pcStr = print();
    puts(pcStr);
	return;
}

结果:
在这里插入图片描述
不能打印hello world原因:
在函数中的数组是局部变量,函数结束系统自动清除。如果此时返回一一个地址,可能会访问到系统下次分配到的数据,如果
修改该位置还可能导致巨大的错误。

这里可以把char acStr[]="hello world"; 改为char *acStr="hello world";

猜你喜欢

转载自blog.csdn.net/qq_46485161/article/details/115035600
今日推荐