C语言指针收藏
指针是什么
》》每一个内存单元只能同时存储一个数据,如何保证内存单元同时只能存储一个数据,可以使用编号的方式实现内存单元标记,此编号就是指针。
》》指针是一个变量,指针是存放着一个数据的内存地址而不是数据本身的值,其是查找数据的另一种方式
相关运算符
【&】在变量中取地址
【*】在地址中取变量
测试小程序:
#include<stdio.h>
void main() {
int i = ;//定义一个变量,并赋初始值为10
int *p = &i;//定义一个指针变量,并赋初始值为i的地址
*p = ;
printf("%d=%d", *p,i);//输出199=199
printf("---%d---", p);//得到变量i的地址
}
指针变量的类型
》》指针类型:int *、float*、long*、double*、char*等等
》》指针变量的类型需要与存储的数据类型相同
》》确定类型可以方便指针变量确定存储数据的大小,为数据寻找到结束符,如int类型占四个字节、char占一个字节。也方便指针使用加1或减1操作,如int加减1会跳动4个字节,char加减1会跳动两个字节。
指针的赋值
int i=10; int *p=&i;

int *pp;
pp=p;

指针运算符:
*p++
等同于*(p++),运算优先级为从右到左,应该是先*p取值,然后地址移动一位,要区别与*(++p)。
char *ch="";
//printf("%c\r\n",*ch++);//输出0
//printf("%c\r\n",*(ch++));//输出0
printf("%c\r\n",*(++ch));//输出1
指针变量作为函数参数
#include<stdio.h>
//int *a1=&b1;
void fun(int *a1, int* a2) { *a1 = ;
int ii = ;
a2 = ⅈ//让指针重新指向另外一个地址
printf("得到的数据:%d,%d", *a1, *a2);//输出100,99
}
void main() {
int b1 = , b2 = ;
fun(&b1, &b2);
printf("调用函数后:%d,%d", b1, b2);//输出100,2
}
输出b2的结果并不是相同的值,是因为执行调用函数改变了实参指针变量的值,并不是改变了实参指针变量所指变量的值
数组作为函数参数
#include<stdio.h>
void fun1(int *arr){
arr[]=;
arr[]=;
}
void fun2(int arr[]){
arr[]=;
arr[]=;
}
void main(){
//变量初始化
int i;
int a[]={,,,,,,};
//函数调用
fun1(a);
fun2(a);
//打印
for(i=;i<sizeof(a)/sizeof(int);i++){
printf("%d ",a[i]); //10 11 100 110 4 5 6
}
}
数组作为函数参数会自动退化为指针
函数形参如果是数组,不管下标是多少都会自动转换为数组的首地址指针
#include<stdio.h>
void fun1(int *p){
printf("%d",p[]);//
}
void fun2(int p[]){
printf("%d",p[]);//
}
void fun3(int p[]){
printf("%d",p[]);//
}
void fun4(char *p[]){
printf("%s",p[]);//dong
}
void fun5(char **p){
printf("%s",p[]);//dong
}
void main(){
int ii[]={,,};
fun1(ii);
fun2(ii);
fun3(ii);
char *ch[]={"dong","xiao"};
fun4(ch);
fun5(ch);
}
一维数组指针变量
数组名(如arr)代表元素的首地址,数组第一个元素的地址也是这个数组的首地址(如&arr[0])。
数组指针中使用加减1将跳到下一个或者上一个数组元素地址,与使用 &arr[n+1] 基本相同。
如果整数数组名为arr,运行int *p=arr,则*(p+3)、p[3]、*(arr+3)、arr[3]效果均是取出数组arr的第三个元素,在编译时arr[3]实际上是*(arr+3)处理的。
#include<stdio.h>
void main() {
int arr[] = { ,,,, };
int *p = arr;
int *pp = &arr[];
printf("%d", *(p+));//输出2
}
函数数组参数
#include<stdio.h>
//等价于void fun(char a1[]) {
void fun(char *a1) {
*(a1 + ) = 'c';//改变第二个值的内容
}
void main() {
char b1[] = { "" };
fun(b1);
printf("调用函数后:%s", b1);//输出: 12c456789
}
二维数组指针变量
#include<stdio.h>
void main() {
int a1[][] = { {,,},{,,} };
int a[][] = { ,,,,, };
printf("地址:%d==%d==%d==%d", a[], &a[][],*(a+),a+);//输出地址
printf("%d===%d==%d", a[][], *(*(a + )+),*(a[]+));//得到值
}
指针引用字符串
字符串常量【char *ch = "dong xiao dong";】表示其指向地址的内容不可变,但指向的地址是可变的;
字符串变量【char ch[] = "dong xiao dong";】其指向地址的内容可变。
#include<stdio.h>
void main() {
//char *ch = "dong xiao dong"; //字符串常量,不可变
char ch[] = "dong xiao dong"; //字符数组,可变
ch[] = '';//字符串常量运行这条将报错
printf("%s\n", ch);
}
可变格式的输出函数:
#include<stdio.h>
void main() {
char *ch = "dong xiao %d\n";
printf(ch, );
ch = "xiaoxiao%d\n";
printf(ch, );
char chh[] = "dongdong %d\n";
printf(ch, );
}
指向函数的指针
【int(*p)(int, int);//定义一个函数指针变量p】,第一个int表示返回值类型,第二个int和第三个int表示函数的参数类型。注意*p两侧的括号不能省略,表示p先与*结合,是指针变量,然后再于后面的()结合,()表示是函数,即该指针变量不是指向一般的变量,而是指向函数。如果写成“int * p(int,int);”,由于()优先级高于*,它相当于“int *(p(int,int))”,就成了声明一个p函数,并且这个函数的返回值是指向整型变量的指针。
返回值为int
#include<stdio.h>
void main() {
int minto(int a, int b);//函数声明
int(*p)(int, int);//定义一个函数指针变量p
p = minto;//函数指针指向函数minto首地址
int cc = (*p)(, );//调用函数
printf("Min===%d", cc);
} int minto(int a, int b) {
if(a > b) return b;
else return a;
}
无返回值:
#include<stdio.h>
void main() {
void fun(int a);//函数声明
void (*p)(int);//定义一个函数指针变量p
p = fun;//函数指针指向函数fun首地址
(*p)();//调用函数
}
void fun(int a) {
printf("%d\n", a);
}
指向函数指针作为函数的参数
#include<stdio.h>
void main() {
int fun(int(*addpp)(int, int), int x, int y);//函数声明
int add(int i, int j); int ii=fun(add, , );//传递函数名和参数即可
printf("输出相加的值为:%d", ii);
} //int (*addpp)(int,int);addpp=add;
int fun(int (*addpp)(int,int),int x,int y){
int cc = (*addpp)(x, y);
return cc;
} int add(int i, int j) {
return i + j;
}
返回指针的函数
#include<stdio.h>
void main() {
int* add(int i, int j);
int *p = add(, );
printf("输出相加的值为:%d", *p);
} int* add(int i, int j) {
int aa = i + j;
return &aa;//返回地址
}
指针数组
一个数组其全部元素都存放着指针,就是指针数组【int * p[5];】
#include<stdio.h>
void main() {
//指针数组
char * p[] = { "dong1","xiao2","dong3","dong4" };
printf("%s\n", p[]);
}
进阶版
#include<stdio.h>
void main() {
//指针数组(字符串)
char * p[] = { "dong1","xiao2","dong3","dong4" };
char **pp;
pp = p;
printf("%s\n", *(pp+));//转换一次就可以拿到对应字符串的首地址通过%s打印 //指针数组(整数)
int a[]= {,,, };
int * ip[] = { &a[],&a[],&a[],&a[],&a[]};
int **ppp = ip;
printf("%d\n", *(*ppp+));//转换第一次得到存储的指针,再次转换得到值
}
void类型指针
void a;//定义一个无类型变量,错误,不能确定分配的内存大小
void *a;//定义一个无类型指针,可行,指针类型都是4个字节(32位,64位为8个字节)
void *p;表示指针变量p不指向一个确定的类型数据,它的作用仅仅是用来存放一个地址。
可以将任意类型的指针直接给void指针赋值,但是如果需要将void指针的赋值给其他类型的指针,则需要进行强制类型转换
#include<stdio.h>
void fun1(void *i){
int *p=(int *)i;//强制类型转换
*p=;
}
void main(){
int ii=;
fun1(&ii);
printf("%d",ii);//输出100
}
错误示范
1、
int *p=10; //等同于:int *p; p=10;
分析:非法操作,内存地址不能用户自定义。10相当于一个内存地址,该内存地址的值不确定且也不明确该地址是否可以直接访问,正确的应该是使用【&变量名】得到内存地址。
2、
int f = 12.3;
int *p;
*p = &f; //错误1
int ff = &f; //错误2
分析:指针(地址)必须赋值给指针变量
C语言指针收藏的更多相关文章
- C语言指针转换为intptr_t类型
1.前言 今天在看代码时,发现将之一个指针赋值给一个intptr_t类型的变量.由于之前没有见过intptr_t这样数据类型,凭感觉认为intptr_t是int类型的指针.感觉很奇怪,为何要将一个指针 ...
- [转]C语言指针学习经验总结浅谈
指针是C语言的难点和重点,但指针也是C语言的灵魂 . 这篇C语言指针学习经验总结主要是我入职以来学习C指针过程中的点滴记录.文档里面就不重复书上说得很清楚的概念性东西,只把一些说得不清楚或理解起来比较 ...
- 不可或缺 Windows Native (7) - C 语言: 指针
[源码下载] 不可或缺 Windows Native (7) - C 语言: 指针 作者:webabcd 介绍不可或缺 Windows Native 之 C 语言 指针 示例cPointer.h #i ...
- C语言指针学习
C语言学过好久了,对于其中的指针却没有非常明确的认识,趁着有机会来好好学习一下,总结一下学过的知识,知识来自C语言指针详解一文 一:指针的概念 指针是一个特殊的变量,里面存储的数值是内存里的一个地址. ...
- (转载)c语言指针学习
前言 近期俄罗斯的陨石.四月的血月.五月北京的飞雪以及天朝各种血腥和混乱,给人一种不详的预感.佛祖说的末法时期,五浊恶世 ,十恶之世,人再无心法约束,道德沦丧,和现在正好吻合.尤其是在天朝,空气,水, ...
- 关于C语言指针的问题
在学习关于C语言指针的时候,发现这样一个问题,代码如下: #include<stdio.h> #include<stdlib.h> #include<string.h&g ...
- C语言指针类型 强制转换
关于C语言指针类型 强制转换 引用一篇文章: C语言中,任何一个变量都必须占有一个地址,而这个地址空间内的0-1代码就是这个变量的值.不同的数据类型占有的空间大小不一,但是他们都必须有个地址,而这个 ...
- C语言指针和数组知识总结(上)
C语言指针和数组知识总结(上) 一.指针的基础 1.C语言中,变量的值能够通过指针来改变,打印指针的语句符号可以是: %08x 2.指针的本质 指针的本质就是变量,那么既然是变量,那么一定会分配地址 ...
- C语言指针操作
欢迎访问我的新博客:http://www.milkcu.com/blog/ 原文地址:http://www.milkcu.com/blog/archives/pointer-manipulation. ...
随机推荐
- c++中怎么实现Java中finally语句
所有学习c++的书籍都明确提出了,不要使用goto, 以免造成程序流程的混乱,使理解和调试程序都产生困难. 但是我们遇到这样一个场景怎么办:就是不管程序执行成功与否,都要执行一些资源释放语句,相当ja ...
- Cadence如何自定义快捷键
第一步:将pcbenv复制到SPB_Data下,并覆盖原来的文件 第二步:打开pcbenv文件,将script和views文件夹以及env复制到cadence安装目录\SPB_16.3\share\p ...
- 不设置JAVA_HOME运行eclipse
编辑eclipse目录下的eclipse.ini 在第一行加入下面那句话,实际路径按照系统中的jdk目录设置.这样设置后可以省了环境中的JAVA_HOME像myeclipse一样. -vm C:\ ...
- web 后台打印
//提交打印 function sbumitPrint() { printHidden("AppsDSPrintDoub.aspx?type=print"); } function ...
- angular 分页2
http://www.alliedjeep.com/2547.htm AngularJS Code (Users.js) var Users = angular.module('Users', []) ...
- 说“DPI”
作者:马健邮箱:stronghorse_mj@hotmail.com发布:2007.03.08更新:2007.04.02 目录一.基本概念二.图像文件中的DPI三.PDG文件中的DPI四.PDF文件中 ...
- C#多线程 线程嵌套调用问题
线程嵌套指的是:线程A的执行代码启动了线程B,线程B的执行代码又启动了线程C. 我原本以为线程A被Abort后,线程B会自动被Abort,但是我大错特错了. 在这种场景下,线程的管理就非常重要了. 线 ...
- linux linux系统的安装及使用
linux linux系统的安装及使用 一.linux系统中安装vm-tools工具: 步骤: 1.在vmware workstation软件中:虚拟机-安装vmware-tools-状态栏会提示- ...
- 自定义Mybatis框架
项目结构: https://files-cdn.cnblogs.com/files/mkl7/ownMybatis.zip 1. 创建maven工程并引入坐标: <?xml versi ...
- Educational Codeforces Round 60 (Rated for Div. 2)E(思维,哈希,字符串,交互)
#include <bits/stdc++.h>using namespace std;int main(){ string t; cin>>t; int n=t.size() ...