找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 2443|回復(fù): 0
收起左側(cè)

函數(shù)指針

[復(fù)制鏈接]
ID:77367 發(fā)表于 2015-4-18 20:37 | 顯示全部樓層 |閱讀模式
函數(shù)指針
定義  void (*FunP)(int) ;   //也可以寫成 void (*FunP)(int x);
   就象某一數(shù)據(jù)變量的內(nèi)存地址可以存儲(chǔ)在相應(yīng)的指針變量中一樣,函數(shù)的首地址也以存儲(chǔ)在某個(gè)函數(shù)指針變量里的。這樣,我就可以通過(guò)這個(gè)函數(shù)指針變量來(lái)調(diào)用所指向的函數(shù)了。

1、C語(yǔ)言面向?qū)ο蟮膶?shí)現(xiàn)
libvirt是Linux下的一個(gè)虛擬化管理API庫(kù),里面用到很多這樣的東東。。。。

2、qsort函數(shù)
qsort包含在<stdlib.h>頭文件中,此函數(shù)根據(jù)你給的比較條件進(jìn)行快速排序,通過(guò)指針移動(dòng)實(shí)現(xiàn)排序。排序之后的結(jié)果仍然放在原數(shù)組中。使用qsort函數(shù)必須自己寫一個(gè)比較函數(shù)compar。
int compar (const void* p1, const void* p2);
函數(shù)原型:
void qsort (void* base, size_t num, size_t size,            int (*compar)(const void*,const void*));
該函數(shù)第三個(gè)參數(shù)就是一個(gè)函數(shù)指針。。
#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、打印函數(shù)值,使用函數(shù)指針

#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;
}





數(shù)組指針
定義 int (*p)[n];
()優(yōu)先級(jí)高,首先說(shuō)明p是一個(gè)指針,指向一個(gè)整型的一維數(shù)組,這個(gè)一維數(shù)組的長(zhǎng)度是n,也可以說(shuō)是p的步長(zhǎng)。也就是說(shuō)執(zhí)行p+1時(shí),p要跨過(guò)n個(gè)整型數(shù)據(jù)的長(zhǎng)度。
如要將二維數(shù)組賦給一指針,應(yīng)這樣賦值:
int a[4][6];
int (*p)[6];    //該語(yǔ)句是定義一個(gè)數(shù)組指針,指向的類型是包含4個(gè)元素的一維數(shù)組。
p=a;           //將該二維數(shù)組的首地址賦給p,也就是a[0]或&a[0][0]
p++;            //該語(yǔ)句執(zhí)行過(guò)后,也就是p=p+1;p跨過(guò)行a[0][]指向了行a[1][]
所以數(shù)組指針也稱指向一維數(shù)組的指針,亦稱行指針。

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

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

p = a;           // 數(shù)組指針指向二維數(shù)組

// a數(shù)組元素可用以下五種表達(dá)式來(lái)引用:
// (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;
// 此處加斷點(diǎn)


return 0;
}





指針數(shù)組
定義 int *p[n];
[]優(yōu)先級(jí)高,先與p結(jié)合成為一個(gè)數(shù)組,再由int*說(shuō)明這是一個(gè)整型指針數(shù)組,它有n個(gè)指針類型的數(shù)組元素。這里執(zhí)行p+1是錯(cuò)誤的,這樣賦值也是錯(cuò)誤的:p=a;因?yàn)閜是個(gè)不可知的表示,只存在p[0]、p[1]、p[2]...p[n-1],而且它們分別是指針變量可以用來(lái)存放變量地址。但可以這樣 *p=a; 這里*p表示指針數(shù)組第一個(gè)元素的值,a的首地址的值。
如要將二維數(shù)組賦給一指針數(shù)組:
int *p[3];
int a[3][4];
for(i=0;i<3;i++)
p=a;
這里int *p[3] 表示一個(gè)一維數(shù)組內(nèi)存放著三個(gè)指針變量,分別是p[0]、p[1]、p[2]
所以要分別賦值。
這樣兩者的區(qū)別就豁然開朗了,數(shù)組指針只是一個(gè)指針變量,似乎是C語(yǔ)言里專門用來(lái)指向二維數(shù)組的,它占有內(nèi)存中一個(gè)指針的存儲(chǔ)空間。指針數(shù)組是多個(gè)指針變量,以數(shù)組形式存在內(nèi)存當(dāng)中,占有多個(gè)指針的存儲(chǔ)空間。
還需要說(shuō)明的一點(diǎn)就是,同時(shí)用來(lái)指向二維數(shù)組時(shí),其引用和用數(shù)組名引用都是一樣的。
比如要表示數(shù)組中i行j列一個(gè)元素:
*(p+j)、*(*(p+i)+j)、(*(p+i))[j]、p[j]

