[英]Calling a pointer function in C++
我用 C++ 寫了一段代碼。 我從搜索引擎結果中提取了第一部分。
1) 使用double **filter_2d
定義函數是什么意思? 我們可以使用指針定義函數嗎?
2)我對以下行感到困惑:
double **filt_out = filter_2d(A, 3, 3, B, 2, 1);
它不能正常工作,我不明白為什么。
#include <iostream>
#include <stddef.h>
#include <cmath>
#include <fftw3.h>
using namespace std;
void filter_2d(double** image, int width_image, int height_image, double** kernel, int width_kernel, int height_kernel, double *** OutImg)
{
double **output = *OutImg;
int i, j, p, q;
//this is the case of 'full' option selected in matlab
//double **output = (double **)malloc(sizeof(double *)*(width_image + width_kernel - 1));
for (i = 0; i<width_image + width_kernel - 1; i++)
{
output[i] = (double *)malloc(sizeof(double)*(height_image + height_kernel - 1));
}
//for each point in the output
for (i = 0; i<width_image + width_kernel - 1; i++)
{
for (j = 0; j<height_image + height_kernel - 1; j++)
{
output[i][j] = 0;
//kernel(p,q)*image(i-p, j-q)
for (p = 0; p<width_kernel; p++)
{
//avoid unnecessary comparisons
if (i - p < 0)
{
break;
}
else if (i - p < width_image)
{
for (q = 0; q<height_kernel; q++)
{
//idem as above
if (j - q < 0)
{
break;
}
else if (j - q < width_image)
{
output[i][j] += kernel[p][q] * image[i - p][j - q];
}
}
}
}
}
}
}
int main()
{
double ** OutImage = 0;
OutImage = (double **)malloc(sizeof(double *)*(3 * 3));
double A[3][3] = { { 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 } };
double *A_ptr[9];
for (int i = 0; i < 10; i++)
{
A_ptr[i] = A[i];
}
double B[1][2] = { 1, 2 };
double *B_ptr[2];
for (int i = 0; i < 2; i++)
{
B_ptr[i] = B[i];
}
//Error in the below line
filter_2d(A_ptr, 3, 3, B_ptr, 2, 1, &OutImage); //unable to understand
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 4; j++)
cout << *OutImage << endl;
}
system("PAUSE");
return 0;
}
指針聲明
一般格式:
data_type *pointer_name;
一個指針聲明,例如,
int *numberPtr;
將 numberPtr 聲明為指向整數變量的變量。 它的內容是一個內存地址。
* 表示被聲明的變量是指針變量而不是普通變量。
考慮以下聲明:
int *numberPtr, number = 20;
在這種情況下,保留了兩個內存地址,與名稱 numberPtr 和 number 相關聯。
變量 number 中的值是整數類型,變量 numberPtr 中的值是另一個內存位置的地址。
例子
// create a 2D array dynamically
int rows, columns, i, j;
int **matrix;
cin >> rows >> columns;
matrix = new int*[rows];
for(i=0; i<rows; i++)
matrix[i] = new int[columns];
您的函數需要double**
而您正在傳遞double [3][3]
。 這些類型沒有隱式轉換。
您需要在main()
中將數組創建為double **
並將其用作函數調用中的參數。
問題 - 將二維數組轉換為指針到指針應該可以幫助您實現您想要做的事情。
您的cout
似乎也不正確。 您正在考慮將filt_out
視為二維數組而不是指針。
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 4; j++)
cout << **(filt_out + i + j) << endl; //changed here
}
我分析了你的代碼,我想我發現了一些問題。
這是新代碼:
#include <iostream>
#include <stdlib.h>
using namespace std;
double** filter_2d(double** image, int width_image, int height_image, double** kernel, int width_kernel, int height_kernel)
{
int i, j, p, q;
//this is the case of 'full' option selected in matlab
double **output = (double **)malloc(sizeof(double *) * (width_image + width_kernel - 1));
for (i = 0; i<width_image + width_kernel - 1; i++)
output[i] = (double *)malloc(sizeof(double) * (height_image + height_kernel - 1));
//for each point in the output
for (i = 0; i<width_image + width_kernel - 1; i++)
for (j = 0; j<height_image + height_kernel - 1; j++)
{
output[i][j] = 0;
//kernel(p,q)*image(i-p, j-q)
for (p = 0; p<width_kernel; p++)
{
//avoid unnecessary comparisons
if (i - p < 0)
{
break;
}
else if (i - p < width_image)
{
for (q = 0; q<height_kernel; q++)
{
//idem as above
if (j - q < 0)
break;
else if (j - q < width_image)
output[i][j] += kernel[p][q] * image[i - p][j - q];
}
}
}
}
return output;
}
int main()
{
double A[3][3] = { { 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 } };
double *A_ptr[9];
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j ++)
A_ptr[i * 3 + j] = &(A[i][j]);
double B[1][2] = { 1, 2 };
double *B_ptr[2];
for (int i = 0; i < 1; i++)
for (int j = 0; j < 2; j ++)
B_ptr[i * 1 + j] = &(B[i][j]);
//no more errors in the function call
double **OutImage = filter_2d(A_ptr, 3, 3, B_ptr, 2, 1);
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 3; j++)
cout << OutImage[i][j] << " ";
cout << endl;
}
return 0;
}
我認為一個更好的主意是函數 filter_2d 返回一個指向輸出矩陣的指針。 輸出矩陣在函數內部使用 malloc 動態分配,因此如果您將地址返回給它並將其存儲回 main 中,它不會丟失(並且您可以獲得矩陣中的計算值)。
您可以在此處看到堆棧內存和函數局部變量與堆內存以及使用 malloc堆棧與堆分配的變量之間的比較
下面說說我在main函數中發現的一些問題。 第一個問題是指針數組 A_ptr 和 B_ptr 的初始化。
double *A_ptr[9];
for (int i = 0; i < 10; i++)
{
A_ptr[i] = A[i];
}
和
double *B_ptr[2];
for (int i = 0; i < 2; i++)
{
B_ptr[i] = B[i];
}
根據我在您的代碼中的理解,A_ptr 和 B_ptr 的元素是指向數組 A 和 B 的每個元素的指針。
因此,由於 A_ptr 和 B_ptr 是線性化矩陣,您必須小心從數組 A 和 B 中給出相應元素的正確地址。
如果將矩陣 M 線性化為矩陣 N,則元素 M[i][j] 將變為 N[i * number_of_columns_from_M + j]。
另一個問題是在打印結果的 for 循環中 i 和 j 的限制。
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 4; j++)
cout << *OutImage << endl;
}
根據我的計算,在 filter_2d 函數中,您分配了一個 4 行 3 列的矩陣。 在這些循環中,您假設 OutImage 有 5 行和 4 列。
最后一個問題是從 OutImage 打印元素。
cout << *OutImage << endl;
您在代碼中聲明的 OutImage 是一個包含 9 個指針的數組(不明白您為什么這樣做)。 使用上述指令,您將重復打印 OutImage 數組的第一個元素(這是一個地址,因為 OutImage 是一個包含 9 個指針的數組),這就是為什么您只能看到打印的地址。
我不確定現在在屏幕上打印的數字是否正確,因為我不知道 filter_2d 中進行了哪些數學計算。
將 C++ 指針上下文中的*
作為pointer to
.
國際*一個;
a 是一個指向 int 的指針。
int** b;
b
是一個指向int
指針的指針。
b = &a;
a
是一個指向int
的指針。 &a
是指向int
的指針的地址。 b
是一個指向int
指針的指針。
*a = 10;
將 10 存儲在a
指向的內存中。
**b = 20;
將 20 存儲在b
指向的int*
所指向的內存中。
#include <iostream>
int main()
{
int i = 1234;
int* a;
int** b;
std::cout << "i is " << i << ", it's address is " << i << "\n";
a = &i;
std::cout << "a = " << a << ", *a = " << *a << ", its address is " << &a << "\n";
b = &a;
std::cout << "b = " << b << ", *b = " << *b << ", **b = " << **b << ", its address is " << &b << "\n";
}
現場演示: http : //ideone.com/OpCro4
您的函數“filter_2d”返回指針的地址。 它還期望第一個參數是指針的地址。
這通常用作允許函數說“給我一個指針的地址,我會為你填充它”的一種方式,但 C++ 也使用指針來傳遞數組。
int a[100];
f(a);
該程序可以將所有 100 個地址傳遞給f()
,這將需要堆棧上的 100 個整數或 100 個寄存器。
或者,它可以傳遞 a 中第一個 int 的地址。 在 C 和 C++ 中,數組通常是這樣工作的——它們作為數組和偏移量進行操作。
int a[100];
int* b = a; // b points to the first element in a
// these two mean the same thing
a[90];
*(b + 90);
// undefined behavior
*(b + 100); // the 101st element of a, i.e. invalid
缺點:指針只知道它們指向的元素,它們本質上不知道任何關於數組長度的信息。
最后,不要使用SYSTEM("PAUSE")
使用 'Ctrl+F5' 啟動而不進行調試(執行后會自動提示您按回車鍵)或使用 'F11' 進入您的程序。
您的代碼有兩個問題:
首先,我假設輸出圖像的大小與輸入圖像的大小相同,因此必須按如下方式分配:
(double **)malloc(sizeof(double *)*(width_image * height_image));
其次,您定義了一個將返回 2D 指針的函數,但不幸的是,您在函數本身內部聲明了這個 2D 指針,這意味着您定義了一個局部變量指針,在大多數情況下,一旦您返回此值,它將完全錯誤,它是不是在函數本身內部分配的那個。
要解決該問題,您可以選擇以下兩種解決方案之一:
//Define these 2 lines in the main function. double ** OutImage = null; OutImage = (double **)malloc(sizeof(double *)*(width_image * height_image));
將 OutImage 傳遞給 filter_2d 函數:
filter_2d(A_ptr, 3, 3, B_ptr, 2, 1, &OutImage);
filter_2d 函數的定義應該是:
void filter_2d(double** image, int width_image, int height_image, double** kernel, int width_kernel, int height_kernel, double *** OutImg)
在 filter_2d 中,您可以將局部變量定義如下:
double **output = *OutImg;
希望這個校准能幫到你。
我用 C++ 寫了一段代碼。 我從搜索引擎結果中提取了第一部分。
你是認真的嗎? 不知道如何理解。 它不是調試站點。 你應該先努力。
無論如何,您的代碼主要是 C。唯一讓我想起 C++ 的代碼是控制台輸出。 如果我能幫上忙,讓我試試吧……因為我喜歡。
1) 使用
double
**filter_2d
定義函數是什么意思? 我們可以使用指針定義函數嗎?
這意味着該函數的結果是一個指向 double 類型指針的指針。 像這樣分解它:
**filt_out
是double
類型 - 用於訪問 double 值; 在二維數組中普遍用於訪問二維,即二維數組的行和列。
*filt_out
是double *
類型double *
- 用於訪問指向 double 值的指針; 在二維數組中普遍用於訪問第一維,即二維數組的行。
filt_out
是double **
類型 - 用於訪問指向 double 值的指針的指針; 二維數組中常用來訪問數組,即為二維數組分配的內存地址。
您可以使用簡單的指針定義函數,但它不適用於二維數組。 閱讀以上項目。
2)我對以下行感到困惑:
double **filt_out = filter_2d(A, 3, 3, B, 2, 1);
它不能正常工作,我不明白為什么。
對我來說沒有意義。 filter_2d
的返回類型是void
,因此我不明白為什么要將返回值分配給指向雙精度指針的指針
它不能正常工作,我不明白為什么。
我也沒有。 但說實話,這聽起來更像是一個調試請求,而不是一個值得投票的問題。 特別是你給我們的印象是,你首先沒有做功課學習C/C++,其次從搜索引擎復制代碼,並要求社區為你解決。
(我將主要使用 C 語法)
OutImage = (double **)malloc(sizeof(double *)*(3 * 3));
對我來說這看起來不對。 請核實。
我認為 OutImage 應該是一個二維數組(圖像),因此**OutImage
指向二維數組的一個元素(二維,你想訪問行和列)。
此外,由於它是一個二維數組,您需要首先初始化第一維(即行),然后是第二維(即列)。
所以我會建議這樣的事情:
//three rows of size for type double*
OutImage = (double **) malloc(sizeof(double *) * 3);
//three columns of size of type double
for (int i=0; i<3; i++)
OutImage[i] = (double *) malloc(sizeof(double) * 4);
這樣您就可以使用OutImage[row][column]
。 我相信它不太容易出錯。 我根據函數filter_2d
中的計算將列的大小設置為4,該函數計算寬度和高度(寬度保持不變,參數給定,高度增加一維)。 另外(見下文)稍后在函數filter_2d
我將刪除內存分配,因為它已經在這里完成。
不確定你想用這個實現什么,但我認為......
double *A_ptr[9];
for (int i = 0; i < 10; i++)
{
A_ptr[i] = A[i];
}
在很多層面上都是錯誤的。
考慮到在上面的函數filter_2d
使用 A_ptr(以及您訪問它的方式),我認為您想要做一些類似於上面 2D 數組的事情。
double ** A_ptr = (double **) malloc(sizeof (double *) * 3);
for (int i = 0; i < 3; i++)
A_ptr[i] = (double *) malloc(sizeof (double) * 3);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
A_ptr[i][j] = A[i][j];
}
}
double B[1][2] = { 1, 2 };
double *B_ptr[2];
for (int i = 0; i < 2; i++)
{
B_ptr[i] = B[i];
}
與上面類似。
您使用以下參數調用過濾器:
&OutImage:過濾后圖像的指針地址(參數實際上是**OutImage
的指針)? 我想你想在函數調用后保留指針,不是嗎? 對我來說聽起來不錯。
filter_2d(A_ptr, 3, 3, B_ptr, 2, 1, &OutImage);
您將 B_ptr 定義為 B 的副本,其維度為 [1][2],但您將 2 作為第一個維度和 1 作為第二個維度傳遞給函數。 要么切換 B/B_ptr 的維度,要么切換兩個參數。
在該函數中,我將刪除以下代碼
for (i = 0; i<width_image + width_kernel - 1; i++)
{
output[i] = (double *)malloc(sizeof(double)*(height_image + height_kernel - 1));
}
(在為OutImage
分配內存時,請參閱上面第一個錯誤中的最后一條評論)。
替換循環以打印結果。 讓它看起來像這樣:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++)
cout << OutImage[i][j] << endl;
}
我保留了 C++ 風格的打印,但實際上你也可以簡單地使用 C 的printf
函數來完成。 真的不需要包含iostream
。
就是這樣了。 我編譯了你的代碼並運行它。 不確定會發生什么,但根據您的評論應該是
2 5 8 3 8 14 17 6 14 23 26 9
你猜怎么着? 我有
1 4 7 6 4 13 16 12 7 22 25 18
好吧,我想在這一點上,現在輪到你了。
請記住,檢查您要在哪里進行內存分配,以便將新維度考慮在內。 我在您的示例中對其進行了硬編碼以使其工作,或多或少。
我可能會分配一個虛擬地址,然后根據參數使用realloc
將大小增加到所需的大小。
請記住,通常您希望釋放分配的內存。 我在這里跳過它,因為它是一個簡短的程序。
該程序可能如下所示:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
void filter_2d(double** image, int width_image, int height_image, double** kernel, int width_kernel, int height_kernel, double *** OutImg) {
double **output = *OutImg;
int i, j, p, q;
int rows = width_image + width_kernel - 1;
int cols = height_image + height_kernel - 1;
//rows of size for type double*
output = (double **) realloc(output, sizeof (double *) * rows);
//columns of size of type double
for (int i = 0; i < rows; i++)
output[i] = (double *) malloc(sizeof (double) * cols);
//for each point in the output
for (i = 0; i < width_image + width_kernel - 1; i++) {
for (j = 0; j < height_image + height_kernel - 1; j++) {
output[i][j] = 0;
//kernel(p,q)*image(i-p, j-q)
for (p = 0; p < width_kernel; p++) {
//avoid unnecessary comparisons
if (i - p < 0) {
break;
} else if (i - p < width_image) {
for (q = 0; q < height_kernel; q++) {
//idem as above
if (j - q < 0) {
break;
} else if (j - q < width_image) {
output[i][j] += kernel[p][q] * image[i - p][j - q];
}
}
}
}
}
}
}
int main() {
//allocate dummy memory of size for type double*
double ** OutImage = (double **) malloc(sizeof (double *));
// define image matrix
double A[3][3] = {
{ 1, 2, 3},
{ 4, 5, 6},
{ 7, 8, 9}
};
// copy image matrix
double ** A_ptr = (double **) malloc(sizeof (double *) * 3);
for (int i = 0; i < 3; i++)
A_ptr[i] = (double *) malloc(sizeof (double) * 3);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
A_ptr[i][j] = A[i][j];
printf(" %f ", A_ptr[i][j]);
}
}
printf("\n");
//define kernel matrix
double B[1][2] = {
{ 1, 2}
};
//copy kernel matrix
double ** B_ptr = (double **) malloc(sizeof (double *));
B_ptr[0] = (double *) malloc(sizeof (double)*2);
for (int i = 0; i < 1; i++) {
for (int j = 0; j < 2; j++) {
B_ptr[i][j] = B[i][j];
printf(" %f ", B_ptr[i][j]);
}
}
printf("\n");
//call filter
filter_2d(A_ptr, 3, 3, B_ptr, 1, 2, &OutImage);
//print result
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++)
cout << OutImage[i][j] << endl;
}
// No idea what that is
//system("PAUSE");
return 0;
}
PS:我剛剛看到Valy有一個很好的解決方案。
是的,函數可以返回指針,甚至是指向指針的指針。 我相信您的兩個答案都已通過此線程解決。
#include <stdlib.h>
int int_sorter( const void *first_arg, const void *second_arg )
{
int first = *(int*)first_arg;
int second = *(int*)second_arg;
if ( first < second )
{
return -1;
}
else if ( first == second )
{
return 0;
}
else
{
return 1;
}
}
int main()
{
int array[10];
int i;
/* fill array */
for ( i = 0; i < 10; ++i )
{
array[ i ] = 10 - i;
}
qsort( array, 10 , sizeof( int ), int_sorter );
for ( i = 0; i < 10; ++i )
{
printf ( "%d\n" ,array[ i ] );
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.