找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2111|回复: 0
收起左侧

函数指针

[复制链接]
ID:77367 发表于 2015-4-18 20:37 | 显示全部楼层 |阅读模式
函数指针
定义  void (*FunP)(int) ;   //也可以写成 void (*FunP)(int x);
   就象某一数据变量的内存地址可以存储在相应的指针变量中一样,函数的首地址也以存储在某个函数指针变量里的。这样,我就可以通过这个函数指针变量来调用所指向的函数了。

1、C语言面向对象的实现
libvirt是Linux下的一个虚拟化管理API库,里面用到很多这样的东东。。。。

2、qsort函数
qsort包含在<stdlib.h>头文件中,此函数根据你给的比较条件进行快速排序,通过指针移动实现排序。排序之后的结果仍然放在原数组中。使用qsort函数必须自己写一个比较函数compar。
int compar (const void* p1, const void* p2);
函数原型:
void qsort (void* base, size_t num, size_t size,            int (*compar)(const void*,const void*));
该函数第三个参数就是一个函数指针。。
#include <stdio.h>
#include <stdlib.h>

int values[] = { 40, 10, 100, 90, 20, 25 };

int compare (const void * a, const void * b)   // 升序排列
{
        return ( *(int*)a - *(int*)b );
}

int main(int argc, char *argv[])
{
        int n;
        qsort (values, 6, sizeof(int), compare);
        for (n=0; n<6; n++)
                printf ("%d ",values[n]);

        getchar();
        return 0;
}

3、打印函数值,使用函数指针

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

/* tabulates values of trigonometric functions */
void tabulate(double (*f)(double), double first, double last, double inc)
{
        double x;
        int i, num_intervals;
        num_intervals = ceil((last - first)/inc);
        for (i = 0; i<=num_intervals; i++)
        {
                x = first + i*inc;
                printf("%10.5f %10.5f\n", x, (*f)(x));
        }
}

int main(int argc, char *argv[])
{
        double initial = 0.0f,
                final = 1.0f,
                inc = 0.05f;
        printf("\n      x        cos(x)\n");
        tabulate(cos, initial, final, inc);
        getchar();
        return 0;
}





数组指针
定义 int (*p)[n];
()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度
如要将二维数组赋给一指针,应这样赋值:
int a[4][6];
int (*p)[6];    //该语句是定义一个数组指针,指向的类型是包含4个元素的一维数组。
p=a;           //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]
p++;            //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]
所以数组指针也称指向一维数组的指针,亦称行指针。

===============例子==============================

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int a[4][6];
int (*p)[6];

p = a;           // 数组指针指向二维数组

// a数组元素可用以下五种表达式来引用:
// (1)a[j](2)*(a+j) (3)*(*(a+i)+j)(4)(*(a+i))[j](5)*(&a[0][0]+4*i+j)
*(*(p+1)+2) = 4;
// 此处加断点


return 0;
}





指针数组
定义 int *p[n];
[]优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组,它有n个指针类型的数组元素。这里执行p+1是错误的,这样赋值也是错误的:p=a;因为p是个不可知的表示,只存在p[0]、p[1]、p[2]...p[n-1],而且它们分别是指针变量可以用来存放变量地址。但可以这样 *p=a; 这里*p表示指针数组第一个元素的值,a的首地址的值。
如要将二维数组赋给一指针数组:
int *p[3];
int a[3][4];
for(i=0;i<3;i++)
p=a;
这里int *p[3] 表示一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2]
所以要分别赋值。
这样两者的区别就豁然开朗了,数组指针只是一个指针变量,似乎是C语言里专门用来指向二维数组的,它占有内存中一个指针的存储空间。指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的存储空间。
还需要说明的一点就是,同时用来指向二维数组时,其引用和用数组名引用都是一样的。
比如要表示数组中i行j列一个元素:
*(p+j)、*(*(p+i)+j)、(*(p+i))[j]、p[j]

优先级:()>[]>*



指针函数
指针函数是指带指针的函数,即本质是一个函数。函数返回类型是某一类型的指针
     类型标识符    *函数名(参数表)
      int *f(x,y);
首先它是一个函数,只不过这个函数的返回值是一个地址值。函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有函数返回值,而且,在主调函数中,函数返回值必须赋给同类型的指针变量。



使用二维指针 ,计算图像数据的平均值(删减)

// Raw video process class  header file
//
#pragma once
#include "KMemDataStream.h"

