指针进阶(二)

(1)指针就是地址,也就是说在某一位数确定的操作系统中,他的范围是可以确定的,就是说指针变量的sizeof值是相等的。

比如32位系统下,不管是指向char、int、还是long型变量的指针,他的大小都是4字节

(2)sizeof是关键字,求值是发生在编译的时候,他不同于函数,因为函数的求值是发生在运行的时候。且看:

int ch[6];

sizeof(ch[6]);//是存在的,值为4,编译是不会报错的

(3)数组int a[5];的&a和a代表的含义

&a:是数组a的起始地址,那么&a+1是指向下一个数组即指向了元素a[5],不是下一个元素a[1]哦

a:是数组第一个元素a[0]的地址,它相当于&a[0]

#include <stdio.h>
#include <string.h>
int main()
{
	int a[5]={1,2,3,4,5};
	int *ptr=(int *)(&a+1);//相当于ptr=a+sizeof(int)*5
	printf("\n*(a+1)=%d   *(&a[0]+1)=%d    *(ptr-1)=%d\n\n",*(a+1),*(&a[0]+1),*(ptr-1));
}

运行结果:

*(a+1)=2   *(&a[0]+1)=2    *(ptr-1)=5

(4)定义为数组声明为指针

先看个例子:

file1.c

#include <stdio.h>
char table[20]="ABCDEF";
void Display_TabAddr(void)
{
	printf("file1:table_addr = 0x%x\n",table);
}

file2.c

#include <stdio.h>
extern char *table;
extern void Display_TabAddr(void);

int main()
{
	Display_TabAddr();
	printf("file2:table_addr = 0x%x\n",table);
	return 0;
}

运行结果:

file1:table = 0x424a30     -->  这才是table数组的真实地址

file2:table = 0x44434241   -->  0x44 0x43 0x42 0x41的意思难道和table[]里边的"D","C","B","A"有关系???

Press any key to continue

结果分析:

①在file2.c中的table是一个指向char型的指针变量,他占有4字节的存储空间,并且extern表明他在其他文件定义,于是编译器就去工程文件中找啊找

终于在file1.c文件中找到了一个table,于是就把table里边前4个字节的值拿出来当做地址使用,这结果为什么这么牵强的?想不懂!

②在file1.c中table是一个数组,实际大小为20字节

(5)定义为指针声明为数组

file1.c

#include <stdio.h>
char *pointer="ABCDEF";
void Display_PointerAddr(void)
{
	printf("file1:*(pointer+1) = %c\n",*(pointer+1));
	printf("file1:pointer_addr = 0x%x\n",p);
}

file2.c

#include <stdio.h>
extern char pointer[];
extern void Display_PointerAddr(void);
int main()
{
	Display_PointerAddr();
	printf("file2:pointer[0] = 0x%x\n",pointer[0]);
	printf("file2:pointer[1] = 0x%x\n",pointer[1]);
	printf("file2:pointer[2] = 0x%x\n",pointer[2]);
	return 0;
}

运行结果:

file1:*(pointer+1) = B
file1:pointer_addr = 0x422064
file2:pointer[0] = 0x64
file2:pointer[1] = 0x20
file2:pointer[2] = 0x42
Press any key to continue

结果分析:

在file2.c中编译器把file1.c中的char型指针变量pointer当做是长度为4字节的char型数组,file1.c中pointer存放的是地址内容,于是file1.c中就把这个地址内容当做数组的值来使用了。究竟为什么会这样做,实在不懂其中的原理,只能通过这种现象来记住这种结论。

(4)和(5)编程小结:以后遇到这两种情况时千万不要定义了数组和指针中的一种,然后在另外的文件中extern声明为另外一种类型

(6)变量用作右值时,编译器只取其变量值,不关心类型,但有些隐式类型转换会有warming

(7)指针变量用作数组名时,下标为负号的问题

int tab[5];

int *p=&a+1;

p[-1]会被编译器解释成*(p-1),也就指向了tab[4]

(8)结构体成员是“指针”时一定要记得先初始化让他有个明确的指向后才能进行“赋值”操作!!!对于指针变量在定义时如果还不知道其指向最好用NULL拴住他,免得成为野指针!

(9)char *p=(char *)malloc(0);malloc函数返回的内存里边的一个地址,不是NULL,但是这个地址是不能用的。这好比尺子上的某个刻度,刻度本身并没有长度,只有某两个刻度一起才能量出长度。

(10)free(p)之后p的指向并没有发生改变,指向的内容也没有改变。在visual c++6.0中free之后的这个指针变量任然可以拿来使用,

看个例子:

#include <stdio.h>
#include <stdlib.h>
void my_mallloc(void)
{
	char *p2 = (char *)malloc(1);
	printf("\nafter free p1--in my_malloc:\np2=%d\n",p2);
	printf("(*p2) = %d\n\n",*p2);
}
int main()
{
	char *p1=(char *)malloc(1);
	printf("\nbefore free p1:\np1=%d\n\n",p1);
	free(p1);
	*p1 = 123;
	printf("after free p1:\n(*p1) = %d\n",*p1);
	printf("p1 = %d\n",p1);

	my_mallloc();

	return 0;
}

运行结果:

before free p1:
p1=8266296

after free p1:
(*p1) = 123
p1 = 8266296

after free p1--in my_malloc:
p2=8266296
(*p2) = -51

Press any key to continue

