欢迎访问我的新博客:http://www.milkcu.com/blog/
原文地址:http://www.milkcu.com/blog/archives/pointer-manipulation.html
原创:C语言指针操作
作者:MilkCu
摘要:指针是C语言的核心,也是一个普通变量,存储的是内存中的地址。在存储空间的分配中,一种常遵循的理念是,由用户管理存储空间以及与存储空间相关的实际的数据结构,而数据结构自身只用于维护数据内部变量的存储空间的分配。C语言使用基于堆的内存分配,通常也称作动态存储分配。
指针基础
一个指针其实只是一个变量,它存储数据在内存中的地址,而不是存储数据本身。
可能产生悬空指针的一些编程错误事例包括:
将任意的整型变量强制转换为指针变量;
操作超出数组边界的指针;
释放一个或多个仍被引用的指针。
存储空间分配
通常情况下,指针会占用一个机器字长的存储空间,但有些时候它们的大小也有所不同。
用malloc分配的存储空间会一直有效,知道调用函数free来释放它。
内存泄露问题的产生是由于动态分配了内存空间,但从未释放它造成的。特别是在重复执行代码时,这种泄露问题会表现得尤为重要。
一种统一的内存管理方法所遵循的理念是,由用户管理存储空间以及与存储空间相关的实际的数据结构,而数据结构自身只用于维护数据内部变量的存储空间的分配。所以,在数据结构中,只使用指针指向数据变量,而不是此数据的私有副本。
数据集合与指针的算术运算
指针在C语言中最长见的用途就是用来引用数据集合。C语言支持两种数据集合:结构和数组。
结构不允许包含自身的实例,但可以包含指向自身实例的指针。
当一个数组标识符在表达式中出现时,C语言会把数组转换为一个指向数组第一个元素的指针。
在C语言中,多为数组其实是以行主序的方式存储的,这也就说明多维数组右边下表变化速度要比左边下标变化来的更快。
二维数组第i行第j列的元素,用a[i][j]表示,等价于((a + i) + j)。
作为函数参数的指针
当把一个多维数组传递给函数时,除了第一维以外其他维的长度必须指定。
泛型指针与类型转换
泛型指针不指定具体的数据类型。可以使用泛型指针实现交换任何类型数据的通用交换函数。
#include <stdio.h>
#include <stdlib.h>
#include <string.h> int swap2(void *x, void *y, int size)
{
void * tmp;
if((tmp = malloc(size)) == NULL) {
return -1;
}
memcpy(tmp, x, size);
memcpy(x, y, size);
memcpy(y, tmp, size);
free(tmp);
return 0;
} int main(void)
{
int a = 2;
int b = 3;
swap2(&a, &b, sizeof(int));
printf("a = %d\nb = %d\n", a, b);
return 0;
}
地址取到什么类型的值是由我们用什么类型的指针访问它所决定的。
函数指针
声明函数指针看起来与声明一个函数非常相似,只是在函数名前有一个表示指针的星号,并且函数名和星号会用圆括号括起来。
函数指针的一个重要用途是将函数封装到数据结构中,它可以使数据结构或函数变得更具通用性。
基于堆的内存分配
C语言使用基于堆的内存分配,通常也称作动态存储分配。它允许一个程序在运行时请求更多所需要的内存,而不是在编译时就分配固定数额的内存。
(全文完)
本文地址:http://www.milkcu.com/blog/archives/pointer-manipulation.html