【C语言】学不会的指针
指针
前言:
指针是C语言程序的核心,刚开始学指针,嗯....这样呀,貌似不难呀;之后开始用指针,&p,p,*p,**p,这些指针在用的时候,额.....什么东东?每次都要想半天,特别是遇到双重指针,脑子直接卡住;
什么是指针?
指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。
指针内在的关联
#include <stdio.h> int main()
{
int a;
int *p;
a = 1;
p = &a; printf("变量a的内存地址是:0x%X \n",&a);
printf("变量a存储的值:%d \n",a);
printf("指针p的内存地址是:0x%X \n",&p);
printf("指针p存储的地址是:0x%X \n",p);
printf("指针p指向地址的值:%d \n",*p);
}
执行输出
变量a的内存地址是:0x24FE4C
变量a存储的值:1
指针p的内存地址是:0x24FE40
指针p存储的地址是:0x24FE4C
指针p指向地址的值:1
能把上面代码理解,那么指针基础内容也就掌握了;首先int a;a=1; 声明一个int类型。声明一个变量就相当于申请一段存储空间,一个存储空间你要让我想办法找到它,好吧就给你一个起始地址(因为一段存储空间不止一位,所以给存储的起始地址来索引)。这个地址就是一个数字,假设我们这里的数字是0x24FE4C,这个数字就是a的内存地址;这块存储空间占用4个字节(int类型是4字节),而且存储的值为1。

int *p; 就是声明一个指针变量, 存储的是一个地址,也可以说存储一个数字,这个数字代表计算机中存储器的位置。
p=&a; &a就是取a的地址(起始地址),a的起始地址是0x24FE4C,然后我们把这个数字赋值给p变量,现在p的值就是0x24FE4C。当然p是一段存储空间,它的地址是0x24FE40。