结果分析:从运行的结果分析可知,在my_malloc函数中定义的指针变量p2和main里边的p1指向是一样的。只是从编程的逻辑上不允许这样做,因为你既然都要free他就是之后不要用到这个内存的意思,之后为了防止吴用free(p1)之后也要将p1用NULL来拴住。

时间: 2024-11-08 07:42:35

指针进阶(二)的相关文章

Python爬虫进阶二之PySpider框架安装配置

关于 首先,在此附上项目的地址,以及官方文档 PySpider 官方文档 安装 1. pip 首先确保你已经安装了pip,若没有安装,请参照 pip安装 2. phantomjs PhantomJS 是一个基于 WebKit 的服务器端 JavaScript API.它全面支持web而不需浏览器支持,其快速.原生支持各种Web标准:DOM 处理.CSS 选择器.JSON.Canvas 和 SVG. PhantomJS 可以用于页面自动化.网络监测.网页截屏以及无界面测试等. 安装 以上附有官方安

二级指针与二维数组

最近看<Linux C程序设计大全>这本书,虽然书中有一些错误,但整体来说,书写得还算可以. 当看到网络编程[第23.2.4小节 获得主机信息]时,遇到了一段代码,原文如下: “一台主机有许多和网络相关的信息,例如,主机名称.IP地址.主机提供的服务等.这些信息一般都保存在系统中的某个文件里(例如/etc/hosts等),用户程序可以通过系统提供的函数读取这些文件上的内容.Linux环境下使用gethostent函数读取和主机有关的信息,该函数的原型如下: 1 #include <net

2、蛤蟆的数据结构进阶二静态查询之顺序查询

2.蛤蟆的数据结构进阶二静态查询之顺序查询 本篇名言:"我从不把安逸和快乐看作是生活的本身 --这种伦理基础,我叫它猪栏的理想. --爱因斯坦" 这篇我们来看下静态查询中的顺序表查询. 我们先来看下概念,然后是代码实现. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47175103 1.  查找 在计算机科学中定义为:在一些(有序的/无序的)数据元素中,通过一定的方法找出与给定关键字相同的数据元素的过程叫做查找.

指针与二维数组间的关系

1.四种表示a[i][j]的形式是等价的: a[i][j]==*(a[i]+j)==*(*(a+i)+j)==(*(a+i))[j] 2.通过行指针p引用二维数组a的元素a[i][j]的方法可用以下4种等价形式: p[i][j]==*(p[i]+j)==*(*(p+i)+j)==(*(p+i))[j] 3.对指向二维数组的行指针p进行初始化的方法: p=a 或p=&a[0] 4.对指向二维数组的列指针进行初始化的方法(以下三种方法等价): p=a[0] 或 p=*a 或 p=&a[0][0

Android架构分析之Android智能指针(二)

作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android版本:4.4.2 在上一篇文章中,我们分析了Android智能指针中的强指针sp,本文我们来分析弱指针wp.为什么需要弱指针wp呢?我们来考虑下面一种场景:有两个类CParent和CChild,CParent类中有一个智能指针指向CChild对象,CChild类中有一个智能指针指向CParent对象 class CParent :public LightRefBase<CParent> { --

例看二维数组,指针,二维数组指针

例程: /****************************************************** * * 文件名:例程 * * 文件描述:例看二维数组,指针,二维数组指针 * * 创建人:Jesse * * 版本号: * * 修改记录: * ******************************************************/ #include <stdio.h> #define ROW 3 #define LINE 3 void main(voi

Android进阶(二十八)上下文菜单ContextMenu使用案例

上下文菜单ContextMenu使用案例 前言 回顾之前的应用程序,发现之前创建的选项菜单无法显示了.按照正常逻辑来说,左图中在"商品信息"一栏中应该存在选项菜单,用户可进行分享等操作,但是现在此操作莫名其妙的消失了.写了个测试Demo,如中图所示,一切按照逻辑显示正常.怪就怪在项目中无法显示,起初设想是因为Android系统版本太高问题,但是在别的手机上测试之后发现问题依旧存在.难道是因为顶部Tab标题栏遮挡住了选项菜单的显示?继续测试,通过在别的没有Tab标题栏的页面测试选项菜单,

Java进阶(二十五)Java连接mysql数据库(底层实现)

Java进阶(二十五)Java连接mysql数据库(底层实现) 前言 很长时间没有系统的使用java做项目了.现在需要使用java完成一个实验,其中涉及到java连接数据库.让自己来写,记忆中已无从搜索.特将之前使用的方法做一简单的总结.也能够在底层理解一下连接数据库的具体步骤. 实现 首先需要导入相关的jar包,我使用的为:mysql-connector-java-5.1.7-bin.jar. 下面来看一下我所使用的数据库连接方法类: MysqlUtil.java package cn.edu

分布式进阶(二)Ubuntu 14.04下安装Dockr图文教程(一)

当前,完全硬件虚拟化技术(KVM.Xen.Hyper-V 等)能在一个物理主机上很好地运行多个互相独立的操作系统,但这也带来一些问题:性能不佳,资源浪费,系统反应迟缓等.有时候对用户来说,完全的硬件虚拟化并不是最好的选择. 一种替代方案是使用轻量级虚拟化技术 -- 所谓的 LinuX Container 容器 (LXC),它提供的是系统级虚拟化.与跑虚拟机相比,LXC 可以在一个轻量级沙箱容器里面跑多个 Linux 操作系统.当你需要设置一些易于克隆的开发环境.测试环境,或想在安全沙盒里安装应用