C语言-指针

发布于:2025-03-19 ⋅ 阅读:(13) ⋅ 点赞:(0)

指针一

1. 指针就是内存单元的地址;存放地址的变量称为指针变量。

一般形式:

<存储类型> <数据类型> * <指针变量名>                eg: char * pName;

数据类型:指针指向的数据类型;

int *p; int a;  p = &a;

 向一个指针变量赋值时,送的值必须是地址常量或者指针变量,不能是普通的整数(除了赋零)

指针的大小与操作系统的位数有关

指针算术运算表(指针运算一般与数组相结合)

指针加减得到的不是地址量,而是两指针之间相隔数据的个数、

#include<stdio.h>
int main(int argc, const char *argv[])
{
	int a[5]= {4 , 5 , 9, 7, 2};
	int *p,*q,*c;
	q = &a[3];
	p = a;
	printf("%p %p\n",p,q);
	printf("%d %d\n",*p,*q);
    printf("%d\n",q-p);//(结果为3)
    c = p++;
    printf("%p %d\n",p,*p);
    printf("%p %d\n",c,*c);    ( *c=4,*p = 5)

	return 0;
}

指针的p++等

#include<stdio.h>

int main(int argc, const char *argv[])
{
	int a[] = {5 , 8 , 4,2,9};
	int *p;
	int y;

	p = &a[1];
	y = (*--p)++;    (先赋值到y,然后进行++)

	printf("%d\n",*p);
	printf("%d\n",y);
	printf("%d\n",a[0]);
		
	return 0;
}
输出: 6 5 6   *p = a[0]

注意指针的位置:

#include<stdio.h>

int main(int argc, const char *argv[])
{
	int i,*p,a[7];
	p = a;
	for(i = 0; i< 7;i++)
	{
		scanf("%d",p++);
	}
	printf("\n");

	p = a;              //作用是用来调整指针位置

	for(i=0;i<7;i++)
	{
		printf("%d ",*p);
		p++;
           
    //  printf("%d ",*p++);   //证明指针具有简洁性
	//	printf("%d ",a[i]);  (这样两种输出也可)
	}

    puts("");  //换行符

	return 0;
}

指针与数组

数组名是常量,所以x++ 会报错

数组名与指针变量都是地址量,但是指针变量是地址变量,而数组的指针是地址常量

x[i]   *(p+i)  *(x+i)  p[i]   具有一样的功能 : 访问数组第 i+1 个数组元素

#include<stdio.h>

int main(int argc, const char *argv[])
{
	int a[] = {1,3,4,54,21,0};
	int *p;
	int i,n;

	p = a;
	n = sizeof(a) / sizeof(int);
	for(i=0;i<n;i++)
	{

		printf("%d %d %d %d\n",a[i],*(p+i),*(a+i),p[i]);

	}

	return 0;
}

程序举例: 编写一个函数,将整形数组中n个数反序存放

#include<stdio.h>
#define N 5
int main(int argc, const char *argv[])
{
	int a[N]= {1,2,3,4,5};
	int t;
	int *p,*q;
	p = a;
	q = a+N-1;
	while(p<q)
	{
		t = *p;
		*p = *q;
		*q = t;
		p++;
		q--;

	}
	for(t = 0;t<N;t++)
	{
		printf("%d",a[t]);
	}
		puts("");

	return 0;
}

 指针与二维数组

二维数组的元素连续存储,按行优先存储

 编程实现,使用一级指针遍历 二维数组

#include<stdio.h>

int main(int argc, const char *argv[])
{
	
	int a[3][2] = {{1,2},{3,4},{5,6}};
	int *p,i,n;
	n = sizeof(a) / sizeof(int);

	//p = a;  会出现警告
	p =&a[0][0];//或者  p = a[0];

	for(i = 0;i<n;i++)
	{
		printf("%d ",p[i]);
	}
	puts("");
	
	return 0;
}

将二维数组看做是多个一维数组组成

 二维数组名称为行地址    *(a+1) 等价于a[1]       a+1走一行,a[1]+1 走一个元素大小    

a[0] a[1] 同样是数组名,不可以后接++   

数组指针 

<存储类型>  <数据类型>  (* <指针变量名>)[表达式]

