Hello,
I am writing a convolution function but I am not sure to follow the good way.
Could you help me?
typedef struct tagFILTRES_PERSO
{
char szName[64] ;
int ColsNumber ;
int Divisor ;
int Bias ;
int Matrix[3][3] ;
} FILTRES_PERSO, *LPFILTRES_PERSO ;
FILTRES_PERSO Filtre = {"FX000000241",3, 1, 0,{ -7, 7, 0, -7, -7, 7, 2, -2, 0}} ;
// Image must be int 32 bits (Alpha, Red, Green, Blue)
// Width and Height mut be > 16 pixels
// The Divisor must not be equal to 0. If it is equal to 0, the function set it to 1.
int Convolve_3x3(int __iWidth,int __iHeight,LPBYTE __lpImageBits,LPFILTRES_PERSO __lpFiltre)
{
LPBYTE _lpxy1, _lpxy2, _lpxy3 ;
LPBYTE _lpTmp ;
int _Red, _Green, _Blue, _Rgb ;
int _x1, _x2, _x3, _y1, _y2, _y3 ;
int _x, _y, _xx, _yy ;
int _i, _j ;
if(!__lpFiltre) return (FALSE) ;
if(!__lpImageBits) return (FALSE) ;
if(__iWidth < 16) return (FALSE) ;
if(__iHeight < 16) return (FALSE) ;
if(__lpFiltre->Divisor == 0)
__lpFiltre->Divisor = 1 ;
_lpTmp = __lpImageBits ;
_xx = 4 ; // Column #1
_yy = (__iWidth * 4) + 4 ; // Line #1
_lpTmp += _xx ;
for(_x = 1 ; _x < __iWidth - 2 ; _x++)
{
_x1 = _xx - 4 ; // X - 1 Offset 0 Previous column
_x2 = _xx ; // X Offset 4 Current column
_x3 = _xx + 4 ; // X + 1 Offset 8 Next column
_xx += 4 ;
for(_y = 1 ; _y < __iHeight - 2; _y++)
{
_y1 = (__iWidth * 4) * (_y - 1) ; // Y - 1 Previous line
_y2 = (__iWidth * 4) * _y ; // Y Current line
_y3 = (__iWidth * 4) * (_y + 1) ; // Y + 1 Next line
_lpxy1 = _lpTmp + _x1 + _y1 ;
_lpxy2 = _lpTmp + _x2 + _y2 ;
_lpxy3 = _lpTmp + _x3 + _y3 ;
_Red = (((*_lpxy1) & 0x00FF0000) >> 16) + (((*_lpxy2) & 0x00FF0000) >> 16) + (((*_lpxy3) & 0x00FF0000) >> 16) ;
_Green = (((*_lpxy1) & 0x0000FF00) >> 8) + (((*_lpxy2) & 0x0000FF00) >> 8) + (((*_lpxy3) & 0x0000FF00) >> 8) ;
_Blue = (((*_lpxy1) & 0x000000FF) ) + (((*_lpxy2) & 0x000000FF) ) + (((*_lpxy3) & 0x000000FF) ) ;
for(_i = 0 ; _i < 3 ; _i++)
{
for(_j = 0 ; _j < 3 ; _j++)
{
_Red *= __lpFiltre->Matrix[_i][_j] ; // Red * Coef
_Green *= __lpFiltre->Matrix[_i][_j] ; // Green * Coef
_Blue *= __lpFiltre->Matrix[_i][_j] ; // Blue * Coef
}
}
_Red /= __lpFiltre->Divisor ;
_Green /= __lpFiltre->Divisor ;
_Blue /= __lpFiltre->Divisor ;
if(_Red < 0) _Red = 0 ;
if(_Green < 0) _Green = 0 ;
if(_Blue < 0) _Blue = 0 ;
if(_Red > 255) _Red = 255 ;
if(_Green > 255) _Green = 255 ;
if(_Blue > 255) _Blue = 255 ;
_Rgb = (_Red << 16) | (_Green << 8) | _Blue ;
*(_lpTmp + _x2 + _y2) = _Rgb ;
}
}
return (TRUE) ;
}
-----------------
Calling : Convolve_3x3(_BitmapWidth,_BitmapHeight,_lpImageBits,&Filtre) ;
-----------------
;) no clue. Is this purpose edge detection? Seems comparable to edge detection in IrfanView which I use extensively.
John z
Now I find the same results that XnView!
The problem was coming from the compiler.
I thought that I could compute the convolution like this :
_Red = (((*_lpx1y1 >> 16) & 255) * _c1) +
(((*_lpx2y1 >> 16) & 255) * _c2) +
(((*_lpx3y1 >> 16) & 255) * _c3) +
(((*_lpx1y2 >> 16) & 255) * _c4) +
(((*_lpx2y2 >> 16) & 255) * _c5) +
(((*_lpx3y2 >> 16) & 255) * _c6) +
(((*_lpx1y3 >> 16) & 255) * _c7) +
(((*_lpx2y3 >> 16) & 255) * _c8) +
(((*_lpx3y3 >> 16) & 255) * _c9) ;
It was wrong, I had to compute the convolution like this:
_r1 = ((*_lpx1y1 >> 16) & 255) * _c1 ;
_r2 = ((*_lpx2y1 >> 16) & 255) * _c2 ;
_r3 = ((*_lpx3y1 >> 16) & 255) * _c3 ;
_r4 = ((*_lpx1y2 >> 16) & 255) * _c4 ;
_r5 = ((*_lpx2y2 >> 16) & 255) * _c5 ;
_r6 = ((*_lpx3y2 >> 16) & 255) * _c6 ;
_r7 = ((*_lpx1y3 >> 16) & 255) * _c7 ;
_r8 = ((*_lpx2y3 >> 16) & 255) * _c8 ;
_r9 = ((*_lpx3y3 >> 16) & 255) * _c9 ;
_Red = _r1 + _r2 + _r3 + _r4 + _r5 + _r6 + _r7 + _r8 + _r9 ;
if(_Red < 0) _Red = 0 ;
if(_Red > 255) _Red = 255;
For me, it is a bug into the C Compiler Mr Pelle.
The final source code is:
int Convolve_3x3(int __iWidth,int __iHeight,LPBYTE __lpImageBits,LPFILTRES_PERSO __lpFiltre,int __iApplyDivisor,int __iChannelRed,int __iChannelGreen,int __iChannelBlue)
{
LPDWORD _lpx1y1, _lpx1y2, _lpx1y3, _lpx2y1, _lpx2y2, _lpx2y3, _lpx3y1, _lpx3y2, _lpx3y3 ;
LPDWORD _lpTmp ;
int _Red, _Green, _Blue ;
int _c1, _c2, _c3, _c4, _c5, _c6, _c7, _c8, _c9 ;
int _r1, _r2, _r3, _r4, _r5, _r6, _r7, _r8, _r9 ;
int _g1, _g2, _g3, _g4, _g5, _g6, _g7, _g8, _g9 ;
int _b1, _b2, _b3, _b4, _b5, _b6, _b7, _b8, _b9 ;
DWORD _iChannel ;
int _x1, _x2, _x3, _y1, _y2, _y3, _Rgb ;
int _x, _y, _xx ;
if(!__lpFiltre) return (FALSE) ;
if(!__lpImageBits) return (FALSE) ;
if(__iWidth < 16) return (FALSE) ;
if(__iHeight < 16) return (FALSE) ;
if((__iApplyDivisor < 0) || (__iApplyDivisor > 1)) return (FALSE) ;
if((__iChannelRed < 0) || (__iChannelRed > 1)) return (FALSE) ;
if((__iChannelGreen < 0) || (__iChannelGreen > 1)) return (FALSE) ;
if((__iChannelBlue < 0) || (__iChannelBlue > 1)) return (FALSE) ;
_iChannel = 0 ;
if(__iChannelRed) _iChannel |= 1 ;
if(__iChannelGreen) _iChannel |= 2 ;
if(__iChannelBlue) _iChannel |= 4 ;
_c1 = __lpFiltre->Matrix[0][0] ; // Y1 X1
_c2 = __lpFiltre->Matrix[0][1] ; // Y1 X2
_c3 = __lpFiltre->Matrix[0][2] ; // Y1 X3
_c4 = __lpFiltre->Matrix[1][0] ; // Y2 X1
_c5 = __lpFiltre->Matrix[1][1] ; // Y2 X2
_c6 = __lpFiltre->Matrix[1][2] ; // Y2 X3
_c7 = __lpFiltre->Matrix[2][0] ; // Y3 X1
_c8 = __lpFiltre->Matrix[2][1] ; // Y3 X2
_c9 = __lpFiltre->Matrix[2][2] ; // Y3 X3
__lpFiltre->Divisor = 0 ;
if(__iApplyDivisor)
{
__lpFiltre->Divisor += _c1 ;
__lpFiltre->Divisor += _c2 ;
__lpFiltre->Divisor += _c3 ;
__lpFiltre->Divisor += _c4 ;
__lpFiltre->Divisor += _c5 ;
__lpFiltre->Divisor += _c6 ;
__lpFiltre->Divisor += _c7 ;
__lpFiltre->Divisor += _c8 ;
__lpFiltre->Divisor += _c9 ;
__lpFiltre->Divisor /= 9 ;
}
if(__lpFiltre->Divisor == 0)
__lpFiltre->Divisor = 1 ;
_Red = _Green = _Blue = _Rgb = 0 ;
_lpTmp = (LPDWORD) __lpImageBits ;
_lpTmp++ ;
_xx = 1 ; // Column #1
for(_x = 1 ; _x < __iWidth - 2 ; _x++)
{
_x1 = _xx - 1 ; // X - 1 Offset 0 Previous column
_x2 = _xx ; // X Offset 4 Current column
_x3 = _xx + 1 ; // X + 1 Offset 8 Next column
_xx++ ;
for(_y = 1 ; _y < __iHeight - 2 ; _y++)
{
_y1 = __iWidth * (_y - 1) ; // Y - 1 Previous line
_y2 = __iWidth * _y ; // Y Current line
_y3 = __iWidth * (_y + 1) ; // Y + 1 Next line
_lpx1y1 = _lpTmp + _x1 + _y1 ; // C1 X1,Y1
_lpx1y2 = _lpTmp + _x1 + _y2 ; // C4 X1,Y2
_lpx1y3 = _lpTmp + _x1 + _y3 ; // C7 X1,Y3
_lpx2y1 = _lpTmp + _x2 + _y1 ; // C2 X2,Y1
_lpx2y2 = _lpTmp + _x2 + _y2 ; // C5 X2,Y2
_lpx2y3 = _lpTmp + _x2 + _y3 ; // C8 X2,Y3
_lpx3y1 = _lpTmp + _x3 + _y1 ; // C3 X3,Y3
_lpx3y2 = _lpTmp + _x3 + _y2 ; // C6 X3,Y2
_lpx3y3 = _lpTmp + _x3 + _y3 ; // C9 X3,Y3
if(__lpFiltre->Divisor == 1)
{
if(__iChannelRed)
{
_r1 = ((*_lpx1y1 >> 16) & 255) * _c1 ;
_r2 = ((*_lpx2y1 >> 16) & 255) * _c2 ;
_r3 = ((*_lpx3y1 >> 16) & 255) * _c3 ;
_r4 = ((*_lpx1y2 >> 16) & 255) * _c4 ;
_r5 = ((*_lpx2y2 >> 16) & 255) * _c5 ;
_r6 = ((*_lpx3y2 >> 16) & 255) * _c6 ;
_r7 = ((*_lpx1y3 >> 16) & 255) * _c7 ;
_r8 = ((*_lpx2y3 >> 16) & 255) * _c8 ;
_r9 = ((*_lpx3y3 >> 16) & 255) * _c9 ;
_Red = _r1 + _r2 + _r3 + _r4 + _r5 + _r6 + _r7 + _r8 + _r9 ;
if(_Red < 0) _Red = 0 ;
if(_Red > 255) _Red = 255;
}
if(__iChannelGreen)
{
_g1 = ((*_lpx1y1 >> & 255) * _c1 ;
_g2 = ((*_lpx2y1 >> & 255) * _c2 ;
_g3 = ((*_lpx3y1 >> & 255) * _c3 ;
_g4 = ((*_lpx1y2 >> & 255) * _c4 ;
_g5 = ((*_lpx2y2 >> & 255) * _c5 ;
_g6 = ((*_lpx3y2 >> & 255) * _c6 ;
_g7 = ((*_lpx1y3 >> & 255) * _c7 ;
_g8 = ((*_lpx2y3 >> & 255) * _c8 ;
_g9 = ((*_lpx3y3 >> & 255) * _c9 ;
_Green = _g1 + _g2 + _g3 + _g4 + _g5 + _g6 + _g7 + _g8 + _g9 ;
if(_Green < 0) _Green = 0 ;
if(_Green > 255) _Green = 255;
}
if(__iChannelBlue)
{
_b1 = (*_lpx1y1 & 255) * _c1 ;
_b2 = (*_lpx2y1 & 255) * _c2 ;
_b3 = (*_lpx3y1 & 255) * _c3 ;
_b4 = (*_lpx1y2 & 255) * _c4 ;
_b5 = (*_lpx2y2 & 255) * _c5 ;
_b6 = (*_lpx3y2 & 255) * _c6 ;
_b7 = (*_lpx1y3 & 255) * _c7 ;
_b8 = (*_lpx2y3 & 255) * _c8 ;
_b9 = (*_lpx3y3 & 255) * _c9 ;
_Blue = _b1 + _b2 + _b3 + _b4 + _b5 + _b6 + _b7 + _b8 + _b9 ;
if(_Blue < 0) _Blue = 0 ;
if(_Blue > 255) _Blue = 255;
}
}
else
{
if(__iChannelRed)
{
_r1 = (((*_lpx1y1 >> 16) & 255) * _c1) / __lpFiltre->Divisor ;
_r2 = (((*_lpx2y1 >> 16) & 255) * _c2) / __lpFiltre->Divisor ;
_r3 = (((*_lpx3y1 >> 16) & 255) * _c3) / __lpFiltre->Divisor ;
_r4 = (((*_lpx1y2 >> 16) & 255) * _c4) / __lpFiltre->Divisor ;
_r5 = (((*_lpx2y2 >> 16) & 255) * _c5) / __lpFiltre->Divisor ;
_r6 = (((*_lpx3y2 >> 16) & 255) * _c6) / __lpFiltre->Divisor ;
_r7 = (((*_lpx1y3 >> 16) & 255) * _c7) / __lpFiltre->Divisor ;
_r8 = (((*_lpx2y3 >> 16) & 255) * _c8) / __lpFiltre->Divisor ;
_r9 = (((*_lpx3y3 >> 16) & 255) * _c9) / __lpFiltre->Divisor ;
_Red = _r1 + _r2 + _r3 + _r4 + _r5 + _r6 + _r7 + _r8 + _r9 ;
if(_Red < 0) _Red = 0 ;
if(_Red > 255) _Red = 255;
}
if(__iChannelGreen)
{
_g1 = (((*_lpx1y1 >> & 255) * _c1) / __lpFiltre->Divisor ;
_g2 = (((*_lpx2y1 >> & 255) * _c2) / __lpFiltre->Divisor ;
_g3 = (((*_lpx3y1 >> & 255) * _c3) / __lpFiltre->Divisor ;
_g4 = (((*_lpx1y2 >> & 255) * _c4) / __lpFiltre->Divisor ;
_g5 = (((*_lpx2y2 >> & 255) * _c5) / __lpFiltre->Divisor ;
_g6 = (((*_lpx3y2 >> & 255) * _c6) / __lpFiltre->Divisor ;
_g7 = (((*_lpx1y3 >> & 255) * _c7) / __lpFiltre->Divisor ;
_g8 = (((*_lpx2y3 >> & 255) * _c8) / __lpFiltre->Divisor ;
_g9 = (((*_lpx3y3 >> & 255) * _c9) / __lpFiltre->Divisor ;
_Green = _g1 + _g2 + _g3 + _g4 + _g5 + _g6 + _g7 + _g8 + _g9 ;
if(_Green < 0) _Green = 0 ;
if(_Green > 255) _Green = 255;
}
if(__iChannelBlue)
{
_b1 = ((*_lpx1y1 & 255) * _c1) / __lpFiltre->Divisor ;
_b2 = ((*_lpx2y1 & 255) * _c2) / __lpFiltre->Divisor ;
_b3 = ((*_lpx3y1 & 255) * _c3) / __lpFiltre->Divisor ;
_b4 = ((*_lpx1y2 & 255) * _c4) / __lpFiltre->Divisor ;
_b5 = ((*_lpx2y2 & 255) * _c5) / __lpFiltre->Divisor ;
_b6 = ((*_lpx3y2 & 255) * _c6) / __lpFiltre->Divisor ;
_b7 = ((*_lpx1y3 & 255) * _c7) / __lpFiltre->Divisor ;
_b8 = ((*_lpx2y3 & 255) * _c8) / __lpFiltre->Divisor ;
_b9 = ((*_lpx3y3 & 255) * _c9) / __lpFiltre->Divisor ;
_Blue = _b1 + _b2 + _b3 + _b4 + _b5 + _b6 + _b7 + _b8 + _b9 ;
if(_Blue < 0) _Blue = 0 ;
if(_Blue > 255) _Blue = 255;
}
}
switch(_iChannel)
{
case 0 : _Rgb = 0 ; break ;
case 1 : _Rgb = (_Red << 16) | (_Red << | _Red ; break ;
case 2 : _Rgb = (_Green << 16) | (_Green << | _Green ; break ;
case 3 : _Rgb = (_Red << 16) | (_Green << ; break ;
case 4 : _Rgb = (_Blue << 16) | (_Blue << | _Blue ; break ;
case 5 : _Rgb = (_Red << 16) | _Blue ; break ;
case 6 : _Rgb = (_Green << | _Blue ; break ;
case 7 : _Rgb = (_Red << 16) | (_Green << | _Blue ; break ;
}
*(_lpTmp + _x1 + _y1) = _Rgb ;
}
}
return (TRUE) ;
}
Rather making the sum, it it possible to compute the MAX, the MIN, the AVERAGE.
When computing a SOBEL filter, you call the function with your filter then the filter must be changed as follow before calling again the function.
*** BEFORE ***
_c1 = __lpFiltre->Matrix[0][0] ; // Y1 X1
_c2 = __lpFiltre->Matrix[0][1] ; // Y1 X2
_c3 = __lpFiltre->Matrix[0][2] ; // Y1 X3
_c4 = __lpFiltre->Matrix[1][0] ; // Y2 X1
_c5 = __lpFiltre->Matrix[1][1] ; // Y2 X2
_c6 = __lpFiltre->Matrix[1][2] ; // Y2 X3
_c7 = __lpFiltre->Matrix[2][0] ; // Y3 X1
_c8 = __lpFiltre->Matrix[2][1] ; // Y3 X2
_c9 = __lpFiltre->Matrix[2][2] ; // Y3 X3
*** AFTER ***
_c1 = __lpFiltre->Matrix[0][0] ; // Y1 X1
_c4 = __lpFiltre->Matrix[0][1] ; // Y1 X2
_c7 = __lpFiltre->Matrix[0][2] ; // Y1 X3
_c2 = __lpFiltre->Matrix[1][0] ; // Y2 X1
_c5 = __lpFiltre->Matrix[1][1] ; // Y2 X2
_c8 = __lpFiltre->Matrix[1][2] ; // Y2 X3
_c3 = __lpFiltre->Matrix[2][0] ; // Y3 X1
_c6 = __lpFiltre->Matrix[2][1] ; // Y3 X2
_c9 = __lpFiltre->Matrix[2][2] ; // Y3 X3
THEN DO
__lpFiltre->Matrix[0][0] = _c1 ; // Y1 X1
__lpFiltre->Matrix[0][1] = _c2; // Y1 X2
__lpFiltre->Matrix[0][2] = _c3; // Y1 X3
__lpFiltre->Matrix[1][0] = _c4; // Y2 X1
__lpFiltre->Matrix[1][1] = _c5 ; // Y2 X2
__lpFiltre->Matrix[1][2] = _c6 ; // Y2 X3
__lpFiltre->Matrix[2][0] = _c7 ; // Y3 X1
__lpFiltre->Matrix[2][1] = _c8 ; // Y3 X2
__lpFiltre->Matrix[2][2] = _c9 ; // Y3 X3
I forgot to show the result.
(https://www.mediafire.com/convkey/9f01/zogr9kgp0zh4y2q4g.jpg) (https://www.mediafire.com/view/zogr9kgp0zh4y2q/Result.jpg/file)
Wow, well you persevered and achieved desired results...
Could it be that part of the problem is this warning in the help file?
Quote
Note! Do not select names for identifiers that begin with two underscores, or with an underscore followed by an uppercase letter. The C standard allows identifier names that begin with these character combinations to be reserved for compiler use.
_Red <= underscore followed by an uppercase letter .....
int
_Red,
_Green,
_Blue ; //
So it may be working accidentally right now.....
John Z
I don't know.
I am working on convolution functions 5x5, 7x7 and 9x9
Then I add complex filters like SOBEL, PREWITT, KIRCH and ROBINSON.
I will post my differents steps.
Thank You John
Don't be afraid I have my mask for writing!
I have made a sample application to test the filters.
The application has 19954 filters build into it!
It must generate 19954 images?
No, because I drop identical images, computing for each a hash (Keccak) stored into a databse.
After if the file size is smaller than the original, I drop it too.
It is not possible to tell how many images will be created.
Into the applcation folder there is a test directory.
For using the application, just put an image into the folder the application is.
If there are more than one image file, it uses the first.
The application onmy wants JPEG files.
It can be downloaded here : https://www.mediafire.com/file/pazgwnpkv8scvw8/MakeFilters.7z/file (https://www.mediafire.com/file/pazgwnpkv8scvw8/MakeFilters.7z/file)
The program has been tested on colored, sepia and grey images.
Actually I am running the test and there are 644 files for 2244 filters!
I made a folder with some test image : https://www.mediafire.com/folder/pzxj2kljcsbv4/Tests (https://www.mediafire.com/folder/pzxj2kljcsbv4/Tests)
Into the source code there is a convolution function for 5x5, but it is not tested again.
For the Robinson filters I create the 8 filters (N/NE/E/SE/S/SO/W/NO), idem for sobel, 2 filters and for Kirsch, 4 filters (N/S/E/W).
One thing is funny with filters, you cann se the image moving. This is because some filters move the new images to the top, or to the bottom, or to the right or th left.
I have used the filters with Photofiltre (http://www.photofiltre-studio.com/pf7.htm (http://www.photofiltre-studio.com/pf7.htm)).
Edit a image created with a filter. It becomes the background.
Paste the original image into photofiltre (CTRL V). Use each of the blend modes, or use Gimp.
The original image
(https://www.mediafire.com/convkey/2cf9/elswpt9li5m186x4g.jpg) (https://www.mediafire.com/view/elswpt9li5m186x/Bonnie_%2526_Clyde.jpg/file)
The new one
(https://www.mediafire.com/convkey/cf14/hevqwm04sndfqia4g.jpg) (https://www.mediafire.com/view/hevqwm04sndfqia/FY000000909-D01-Bonnie_%2526_Clyde-01.jpg/file)
The PhotoFiltre file :
https://www.mediafire.com/file/cazbgy27im02uib/FY000000909-D01-Bonnie_%2526_Clyde-01.pfi/file (https://www.mediafire.com/file/cazbgy27im02uib/FY000000909-D01-Bonnie_%2526_Clyde-01.pfi/file)
Wow - I just don't know what I would use it for.
I'll download though and try a few things. Hope I have enough memory for 644 images ;D
Did you change the underscore caps variables (_R ..) or just let it work that way? Just wondering if that had an effect or not.
I'm think I might implement a "Wu's Color Quantizer" for BMP - just thinking at this stage.
John Z
P.S. How is that radio project coming?
Hello John,
I have changed but no effect, so I set it to my coding conventions :
One underscore for local variables and two underscores for parameters. No underscore for global variables.
I have now to create some source code for some filters not yet implemented.
After it will be possible to merge the original image and the filter result.
Merging modes are similar to these used by GIMP.
The code is written for the modes there is no big work to joi the filters and the merge modes.
For my radio project, I have my SWL paper and code F5205SWL.
One of my cats came on my desl and make the baofeng falling down!
Can't use it now, broken.
I have seen a little radio, not expensive, I will buy it. I just wait to have more work, C19!
Quote from: Grincheux on March 06, 2021, 02:51:11 AM
Hello John,
I have changed but no effect, so I set it to my coding conventions :
One underscore for local variables and two underscores for parameters. No underscore for global variables.
While you're free to use any convention you like, you must be advised anyway that it is uncompliant with the standard, that, at least in this case, reserve a full subsection to clarify what are to be considered
reserved identifiers.
For your convenience I copycat the paragraph below. If you want use a more compliant convention you can have a look at the Hungarian notation (https://en.wikipedia.org/wiki/Hungarian_notation), adopted also by MS for its, now rare, plain C code.
Excerpt from ISO/IEC 9899:2011:
ยง7.1.3 Reserved identifiers
- Each header declares or defines all identifiers listed in its associated subclause, and optionally declares or defines identifiers listed in its associated future library directions subclause and identifiers which are always reserved either for any use or for use as file scope identifiers.
All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use.
- All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces.
Each macro name in any of the following subclauses (including the future library directions) is reserved for use as specified if any of its associated headers is included; unless explicitly stated otherwise (see 7.1.4).
All identifiers with external linkage in any of the following subclauses (including the future library directions) and errno are always reserved for use as identifiers with external linkage.181)
Each identifier with file scope listed in any of the following subclauses (including the future library directions) is reserved for use as a macro name and as an identifier with file scope in the same name space if any of its associated headers is included.
No other identifiers are reserved.
If the program declares or defines an identifier in a context in which it is reserved (other than as allowed by 7.1.4), or defines a reserved identifier as a macro name, the behavior is undefined
If the program removes (with #undef) any macro definition of an identifier in the first group listed above, the behavior is undefined.
Consider also that object symbols are composed by prefixing the C identifier name with an underscore (see
identifiers with external linkage above), in standard C, not MS convention that use also decoration, so the mess between program identifiers, system identifiers and symbol names, as identifiers with external linkage, become epic.
As said you're eventually free to follow your way.
You seem to right, but in this case one can consider a bug into any compiler that accept local and parameters variable to begin with an underscore. I have seen many C grammars, it is not forbidden to use the underscore anywhere in the variable name.
I thought that it was link any other character. In my mind when I have a variable "_Toto" the compiler must create "__Toto".
And when I have a "__Toto" variable it becomes "___Toto".
That is only valid for external variables, when there is no external variables defined, the syntax is accepted.
I don't want the war.
I like that kind of discuss because it is possible to learn many things.
But the problem I had was not caused by the syntax, for me it was a bug.
Thank You Frankie. ;D
Quote from: Grincheux on March 18, 2021, 08:44:37 PM
You seem to right, but in this case one can consider a bug into any compiler that accept local and parameters variable to begin with an underscore. I have seen many C grammars, it is not forbidden to use the underscore anywhere in the variable name.
No war, never :)
Maybe I haven't been clear enough, you can use the underscore, and the compiler will never prevent you to do so.
The standard prohibit the use of symbols beginning with underscores for application code, but you are allowed to use them when using system or library headers or symbols.
The compiler don't, and can't, block you because you must be allowed to create a compiler header or library, and must be allowed to use those symbols in your application code.
So the compiler will not complain, but the code isn't compliant with the standard.
Said that you're free to do whatever you want... only your code isn't formally correct ;D ;D ;D ;D
Frankie Game, Set and Match :o
;D ;D ;D
Ok, drawed match.