我正在嘗試使用 CS50 制作灰度濾鏡。
首先 - 為什么我的代碼不起作用,而我在 GitHub 上找到的與我的類似的代碼運行良好。
那是我的代碼:
void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
int i = 0, j = 0;
float rgbGray;
while (i < height)
{
while (j < width)
{
rgbGray = (image[i][j].rgbtBlue image[i][j].rgbtGreen image[i][j].rgbtRed) / 3.00;
rgbGray = round(rgbGray);
image[i][j].rgbtBlue = rgbGray;
image[i][j].rgbtGreen = rgbGray;
image[i][j].rgbtRed = rgbGray;
j ;
}
i ;
}
return;
}
這是我在 GitHub 上找到的作業代碼
void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
float rgbGray;
for (int i = 0; i < height; i )
{
for (int j = 0; j < width; j ) {
rgbGray = round( (image[i][j].rgbtBlue image[i][j].rgbtGreen image[i][j].rgbtRed)/ 3.00);
image[i][j].rgbtBlue = rgbGray;
image[i][j].rgbtGreen = rgbGray;
image[i][j].rgbtRed = rgbGray;
}
}
return;
}
作者:https : //gist.github.com/ndiecodes
第二個問題是 - 為什么不需要指標。我的意思是在講座中有資訊,我們需要在想要更改元素值的情況下使用指標。這個函式沒有回傳任何值 - 它只是 VOID - 所以我很好奇為什么第二個代碼可以正常作業
uj5u.com熱心網友回復:
您的代碼使用 while 回圈,在回圈后不會重置j為零。結果,在第一行之后,對陣列的每一行都不做任何事情。
其次,這里沒有顯式指標,但 C 陣列被有效地傳遞,就好像(松散地說)它們是指向資料的指標,因此您的訪問會image影響呼叫者看到的資料。
uj5u.com熱心網友回復:
第二個問題是 - 為什么不需要指標。我的意思是在講座中有資訊,我們需要在想要更改元素值的情況下使用指標。
陣列很奇怪。
除非它是sizeof或 一元運算&符的運算元,或者是用于在宣告中初始化字符陣列的字串文字,否則“N 元素陣列”型別的運算式T將被轉換(或“衰減”)為運算式型別為“指向”的指標T,運算式的值將是陣列第一個元素的地址。
當你使用陣列運算式作為引數呼叫函式時,函式實際接收的是指向第一個元素的指標:
int arr[10];
foo( arr ); // equivalent to foo( &arr[0] );
...
void foo( int *a ) { ... }
在你的情況下,當你這樣打電話時grayscale:
RGBTRIPLE image[rows][cols];
...
grayscale( rows, cols, image );
什么grayscale實際接收是一個指標到cols的-元素陣列RGBTRIPLE:
void grayscale( int height, int width, RGBTRIPLE (*image)[width] )
{
...
}
然而...
在函式引數宣告的背景關系中,任何帶有 typeT []或 的引數T [N]都將被“調整”為 type T *,因此我可以宣告 foo為
void foo( int a[10] )
或者
void foo( int a[] )
或者
void foo( int *a )
和所有被解釋相同的方式-a是一個指標到int,而不是陣列int。這就是為什么你仍然可以宣告grayscale為
void grayscale( int height, int width, RGBTRIPLE image[height][width] )
陣列下標是根據指標操作定義的。運算式a[i]定義為*(a i)- 給定起始地址a,從該地址偏移i物件(不是位元組!)并取消參考結果:
a[0] == *(a 0) == *a
a[1] == *(a 1)
a[2] == *(a 2)
等等。
Array access is why the decay rule exists in the first place. C was derived from an earlier language named B (which was derived from BCPL, which was derived from CPL, which was influenced by Algol, etc.). In the B language, there was an explicit pointer to the first element of the array. Given the declaration
auto vec[10];
you'd get this in memory:
---
vec: | | ----------
--- |
... |
--- |
| | vec[0] <--
---
| | vec[1]
---
...
So in B the equivalence of a[i] == *(a i) makes sense - you always had an explicit pointer to the first element.
When he was designing C, Ritchie wanted to keep B's array behavior, but he didn't want to set aside space for the explicit pointer that behavior required - he just wanted to set aside space for the array elements themselves. Given
int vec[10];
you get
---
vec: | | vec[0]
---
| | vec[1]
---
...
so he came up with the decay rule - any time the compiler sees an array expression that isn't the operand of & or sizeof (or _Alignof), it replaces that expression with a pointer to the first element of the array.
This is why you don't need to use & when passing an array argument to functions like scanf, and why you can't return arrays from functions - all that gets returned is a pointer to the first element of the array, which ceases to exist when the function returns.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/338892.html
