带你分分钟玩转C语言指针

目录
  • 何为指针
  • 数组指针
  • 指针数组
  • 字符串数组
  • 数组指针的sao气操作
  • 二级指针
  • 函数指针
  • 指针函数
  • 文件指针
  • 总结

何为指针

指针这玩意说白了,就是用来存储一个变量地址的东东 如图:

(编辑器为vc2010)

#include<stdio.h>
void main(){
	int a,*p;
	a=5;
	p=&a;
	printf("a=%d,p=%p,*p=",a,p,*p);
	getchar();

}

所以通过刚刚的情况,我们发现通过指针我们不仅可以获取一个变量的值还可以直接对变量的值修改

又如下面的例子:

#include<stdio.h>
void main(){
	int a=3;
	int* prt;
	prt=&a;
	printf("a的值为%d\na的地址为%p\nprt存放的值为%p\nprt的内存地址为%p\nprt所存的地址对应的值为%d",a,&a,prt,&prt,*prt);
	getchar();

}

数组指针

说到指针只说基本的int char float有什么意思,接下来是一个数组指针 将数组和指针结合起来.当然数组本身在传递的时候就是以指针传递的. 下面是以段代码演示

#include<stdio.h>
void main(){
	int a [5]={1,2,3,4,5},*p,i;
	p = a;
	for(i=0;i<5;i++){
		printf("&a[%d]=%p,a[%d]=%d\n",i,p,i,p[i]);

	}
	getchar();
}

我们发现当p=a(指针指向数组a)后,指针p可以和数组a一样操作,这就是指针数组.

指针数组

既然说到了指针数组那么就不得不说数组指针,乍一看这两个名字很像,其实差距还是很大的. int *p[] 下面还是以上面的例子为例,我们让输出结果一致

#include<stdio.h>
void main(){
	int a [5]={1,2,3,4,5},*p[5],i;
	for(i=0;i<5;i++){
		p[i]=&a[i];
	}
	for(i=0;i<5;i++){
		printf("&a[%d]=%p,a[%d]=%d\n",i,p[i],i,*p[i]);

	}
	getchar();
}

我们发现,这个东东其实就是一个存储地址的数组,这个内存地址既可以是int char 或者float 同时也可以是数组,这个我们在说完字符串数组后再说.

字符串数组

C语言里面没有string类(java)也没有str(python)只有字符,所以我们引入了字符串数组,用来存储字符串. ('a' 一个字节 "a"两个字节) 这里要注意一下的是,一个字符串数组如 char a[5]="hello",表面上看这里只有五个字符,但是其实在他们的内存分布里面最后面结尾('o'后面)还有一个字符'\0'表示结束,所以只用char a[5]放不下hello,char a[6]="hello"才行.所以"a" 是'a'+'\0'两个字节('\0'不显示)

#include<stdio.h>
void main()
{
	char a[6]={'h','e','l','l','o'};
	//char a[6] ="hello";也行
	printf("%s",a);
	getchar();
}

此外还要注意一点直接写一个"hello"也是一个字符串数组只不过未命名罢了,我们可以用指针访问

#include<stdio.h>
void main()
{
	char *p="hello";
	printf("%s\n",p); //%s 会读取第一个字符的地址知道读到'\0'
	printf("%c",p[1]);//输出字母e
	getchar();
}

数组指针的sao气操作

先看一段代码

#include<stdio.h>
void main(){
	char *p[3]={
		"hello",
		"my",
		"friend"
	};
	printf("%s",p[1]);
	getchar();

}

现在我们发现p[1]可以和一个字符指针一样操作,也就是说 p[1]等价于

char a[4]="my",*c; c=a; 这里的c就等价于p[1]

#include<stdio.h>
void main(){
	char *p[3]={
		"hello",
		"my",
		"friend"
	};
	int i;
	for(i=0;i<2;i++)
	{
		printf("%c\n",p[1][i]);
	}
	getchar();
}

二级指针

这个家伙,就是套娃,看一张图就明白了

函数指针

int (*p)( int x) int 指向的函数类型 (*p)指针名字 (int x) 所指向的函数所需要输入的参数

这个呢就是一个函数 举个例子

#include<stdio.h>
void main(){
	int go(int x);
	int x,(*p)(int x);
	scanf("%d",&x);
	p=go;//指针指向函数
	//(*p)(x)也行
	p(x);
	getchar();
	getchar();
}