優(yōu)先級(jí):()>[]>*



指針函數(shù)
指針函數(shù)是指帶指針的函數(shù),即本質(zhì)是一個(gè)函數(shù)。函數(shù)返回類型是某一類型的指針
     類型標(biāo)識(shí)符    *函數(shù)名(參數(shù)表)
      int *f(x,y);
首先它是一個(gè)函數(shù),只不過(guò)這個(gè)函數(shù)的返回值是一個(gè)地址值。函數(shù)返回值必須用同類型的指針變量來(lái)接受,也就是說(shuō),指針函數(shù)一定有函數(shù)返回值,而且,在主調(diào)函數(shù)中,函數(shù)返回值必須賦給同類型的指針變量。



使用二維指針 ,計(jì)算圖像數(shù)據(jù)的平均值(刪減)

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

// 處理數(shù)據(jù)流
class Rprocess : KMemDataStream
{
public:
Rprocess(void* pMem, size_t size/* 數(shù)據(jù)緩存大小 */, bool freeOnClose = false);
Rprocess(size_t size/* 數(shù)據(jù)緩存大小 */, bool freeOnClose = false);// Create a memory stream
~Rprocess(void);
void CommInit();
        // other code
// 處理過(guò)程
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;   // 圖像緩存,用于幀平均法設(shè)計(jì)
int m,  // m個(gè)緩存指針
n;        // 每個(gè)指針指向的長(zhǎng)度1024*576
BYTE *m_ptmp; // 指向初始的val[0]地址,只是用于釋放內(nèi)存,因?yàn)槌绦虻倪\(yùn)行過(guò)程,val地址被反復(fù)交換,釋放內(nèi)存的時(shí)候造成bug

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

};

//=========================實(shí)現(xiàn)文件==================================
#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位灰度圖像, 該程序需要很大的優(yōu)化。。。。。
void Rprocess::process()
{
//other code
BYTE *image = (BYTE *)GetBits();

//各級(jí)長(zhǎng)寬
int* pnMatrixInfo = new int[(nLevel+2)*3];
pnMatrixInfo[0] = nLevel;
pnMatrixInfo[1] = GetWidth() ;   //w
pnMatrixInfo[2] = GetHeight() ; //h
pnMatrixInfo[3] = GetPitch();    //stride

//灰度內(nèi)存塊
BYTE *pPixelsGrey = new BYTE[pnMatrixInfo[2] * pnMatrixInfo[3]];
       // 取圖像的平均值
MFA_ImageAdd8(image, pPixelsGrey, pnMatrixInfo[1], pnMatrixInfo[2], pnMatrixInfo[3]);

delete pPixelsGrey;
}

// 功能:幀平均算法
// 參數(shù):
//pData 要添加的新的數(shù)據(jù)幀
//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緩沖區(qū),m=4

BYTE *tmp = val[0];// 紀(jì)錄val[0]的地址, 并且向里面復(fù)制數(shù)據(jù)
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;//

// 計(jì)算平均值
int x, y;
int k = 0;
for(y = _top; y < _bottom; y++)
{
for(x = _letf; x < _right; x++)
{
int nResult = 0;
// 取出平均值過(guò)來(lái)
for (int j = 0; j < m; ++j)  // 0 1 2 3
{
//int i = y*stride + x;
//ASSERT(i <= n);
nResult += val[j][k];   // 這句話有語(yǔ)病
}

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];// 釋放標(biāo)志

for(int i=1; i<m; i++)
{
val = val[i-1] + n;
ASSERT(val);
memcpy(val, m_pImage, n*sizeof(BYTE));// 用初始的圖像填充開辟的緩沖區(qū)
}
}

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





相關(guān)帖子

回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表