#include <stdio.h> int main()
{
int a;
int *p;
int b;
a = 1;
p = &a; *p = 10;
printf("变量a存储的值:%d \n",a);
printf("变量a的内存地址是:0x%X \n",&a);
} //变量a存储的值:10
//变量a的内存地址是:0x24FE44
很显然赋值可以生效,而且变量a的内存地址也进行了更改
点击=》指针的指针
空指针
在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯。赋为 NULL 值的指针被称为空指针。
NULL 指针是一个定义在标准库中的值为零的常量。请看下面的程序:
#include <stdio.h> int main ()
{
int *ptr = NULL; printf("ptr 的地址是 %p\n", ptr ); return 0;
} //ptr 的地址是 0000000000000000
在大多数的操作系统上,程序不允许访问地址为 0 的内存,因为该内存是操作系统保留的。然而,内存地址 0 有特别重要的意义,它表明该指针不指向一个可访问的内存位置。但按照惯例,如果指针包含空值(零值),则假定它不指向任何东西。
如需检查一个空指针,您可以使用 if 语句,如下所示:
if(ptr) /* 如果 p 非空,则完成 */
if(!ptr) /* 如果 p 为空,则完成 */
传递指针给函数
C 语言允许您传递指针给函数,只需要简单地声明函数参数为指针类型即可。
下面的实例中,我们传递一个无符号的 long 型指针给函数,并在函数内改变这个值:
#include <stdio.h>
#include <time.h> void getSeconds(unsigned long *par); int main ()
{
unsigned long sec; getSeconds( &sec ); /* 输出实际值 */
printf("Number of seconds: %ld\n", sec ); return 0;
} void getSeconds(unsigned long *par)
{
/* 获取当前的秒数 */
*par = time( NULL );
return;
} //Number of seconds: 1563865435
能接受指针作为参数的函数,也能接受数组作为参数,如下所示:
#include <stdio.h> /* 函数声明 */
double getAverage(int *arr, int size); int main ()
{
/* 带有 5 个元素的整型数组 */
int balance[5] = {1000, 2, 3, 17, 50};
double avg; /* 传递一个指向数组的指针作为参数 */
avg = getAverage( balance, 5 ) ; /* 输出返回值 */
printf("Average value is: %f\n", avg ); return 0;
} double getAverage(int *arr, int size)
{
int i, sum = 0;
double avg; for (i = 0; i < size; ++i)
{
sum += arr[i];
} avg = (double)sum / size; return avg;
} //Average value is: 214.400000
int func(int *p) 在函数中,此时的p表示一个内存地址,*p表示内存地址的值 记住!!
【C语言】学不会的指针的更多相关文章
- Swift3.0语言教程使用指针创建和初始化字符串
Swift3.0语言教程使用指针创建和初始化字符串 Swift3.0语言教程使用指针创建和初始化字符串苹果的Swift团队花了不少功夫来支持C的一些基础特性.C语言中为我们提供了指针,Swift也不例 ...
- C语言中的指针数组
C语言中的指针数组是什么,像 char *a[]={"ddd","dsidd","lll"}; 这里讲一下注意如果我们使用了a也就是首元素的 ...
- 【ZZ】C 语言中的指针和内存泄漏 & 编写高效的C程序与C代码优化
C 语言中的指针和内存泄漏 http://www.ibm.com/developerworks/cn/aix/library/au-toughgame/ 本文讨论了几种在使用动态内存分配时可以避免的陷 ...
- GO语言中的指针
http://www.tizgrape.com/?p=100 Go语言中的指针语法和C++一脉相承,都是用*作为符号,虽然语法上接近,但是实际差异不小. Go使用var定义变量: var v6 *in ...
- 由链表初始化看C语言的二级指针
先来看C语言创建链表.插入节点和遍历链表的一段代码: #include <stdio.h> #include <stdlib.h> typedef int ElemType; ...
- C语言 > 数组和指针
C语言 数组和指针 const: 关于指针和const需要注意一些规则.首先,把const数据或非const数据的地址初始化为指向const的指针或为其赋值是合法的. 然而,只能把非const数据的地 ...
- C语言结构体指针的引用问题
在写栈的一个应用时遇见这样的一个问题 SqStack s; s->base = (int*)malloc(sizeof(int)*10); 通过这样一个代码引用的时候,会导致程序出现异常 经过一 ...
- Go语言基础之指针
区别于C/C++中的指针,Go语言中的指针不能进行偏移和运算,是安全指针. 要搞明白Go语言中的指针需要先知道3个概念:指针地址.指针类型和指针取值. Go语言中的指针 Go语言中的函数传参都是值拷贝 ...
- c语言之函数指针应用
c语言之函数指针应用 1.函数指针与指针函数 在开始运用函数指针前,我们需要将两个概念即:函数指针与指针函数搞清楚. 函数指针,指明这个一个函数,但返回值为指针类型,语法格式为: 类型名* 函数名A( ...
- C语言中的指针笔记
C语言指针 得到变量的地址 可以使用&运算符找到变量保存在内存中的位置 int x = 1; printf("x的内存地址是"%p\n",&x) %p格式 ...
随机推荐
- kuma kong 团队开发的可视化&&安全的service mesh
最近service mesh 的开源产品是越来越多了,好多团队都开源了自己的解决方案 maesh 最近kong 团队也开源了自己的service meshkuma 一张参考图 说明 kuma 没有基于 ...
- Nginx+Php-fpm运行原理 代理与反向代理
一.代理与反向代理 现实生活中的例子 1.正向代理:访问google.com 如上图,因为google被墙,我们需要vpnFQ才能访问google.com.Virtual Private Networ ...
- linux命令之------rm命令
rm命令 1) 作用:用于删除一个文件或者目录: 2) -i:删除前逐一询问确认: 3) -f:即使原档案属性设为只读,亦直接删除,无需逐一确认: 4)-r:将目录及以下之档案亦逐一 ...
- 【转】Impala 中的 Invalidate Metadata 和 Refresh
前言Impala采用了比较奇葩的多个impalad同时提供服务的方式,并且它会由catalogd缓存全部元数据,再通过statestored完成每一次的元数据的更新到impalad节点上,Impala ...
- 从工厂流水线小妹到Google上班程序媛,看完后,我跪服了!
阅读本文大概需要 10.2 分钟. 文作者:Ling Sun 原文链接:https://www.zhihu.com/question/68154951/answer/546265013 我家境很不好, ...
- Linux中git用https连接时不用每次输入密码
应用场景: 比如每天凌晨执行crontab对应的项目部署脚本(使用git作为项目的版本控制). 如果不这样做会怎么样? 每次部署都要git clone并输入对应的用户名和密码,需要人工.这样就显得很不 ...
- [技术博客] rails控制台调试路由
目录 rails console 获得路由 app.xxx_path 发送请求 获得响应 作者:庄廓然 rails console 在项目目录下执行rails console test 可以进入测试模 ...
- leetcode:146. LRU缓存机制
题目描述: 运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制.它应该支持以下操作: 获取数据 get 和 写入数据 put . 获取数据 get(key) - 如果密钥 ( ...
- mysql插入数据报错IntegrityError: (1062, "Duplicate entry 'xx' for key 'xxxxx'")
1.问题描述 MySQL插入数据的时候报错,提示如下: IntegrityError: (1062, "Duplicate entry 'xx' for key 'xxxxx'") ...
- java多线程(三)线程的安全问题
1.1. 什么是线程安全 如果有多个线程同时运行同一个实现了Runnable接口的类,程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的:反之,则是线程不 ...