目录

一、int类型指针

二、字符类型指针

三、数组类型指针

四、字符串类型指针

五、常量指针和指针常量

六、函数参数是指针

七、指针函数和函数指针

八、结构体指针


指针是用来指向一个内存块的地址的值。可以看一张图来理解指针:

64位机器:

char :1个字节
char*(即指针变量): 8个字节
short int : 2个字节
int:  4个字节
unsigned int : 4个字节
float:  4个字节
double:   8个字节
long:   8个字节
long long:  8个字节
unsigned long:  8个字节
1. 使用*符号定义一个指针:

int *p = NULL;

2. &符号为取地址符:

int x = 100;
p = &x; //取变量x的地址值

3. *符号为取值符号:

int x = 100;
p = &x;
printf("值:%d", *p); //*p取值

一、int类型指针


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>int main(void) {int a = 100;int *p = NULL; //定义一个int类型指针p = &a; //&号取地址值,&a就是取a的地址值printf("a的值:%d\n", *p); //*是取值符号,*p就是取a的值*p = 1001; //改变a的值为1001printf("a值被改变:%d\n", a); //输出a的值printf("a的地址值:%d\n", p); //直接p 即地址值
}

输出:

[admin@localhost test_c]$ ./point
a的值:100
a值被改变:1001
a的地址值:1389256820

二、字符类型指针


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>int main(void) {char x = 'a';char *p = NULL; //定义一个字符指针p = &x; //取x变量的地址值printf("x的值:%c\n", *p); //输出x的值printf("x的地址值:%d\n", p); //输出x的地址*p = 'z'; //将x变量的值改变为zprintf("x被改变:%c\n", x); //输出x的值
}

输出:

[admin@localhost test_c]$ ./point
x的值:a
x的地址:31265799
x被改变:z

三、数组类型指针


数组本身就是指向第一个数组元素地址的指针。

可以看一副图:

上图定义了一个int[10]的数组,内存块中会开辟10个int类型的块给这个数组使用。而每一个内存块占4个字节(64位系统),其中数组实际上指向的是a[0] 的内存块的值。

因为知道了a[0]的地址值之后,因为数组是连续的内存块地址,就可以通过 *(a + n) 这样的方式或者 a[n]这样的方式来读取数组中的元素了。

下面看一个字符数组的例子:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>int main(void) {char strs[5] = { 'a', 'b', 'c', 'd', 'e'};  char *pstrs = NULL;  //定义一个字符数组指针pstrs = strs;  //数组本身就是指向数组元素第一个值的内存的地址printf("数组第一个值:%c 数组第二个值:%c", *pstrs, *(pstrs + 1));  //如果指针指向地址改变,则指向数组的值也改变  pstrs++;  printf("\n数组第一个值:%c", *pstrs);  printf("\n数组也可以通过下标方式获取值:%c", strs[3]);  //还可以把数组变量直接当初指针来操作int i;  printf("\n循环输入:");  for (i = 0; i < sizeof(strs) / sizeof(char); i++) {   printf("\n:%c", *(strs + i));  }
}

输出:

[admin@localhost test_c]$ ./point
数组第一个值:a 数组第二个值:b
数组第一个值:b
数组也可以通过下标方式获取值:d
循环输入:
:a
:b
:c
:d
:e

四、字符串类型指针


定义一个字符串:

char str[] = "woshishen"; 

字符串相当于结尾会带\0的一个字符数组

我们可以通过strlen方法来获取字符串的长度。通过sizeof方法,则可以获取字符数组的长度。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>int main(void) {char str[] = "woshishen333"; //字符数组本身就是一个指针,指向字符数组的第一个位置printf("长度:%d\n", strlen(str)); //字符串的长度printf("实际的字符数组长度,结尾带\\0,长度:%d", sizeof(str));
}

输出:

[admin@localhost test_c]$ ./point
长度:12
实际的字符数组长度,结尾带\0,长度:13

定义的字符串本身就是字符数组,而数组本身就是指向第一个数组元素地址的指针。

下面可以看一个字符串指针例子:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>int main(void) {char str[] = "woshishen"; //字符数组本身就是一个指针,指向字符数组的第一个位置char *p = NULL; //定义一个字符串指针p = str;  //因为字符串是数组,而数组本身就是指向第一个数组元素的指针,所以不需要用&符号取值//字符串输出。因为字符串本身末尾会自动带上\0,所以直接通过%s就可以输出字符串//而如果是字符数组,因为数组中没有\0符号,所以拿着字符数组直接%s来输出就会有问题printf("字符串的值:%s\n", p); printf("字符串中的第一个值:%c\n", *p); //字符串第一个值printf("字符串中的第二个值:%c\n", *(p + 1)); //字符串第二个值p++;printf("改变字符串指针指向位置,指向第二个字符开始:%s\n", p);
}

