News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

C++ argument passed by adress or value

Started by ToutEnMasm, October 02, 2007, 03:12:41 PM

Previous topic - Next topic

ToutEnMasm

Hello,

The function ID3DXBaseMesh::GetDeclaration,pass his argument by adress.
Usually,there is a "*" to say it's a pointer.Here,there isn't.
example of arguments passed by values:
           http://www.masm32.com/board/index.php?topic=6182.0

How can we see in the declaration of the function , if it is one or other.
           ToutEnmasm


Quote
;----------------------------------------------------------------------------
;declare
typedef struct _D3DVERTEXELEMENT9
{
    WORD    Stream;     // Stream index
    WORD    Offset;     // Offset in the stream in bytes
    BYTE    Type;       // Data type
    BYTE    Method;     // Processing method
    BYTE    Usage;      // Semantics
    BYTE    UsageIndex; // Semantic index
} D3DVERTEXELEMENT9, *LPD3DVERTEXELEMENT9;

// This is used to initialize the last vertex element in a vertex declaration
// array
//
D3DDECLTYPE_UNUSED    = 17,  // When the type field in a decl is unused.

#define D3DDECL_END() {0xFF,0,D3DDECLTYPE_UNUSED,0,0,0}
#define MAXD3DDECLLENGTH        64 // does not include "end" marker vertex element

enum _MAX_FVF_DECL_SIZE
{
    MAX_FVF_DECL_SIZE = MAXD3DDECLLENGTH + 1 // +1 for END
};



DECLARE_INTERFACE_(ID3DXBaseMesh, IUnknown)
{
...
    STDMETHOD(GetDeclaration)(THIS_ D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]) PURE;
..
}

;----------------------------------------------------------------------------


decompiled
Quote
; 1085 :     {
; 1086 :         D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE];
; 1087 :         D3DVERTEXELEMENT9 End = D3DDECL_END();

   mov   WORD PTR _End$114014[ebp], 255      ; 000000ffH
   mov   WORD PTR _End$114014[ebp+2], 0
   mov   BYTE PTR _End$114014[ebp+4], 17      ; 00000011H
   mov   BYTE PTR _End$114014[ebp+5], 0
   mov   BYTE PTR _End$114014[ebp+6], 0
   mov   BYTE PTR _End$114014[ebp+7], 0

; 1088 :         int iElem;
; 1089 :     
; 1090 :         m_pMeshSysMem->GetDeclaration( Declaration );

   lea   eax, DWORD PTR _Declaration$114013[ebp]      ;by adress
   push   eax
   mov   ecx, DWORD PTR _this$[ebp]
   mov   edx, DWORD PTR [ecx+2052]
   mov   eax, DWORD PTR _this$[ebp]
   mov   ecx, DWORD PTR [eax+2052]
   mov   edx, DWORD PTR [edx]
   push   ecx                  ;this
   mov   eax, DWORD PTR [edx+28]
   call   eax



u

Actually the GetDeclaration(..) receives 1 DWORD parameter - the address of that array. (apart for the _this parameter)
I haven't seen it mentioned anywhere, but these 3 are identical:
void Func1(int* Array);
void Func1(int Array[]);
void Func1(int Array[1000]);

the "%TYPE %NAME[%NUM]"   type of function-definition is simply to visually aid programmers - a reminder that this array has some fixed size.

Also the fourth way to define a pointer-argument is
void Func2(int &Element); 
but here you start "thinking" as if that argument was allocated on this proc's stack. (though in reality it's in the caller-proc's stack).

A fifth way to play with functions and pointers is by returning a big-structure (usually bigger than 8 bytes):
D3DMATRIX4 Func3(){
D3DMATRIX4 m1;
memset(&m1,0,sizeof(m1));
return m1;
}
this code is identical to:
void Func3(D3DMATRIX4 *result){
  D3DMATRIX4 m1;
  memset(&m1,0,sizeof(m1));
  memcpy(result,&m1,sizeof(m1));
}
but usually optimized simply to
void Func3(D3DMATRIX4 *result){
  memset(result,0,sizeof(m1));
}
The caller-function allocates space for the big-struct result, and then calls Func3.



N.B: Toying with "seemingly big parameters" gets ugly ONLY if you pass one whole struct-variable:
void Func4(D3DMATRIX4 bigParam1);
There, the calling function will do a memcpy() to pass the parameter!
Please use a smaller graphic in your signature.

ToutEnMasm


Things are less unclear now.
I search what is the difference in the writing of this two functions.
Quote
STDMETHOD(GetDeclaration)(THIS_ D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE]) PURE;

HRESULT AssocCreate(CLSID clsid,REFIID riid,LPVOID *pqa);

The D3DVERTEXELEMENT9 is a structure of a size greater than a dword.
The CLSID is a structure of a size greater than a dword.

In the two declaration,there is no sign *,& and no typedef with a dword size.
Reading your post,we can see that

Quote
void Func1(int Array[]);

The "int" is a dword and we used an adress to read it.

Quote
void Func4(D3DMATRIX4 bigParam1);

There is no sign *, & or typedef of dword size in the func4,and we acces it by value.

Where I am a bit confuse is between GetDeclaration and Func4 .I couldn't see why GetDeclaration pass his argument by adress ?.

                           ToutEnMasm












u

Oks, this short example will clarify it for you:

These are absolutely identical:
void Func1(RECT* Array);
void Func1(RECT Array[]);
void Func1(RECT Array[1000]);

Please use a smaller graphic in your signature.

ToutEnMasm

Hello,
Thanks for help.It seems that i have understand something.
If there is [] after the structure,an array is define and there is no need of * or & because an array can be only pass by adress.
If theris'nt the [],* or & are needed because it is only a structure than can be passed by value or adress.
Am I right ?

u

Here is valid code, study the syntax from it:


short data1[100];
int num1=0;

void func7(short* what){ // the parameter can also be written as "short what[]" or "short what[10]"
//--[ identical ]-------[
what[0]=0;
*what = 0;
//----------------------/
}

void main(){
//--[ identical ]-------[
func7(data1);
func7(&data1[0]);
func7(&data1[num1]);
func7(data1+num1);
func7(data1+0);
//----------------------/


// INVALID!!:
// func7(&data1); // Though, I have a faint memory that this was ok with GCC
}


Maybe if you try these things yourself, with some printf showing addresses and data, you will grasp C pointers/arrays faster.
Please use a smaller graphic in your signature.

ToutEnMasm


Hello,
I have compiled it with VC++ express and here is the explain he give (translation).
//  error C2664: 'func7(&data1)' : It isn't possble to convert the 1 parameter from 'short (*__w64 )[100]'  to  'short *'
//        The pointed type have no relation between them ;The convert need reinterpret_cast, cast of style C  or cast of style function.


ToutEnMasm

Hello,
It's OK now.
I have used several forum and i have received this answer who can interest someone.
Quote
As far as I could get from your post, it seems that you are having a method receiving an array of type D3DVERTEXELEMENT9 where as another method receiving an object of type CLSID as one of its parameters. This is what is defining the pass by value and pass by reference behavior. Arrays are passed by reference only where as for objects you can pass reference too but here you are passing the object itself and not the reference. Hope this clears up things for you.