int go(int x)
{
	printf("you input number is:%d",x);
}

这玩意的好处是啥呢, 有了这玩意,我可以直接向一个函数里面传递另一个函数 举例升级

#include<stdio.h>
void main(){

	int go(int x),x;
	void show(int x, int(*p)(int x));

	scanf("%d",&x);
	show(x,go);
	getchar();
	getchar();
}

int go(int x)
{
	printf("you input number is:%d",x);
}
void show(int x, int(*p)(int x)){
	printf("you have inputed!\n");
	p(x);

}

指针函数

说白了这就是一个函数,返回了一个地址如:

int* go (int* x,int* y)

和函数指针长得像,原因在于* 得运算级别比()低所以函数指针加了() 举个例子

#include<stdio.h>
void main(){

	int *go(int *x);
	int a=5,*p;
	p=go(&a);
	printf("a的地址为:%p,值为:%d",p,*p);
	getchar();
}

int *go(int *x){
	printf("地址以获取\n");
	return x;
}

文件指针

这个就有意思了,C语言把所有的设备都视为指针. FILE *fp=NULL; fp = fopen("文件路径","w") ("w"是打开模式,w写) fprintf(fb,"%s",str) 这玩意和print的用法是一样的只不过前面指明了指针 换句话说 printf("hello) 与 fprintf(stdout,"hello")一样,stdout屏幕指针,stdin键盘指针 同理 fputs("hello",fp)

接下来是读文件 char s[100] fp = fopen("文件路径","r")
fscanf(fp,"%s",s) fgets(s,100,fp) (100是最大长度) 区别是什么呢,fprintf()读到空格或回车就返回,fgets()读到回车返回 此外还要fread() fread(接收数据的地址,读取多少字节的内容,数据项个数,文件指针) 其他的查手册就好 最后别忘了关闭 fclose(fp)

总结

到此这篇关于C语言指针的文章就介绍到这了,更多相关C语言指针内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2022-06-07

C语言入门之指针用法教程

本文针对C语言初学者详细讲述了指针的用法,并配以实例进行说明.具体分析如下: 对于C语言初学者来说,需要明白指针是啥?重点就在一个"指"上.指啥?指的地址.啥地址?内存的地址. 上面说明就是指针的本质了. 这里再详细解释下.数据存起来是要存在内存里面的,就是在内存里圈出一块地,在这块地里放想放的东西.变量关心的是这块地里放的东西,并不关心它在内存的哪里圈的地:而指针则关心这块地在内存的哪个地方,并不关心这块地多大,里面存了什么东西. 指针怎么用呢?下面就是基本用法: int a, b,

C语言指针的长度和类型深入分析

指针是C语言的精髓,本文就以实例的形式详细分析了C语言的长度和类型.对于初学者深入理解C语言程序设计有很好的参考价值.具体分析如下: 一般来说,如果考虑应用程序的兼容性和可移植性,指针的长度就是一个问题,在大部分现代平台上,数据指针的长度通常是一样的,与指针类型无关,尽管C标准没有规定所有类型指针的长度相同,但是通常实际情况就是这样.但是函数指针长度可能与数据指针的长度不同. 指针的长度取决于使用的机器和编译器,例如:在现代windows上,指针是32位或是64位长 测试代码如下: #inclu

C语言 指针与二维数组详解

二维数组在概念上是二维的,有行和列,但在内存中所有的数组元素都是连续排列的,它们之间没有"缝隙".以下面的二维数组 a 为例: int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} }; 从概念上理解,a 的分布像一个矩阵: 0   1   2   3 4   5   6   7 8   9  10  11 但在内存中,a 的分布是一维线性的,整个数组占用一块连续的内存: C语言中的二维数组是按行排列的,也就是先存放 a[

C语言指针学习经验总结浅谈

这篇C语言指针学习经验总结主要是我入职以来学习C指针过程中的点滴记录.文档里面就不重复书上说得很清楚的概念性东西,只把一些说得不清楚或理解起来比较费解的东西做一下讲解,希望能达到以下三个目的 1.通过写这些东西,把我脑袋中关于C的模糊的知识清晰化.2.给初转C的同事们一点提示和帮助.3.也希望各位前辈检查一下文档中是否有理解偏差的地方.1 指针的概念分解      指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址. 要搞清一个指针需要搞清指针的四方面的内容: 1.指针的类型2.指

C语言指针详解及用法示例

新手在C语言的学习过程中遇到的最头疼的知识点应该就是指针了,指针在C语言中有非常大的用处.下面我就带着问题来写下我对于指针的一些理解. 指针是什么? 指针本身是一个变量,它存储的是数据在内存中的地址而不是数据本身的值.它的定义如下: int a=10,*p; p=&a int a=10; int *p=&a; 首先我们可以理解 int* 这个是要定义一个指针p,然后因为这个指针存储的是地址所以要对a取地址(&)将值赋给指针p,也就是说这个指针p指向a. 很多新手都会对这两种定义方法

C语言的指针类型详细解析

指针存储了内存的地址,同时指针是有类型的,如int*,float*,那么,一个自然的猜想就是指针变量应该存储这两方面的信息:地址和指针类型,比如,就像下面的结构体: 复制代码 代码如下: struct pointer{    long address;    int type;} 举个例子:打印sizeof(int*),值为4,可见4字节是存储内存地址用的,反过来就说明指针并没有存储类型信息的地方,那么指针的类型信息存放在哪儿呢?下面剖析一段简单的代码. 复制代码 代码如下: // ma.cpp

c语言指针之二级指针示例

二级指针的概念 首先任何值都有地址,一级指针的值虽然是地址,但这个地址做为一个值亦需要空间来存放,是空间就具有地址,这就是存放地址这一值的空间所具有的地址,二级指针就是为了获取这个地址,一级指针所关联的是其值(一个地址)名下空间里的数据,这个数据可以是任意类型并做任意用途,但二级指针所关联的数据只有一个类型一个用途,就是地址,指针就是两个用途提供目标的读取或改写,那么二级指针就是为了提供对于内存地址的读取或改写指针的表现形式是地址,核心是指向关系指针运算符"*"的作用是按照指向关系访问

C语言 结构体和指针详解及简单示例

指针也可以指向一个结构体,定义的形式一般为: struct 结构体名 *变量名; 下面是一个定义结构体指针的实例: struct stu{ char *name; //姓名 int num; //学号 int age; //年龄 char group; //所在小组 float score; //成绩 } stu1 = { "Tom", 12, 18, 'A', 136.5 }; //结构体指针struct stu *pstu = &stu1; 也可以在定义结构体的同时定义结构

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

C语言允许函数的返回值是一个指针(地址),我们将这样的函数称为指针函数.下面的例子定义了一个函数 strlong(),用来返回两个字符串中较长的一个: #include <stdio.h> #include <string.h> char *strlong(char *str1, char *str2){ if(strlen(str1) >= strlen(str2)){ return str1; }else{ return str2; } } int main(){ cha

详解C语言结构体中的函数指针

结构体是由一系列具有相同类型或不同类型的数据构成的数据集合.所以,标准C中的结构体是不允许包含成员函数的,当然C++中的结构体对此进行了扩展.那么,我们在C语言的结构体中,只能通过定义函数指针的方式,用函数指针指向相应函数,以此达到调用函数的目的. 函数指针 函数类型 (*指针变量名)(形参列表):第一个括号一定不能少. "函数类型"说明函数的返回类型,由于"()"的优先级高于"*",所以指针变量名外的括号必不可少.  注意指针函数与函数指针表示

详解C++调用Python脚本中的函数的实例代码

1.环境配置 安装完python后,把python的include和lib拷贝到自己的工程目录下 然后在工程中包括进去 2.例子 先写一个python的测试脚本,如下 这个脚本里面定义了两个函数Hello()和_add().我的脚本的文件名叫mytest.py C++代码: #include "stdafx.h" #include <stdlib.h> #include <iostream> #include "include\Python.h&quo

详解Swift语言中的类与结构体

类 在 Swift 中类是建立灵活的构建块.类似于常量,变量和函数,用户可以定义的类的属性和方法.Swift给我们提供了声明类,而无需用户创建接口和实现文件的功能.Swift 允许我们创建类作为单个文件和外部接口,将默认在类一次初始化来创建. 使用类的好处: 继承获得一个类的属性到其他类 类型转换使用户能够在运行时检查类的类型 初始化器需要处理释放内存资源 引用计数允许类实例有一个以上的参考 类和结构的共同特征: 属性被定义为存储值 下标被定义为提供访问值 方法被初始化来改善功能 初始状态是由初

详解C语言中结构体的自引用和相互引用

结构体的自引用(self reference),就是在结构体内部,包含指向自身类型结构体的指针. 结构体的相互引用(mutual reference),就是说在多个结构体中,都包含指向其他结构体的指针. 1. 自引用 结构体 1.1 不使用typedef时 错误的方式: struct tag_1{ struct tag_1 A; /* 结构体 */ int value; }; 这种声明是错误的,因为这种声明实际上是一个无限循环,成员b是一个结构体,b的内部还会有成员是结构体,依次下去,无线循环.

详解C语言的结构体中成员变量偏移问题

c语言中关于结构体的位置偏移原则简单,但经常忘记,做点笔记以是个记忆的好办法 原则有三个: a.结构体中的所有成员其首地址偏移量必须为器数据类型长度的整数被,其中第一个成员的首地址偏移量为0, 例如,若第二个成员类型为int,则其首地址偏移量必须为4的倍数,否则就要"首部填充":以此类推 b.结构体所占的总字节数即sizeof()函数返回的值必须是最大成员的长度的整数倍,否则要进行"末尾填充": c.若结构体A将结构体B作为其成员,则结构体B存储的首地址的偏移量必须

C语言 结构体(Struct)详解及示例代码

前面的教程中我们讲解了数组(Array),它是一组具有相同类型的数据的集合.但在实际的编程过程中,我们往往还需要一组类型不同的数据,例如对于学生信息登记表,姓名为字符串,学号为整数,年龄为整数,所在的学习小组为字符,成绩为小数,因为数据类型不同,显然不能用一个数组来存放. 在C语言中,可以使用结构体(Struct)来存放一组不同类型的数据.结构体的定义形式为: struct 结构体名{     结构体所包含的变量或数组 }; 结构体是一种集合,它里面包含了多个变量或数组,它们的类型可以相同,也可

C语言 结构体数组详解及示例代码

所谓结构体数组,是指数组中的每个元素都是一个结构体.在实际应用中,结构体数组常被用来表示一个拥有相同数据结构的群体,比如一个班的学生.一个车间的职工等. 定义结构体数组和定义结构体变量的方式类似,请看下面的例子: struct stu{ char *name; //姓名 int num; //学号 int age; //年龄 char group; //所在小组 float score; //成绩 }class[5]; 表示一个班级有5个学生. 结构体数组在定义的同时也可以初始化,例如: str

详解C 语言项目中.h文件和.c文件的关系

详解C 语言项目中.h文件和.c文件的关系 在编译器只认识.c(.cpp))文件,而不知道.h是何物的年代,那时的人们写了很多的.c(.cpp)文件,渐渐地,人们发现在很多.c(.cpp)文件中的声明语句就是相同的,但他们却不得不一个字一个字地重复地将这些内容敲入每个.c(.cpp)文件.但更为恐怖的是,当其中一个声明有变更时,就需要检查所有的.c(.cpp)文件. 于是人们将重复的部分提取出来,放在一个新文件里,然后在需要的.c(.cpp)文件中敲入#include XXXX这样的语句.这样即

详解Go语言中关于包导入必学的 8 个知识点

1. 单行导入与多行导入 在 Go 语言中,一个包可包含多个 .go 文件(这些文件必须得在同一级文件夹中),只要这些 .go 文件的头部都使用 package 关键字声明了同一个包. 导入包主要可分为两种方式: 单行导入 import "fmt" import "sync" 多行导入 import( "fmt" "sync" ) 如你所见,Go 语言中 导入的包,必须得用双引号包含,在这里吐槽一下. 2. 使用别名 在一些场

详解C语言函数返回值解析

详解C语言函数返回值解析 程序一: int main() { int *p; int i; int*fun(void); p=fun(); for(i=0;i<3;i++) { printf("%d\n",*p); p++; } return 0; }; int* fun(void) { static int str[]={1,2,3,4,5}; int*q=str; return q; } //不能正确返回 虽然str是在动态变量区,而该动态变量是局部的,函数结束时不保留的.