输出:

[admin@localhost test_c]$ ./point
字符串的值:woshishen
字符串中的第一个值:w
字符串中的第二个值:o
改变字符串指针指向位置,指向第二个字符开始:oshishen

注:如果是 char *x = "sadasddsa";  则x指向的字符串被系统当做静态常量,不能通过指针修改字符串里面的字符内容。

五、常量指针和指针常量


1. 常量指针。常量指针不可以修改指针所指向的地址值。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>int main(void) {//常量指针常量指向一个地址后,不能被改变地址,但是可以改变地址int x = 100;int y = 200;int * const p = &x;*p = 200;//p = &y; //如果重新指向y的地址,则会编译出错printf("\n常量指针值:%d", *p);
}

输出:

[admin@localhost test_c]$ ./point
常量指针值:200

2. 指针常量。指针常量不可以修改指针所指向内存地址的值。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>int main(void) {//指针常量,不可以修改指针指向的内存地址的值int x = 100;int y = 200;int const *p = &x;//*p = 200; //不可以修改之p = &y;  //可以修改指向的地址printf("\n常量指针值:%d", *p);
}

输出:

[admin@localhost test_c]$ ./point 常量指针值:200

六、函数参数是指针


函数的入参为指针,则函数中可以修改该内存地址上的值。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>//传入指针
void swap(int *a, int *b) {  if (*a > *b) {  int temp;  temp = *a;  *a = *b;  *b = temp;  }
}  int main(void) {int xxx = 20, yyy = 10;  int *pxxx = NULL, *pyyy = NULL;  pxxx = &xxx;  pyyy = &yyy;  swap(pxxx, pyyy); //如果xxx > yyy 则变量值交换位置  printf("\nXXX:%d YYY:%d", xxx, yyy);
}

输出:

[admin@localhost test_c]$ ./point XXX:10 YYY:20

七、指针函数和函数指针


1. 指针函数,本身上还是一个函数,只不过返回值是指针类型的。

int *func(int x, int y);
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>//指针函数,返回值是int类型的一个指针
int *get(int *a) {*a = *a * 100;return a;
}  int main(void) {int a = 100;int *b = &a;int *c = get(b); //返回的指针用 int *c来接printf("指针函数的值:%d", *c);
}

输出:

[admin@localhost test_c]$ ./point
指针函数的值:10000

2. 函数指针。函数指针是指向函数的指针变量,即本质是一个指针变量

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>//普通函数
int sum(int a, int b) {return a + b;
}  int main(void) {int (* sum_p) (int x, int y); //声明一个函数指针int x = 100;int y = 200;//函数指针指向 sum这个函数//或是使用 sum_p = &sumsum_p = sum; //也可以使用 int z = (* sum_p)(x, y)int z =  sum_p (x, y);printf("\n函数指针的值:%d", z);
}

输出:

[admin@localhost test_c]$ ./point 函数指针的值:300

八、结构体指针


定义一个结构体:

//定义一个结构体
typedef struct student {  char *username;  int age;
} STU;  

下面是一个结构体指针的例子:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>//定义一个结构体
typedef struct student {  char *username;  int age;
} STU;  int main(void) {STU *p = NULL; //定义一个结构体指针p = (STU *) malloc(sizeof(STU)); //分配一个结构体内存,p指向这个内存地址p->username = "zhuli"; p->age = 100;printf("结构体数据:用户名%s 用户年龄%d", p->username, p->age);
}

也可以这样定义结构体,不过一般倾向于使用typedef来定义结构体

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>//定义一个结构体
struct student {  char *username;  int age;
};  int main(void) {struct student *p = NULL; //定义一个结构体指针p = (struct student *) malloc(sizeof(struct student)); //分配一个结构体内存,p指向这个内存地址p->username = "zhuli"; p->age = 100;printf("结构体数据:用户名%s 用户年龄%d", p->username, p->age);
}

输出:

[admin@localhost test_c]$ ./point
结构体数据:用户名zhuli 用户年龄100