int (*p)[3];    3列

编程实现,使用行指针表示二维数组 的元素a[1][1] ,并实现二维数组的遍历

#include<stdio.h>

int main(int argc, const char *argv[])
{
	
	int a[3][2] = {{1,2},{3,4},{5,6}};
	int (*p)[2],i,j;

	p = a;

	printf("%d %d %d %d\n",a[1][1],*(* (a+1)+1),*(*(p+1)+1),p[1][1]);

	for(i = 0; i <3;i++){
		for(j=0;j<2;j++)
	printf("%d %d %d %d\n",a[i][j],* (*(a+i)+j),*(*(p+i)+j),p[i][j]);
		puts("");
	}

	return 0;
}
区别就是 a是地址常量  p是地址变量

 指针二

字符指针与字符串

C语言通过使用 字符数组 来处理  字符串

1.初始化字符指针是把内存中字符串的首地址赋予指针,并不是吧该字符串复制到指针

           char str[] = "hello world"; (存放在栈)    

               char *p = str;

这种类型可以通过指针改变字符串中的字符

2.C编程中,当一个字符指针指向一个字符串常量时,不能修改指针指向的对象的值

           char *p = "hello world";(hello world 为字符串常量,存放在只读数据段)

            *p = 'h';  //错误,字符串常量不能修改

程序举例:      

#include<stdio.h>
#include<string.h>
int main(int argc, const char *argv[])
{
	char ch[] = "welcome";
	char *p = "hello world";

	strcpy(ch,p);
	strcpy(p,ch);//会发生段错误

	return 0;
}

编程实现:不利用任何字符串函数,编程实现字符串连接函数的功能

#include<stdio.h>
int main(int argc, const char *argv[])
{
	char ch[100] = "welcome";
	char *p = " hello world";

	int i=0;
	while(*(ch + i) !=0)
	i++;

	while(*p !=0)
	{
		ch[i] = *p;// *(ch+i) = *p;
		p ++;
		i++;
	}
	ch[i] = *p;

	puts(ch);
	puts(p);


		return 0;
}

指针数组

指的是由若干个具有相同存储类型数据类型的指针变量构成的集合

指针数组经常和二维数组结合,二维数组的每一行都可以用一个指针变量指向

                                                   数组指针需要说明二维数组的列数

<存储类型> <数据类型>  *<指针数组名> [<大小> ]

double  * p[2];   //  double *p[0];  double *p[1];

double  * p[2] ,a[2][3];

p[0] = a[0];   //等价于 p[0] = &a[0][0];

p[1] = a[1];   //等价于 p[1] = &a[1][0];

#include<stdio.h>

int main(int argc, const char *argv[])
{
	int a[2][3] ={ {1,2,3},{4,5,6}};
	int * p[2];    //sizeof(p)=8   因为存放了两个指针
	p[0] = a[0];
	p[1] = a[1];

	printf("%d\n",a[0][1]);
	printf("%d\n", *(a[0]+1));
	printf("%d\n", *(p[0]+1));
	printf("%d\n", *(p[1]-2));
	
	return 0;
}

指针数组名加1,移动4个字节(指针大小) 

指针数组名相当于二级指针

程序举例:利用指针数组处理一个二维数组,要求求出二维数组所有元素的和

#include<stdio.h>

int main(int argc, const char *argv[])
{
	int a[2][3] ={ {1,2,3},{4,5,6}};
	int *p[2],i,j;
	int sum = 0;
	p[0] = a[0];
	p[1] = a[1];
	for(j=0;j<2;j++){
		for(i=0;i<3;i++)
		{
			sum += *(p[j]+i);
		}
	}
	printf("sum = %d\n",sum);

	return 0;
}

void指针   

#include<stdio.h>

int main(int argc, const char *argv[])
{
	int a = 10;
	double b = 3.13;
	void *p,*q;

	p = &a;//  p = (void *)&a;
	printf("%d %d\n",a,*(int *)p);

	q= &b; //  q = (void *)&b; //赋值是可以不转换
	printf("%.2lf %.2lf\n",b,*(double *)q); //void指针使用的时候必须强制类型转换,

	return 0;
}