// 处理数据流
class Rprocess : KMemDataStream
{
public:
Rprocess(void* pMem, size_t size/* 数据缓存大小 */, bool freeOnClose = false);
Rprocess(size_t size/* 数据缓存大小 */, bool freeOnClose = false);// Create a memory stream
~Rprocess(void);
void CommInit();
        // other code
// 处理过程
void process();
protected:
// Multi-frame average
void MFA_ImageAdd8(BYTE *pData/* in */, BYTE* pResult/* out */, int w, int h, int stride);

private:
int m_nWidth;
int m_nHeight;
int m_bitcount;

BYTE **val;   // 图像缓存,用于帧平均法设计
int m,  // m个缓存指针
n;        // 每个指针指向的长度1024*576
BYTE *m_ptmp; // 指向初始的val[0]地址,只是用于释放内存,因为程序的运行过程,val地址被反复交换,释放内存的时候造成bug

void allocateMemory (const int m_,const int n_);
void releaseMemory ();

};

//=========================实现文件==================================
#include "StdAfx.h"
#include "Rprocess.h"

#define _N_num  4
#define _Buf_length  589824   

Rprocess::Rprocess(void* pMem, size_t size, bool freeOnClose/* = false*/) : KMemDataStream(pMem, size, freeOnClose)
{
m_pImage = (BYTE *)m_lpData;
CommInit();
}

Rprocess::Rprocess(size_t size, bool freeOnClose /*= false*/) : KMemDataStream(size, freeOnClose)
{
m_pImage = (BYTE *)m_lpData;
CommInit();
}


Rprocess::~Rprocess(void)
{
releaseMemory();
}

void Rprocess::CommInit()
{
m_nWidth = 1024;
m_nHeight = 576;
m_bitcount = 8;
m = 0;
n = 0;
val = 0;

allocateMemory(_N_num, _Buf_length);
}

//////////////////////////////////////////////////////////////////////////
// 处理8位灰度图像, 该程序需要很大的优化。。。。。
void Rprocess::process()
{
//other code
BYTE *image = (BYTE *)GetBits();

//各级长宽
int* pnMatrixInfo = new int[(nLevel+2)*3];
pnMatrixInfo[0] = nLevel;
pnMatrixInfo[1] = GetWidth() ;   //w
pnMatrixInfo[2] = GetHeight() ; //h
pnMatrixInfo[3] = GetPitch();    //stride

//灰度内存块
BYTE *pPixelsGrey = new BYTE[pnMatrixInfo[2] * pnMatrixInfo[3]];
       // 取图像的平均值
MFA_ImageAdd8(image, pPixelsGrey, pnMatrixInfo[1], pnMatrixInfo[2], pnMatrixInfo[3]);

delete pPixelsGrey;
}

// 功能:帧平均算法
// 参数:
//pData 要添加的新的数据帧
//pResult 返回的平均值
void Rprocess::MFA_ImageAdd8(BYTE *pData/* in */, BYTE* pResult/* out */, int w, int h, int stride)
{
int pixelByte8 = 1 ;
BYTE* _pixels_R = pResult;
int _strideoff = stride - pixelByte8  * w;
unsigned short _letf=0;
unsigned short _top=0;
unsigned short _right = w;
unsigned short _bottom = h;

// 将pData添加到val缓冲区,m=4

BYTE *tmp = val[0];// 纪录val[0]的地址, 并且向里面复制数据
memcpy(tmp, pData, n*sizeof(BYTE));  

for (int i = 1; i < m; i++)   // i=1,2,3 指针前移
{
val[i-1] = val;
}
val[m-1] = tmp;//

// 计算平均值
int x, y;
int k = 0;
for(y = _top; y < _bottom; y++)
{
for(x = _letf; x < _right; x++)
{
int nResult = 0;
// 取出平均值过来
for (int j = 0; j < m; ++j)  // 0 1 2 3
{
//int i = y*stride + x;
//ASSERT(i <= n);
nResult += val[j][k];   // 这句话有语病
}

nResult = nResult / m;  
*_pixels_R = (BYTE)nResult;
k++;

_pixels_R++;
}
_pixels_R += _strideoff;
k += _strideoff;
}

return;
}

void Rprocess::allocateMemory (const int m_,const int n_)
{
TRACE2("allocate memory, m=%d, n=%d\n\n", m_, n_);

m = abs(m_); n = abs(n_);
if (m == 0 || n == 0) {
val = 0;
return;
}
val    = (BYTE **)malloc(m*sizeof(BYTE*));
val[0] = (BYTE*)calloc(m*n,sizeof(BYTE));
memcpy(val[0], m_pImage, n*sizeof(BYTE));        // copy data to buffer
m_ptmp = val[0];// 释放标志

for(int i=1; i<m; i++)
{
val = val[i-1] + n;
ASSERT(val);
memcpy(val, m_pImage, n*sizeof(BYTE));// 用初始的图像填充开辟的缓冲区
}
}

void Rprocess::releaseMemory ()
{
if (val != 0 ) {
//free(val[0]);    // 出现偶然bug
free(m_ptmp);
free(val);
val = 0;
}
}





回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表