Linux c 开发 - 指针相关推荐

  1. Linux 汇编语言开发指南

    Linux 汇编语言开发指南 肖文鹏 (xiaowp@263.net), 北京理工大学计算机系硕士研究生 本文作者 肖文鹏是北京理工大学计算机系的一名硕士研究生,主要从事操作系统和分布式计算环境的研究 ...

  2. 用 GStreamer 简化 Linux 多媒体开发

    GStreamer 是 GNOME 桌面环境下用来构建流媒体应用的编程框架(framework),其目标是要简化音/视频应用程序的开发,目前已经能够被用来处理像 MP3.Ogg.MPEG1.MPEG2 ...

  3. Linux后台开发必看!

    来自:我是程序员小贱 一 自我介绍二 面试情况三 相关知识点汇总1 c/c++相关2 计算机网络3 数据结构相关4 数据库相关5 操作系统6 Linux基础知识及应用编程(后台必备!)7 大数问题8 ...

  4. Linux 内核开发特点

    Linux 内核 开发的特点 无 libc 库抑或无标准头文件库 GUN C 没有内存保护机制 不要再内核中轻易使用浮点数 容积小而且固定的栈 同步和并发 可移植性的重要性 参考文献 开发的特点 相对 ...

  5. Linux后台开发应该具备技能

    Linux后台开发应该具备技能 一.linux和os: 1.命令:netstat tcpdump ipcs ipcrm  这四个命令的熟练掌握程度基本上能体现实际开发和调试程序的经验 2.cpu 内存 ...

  6. 基于c语言的linux嵌入式开发入门

    前言 本文主要包含,c语言基本结构与语法.make及makefile的使用.main函数参数与返回值的说明.标准输入.输出.错误流的介绍以及linux管道的应用. 语言数据类型 联合体也有翻译为共用体 ...

  7. linux驱动开发书籍(待续)

    (mine) C Primer Plus(第五版) 高质量程序设计指南.C语言(第三版) 林锐 [C.C...Java.程序设计经典教程] Linux指令速查手册 Linux设备驱动开发详解_宋宝华 ...

  8. linux 内核驱动的poll,嵌入式Linux驱动开发(五)——poll机制原理以及驱动实现...

    前情回顾: 再开始今天的内容之前,先简单review一下,我们都用了什么方案来获取按键值,他们的特点都是什么.只有不断地理清了思路,我们才能够更好的理解,为何会出现如此多的解决方案,当遇到问题的时候, ...

  9. (转)Linux后台开发应该具备技能

    Linux后台开发应该具备技能 分类: 杂谈 2013-04-14 12:45 741人阅读 评论(0) 收藏 举报 Linux后台开发应该具备技能 一.linux和os: 1.命令:netstat ...

最新文章

  1. Android 获取手机系统信息
  2. pygame判断鼠标左键_美商海盗船DarkCoreRGB Pro SE无线电竞鼠标评测
  3. 用FTP客户端实现主机和虚拟机之间文件的传输(方法2)
  4. android摄像头矩形框提取_视频图像摄像头跟踪的上位机系统设计
  5. 每个人都应该学git,最新GitHub上git指南我不信你不会git
  6. 电力企业信息化建设解决方案之计量生产分析系统
  7. UISwitch详解
  8. 手机版wps怎么制作折线图_头像制作软件手机版下载-头像制作免费软件带字体下载app...
  9. excel简繁切换_excel简繁转换_EXCEL中的“中文简繁转换”按钮不见了!
  10. photoshop抠图场景二
  11. 并发编程之四:并发之共享问题、线程安全、synchronized关键字
  12. 科罗拉多州立大学计算机科学,2020年科罗拉多州立大学排名TFE Times美国最佳计算机科学硕士专业排名第81...
  13. python_绘制玫瑰图_南丁格尔图
  14. IT项目管理那些事儿读书笔记
  15. 【MySQL】--架构简介
  16. rowid与rownum的含义是什么?
  17. 直流无刷电机发热问题及解决方案
  18. PythonOCC封装:2.重新封装pythonocc
  19. 抽取文本数据(TSV文件的抽取)
  20. Not in GZIP format异常

热门文章

  1. 中文分词:原理及分词算法
  2. 如何下载tomcat历史版本
  3. jQuery源码解析(架构与依赖模块)
  4. java md5库_Java常用类库API之MD5简单使用
  5. 墨者Bash漏洞分析溯源题解
  6. Git中的vim命令
  7. Sublime Text 3 配置python开发环境遇见的问题
  8. XML常见的两种解析方式总结
  9. 【Java应用】使用Java实现机器学习算法:聚类、分类、预测
  10. 2021年北航计算机学院夏令营面试经历