Nested structures in Visual Studio 2008

Zvekan

Newcomer
I have started to write a raytracing algorithm. Before I have been using Fortran, but I plan to switch to C++.

I have Visual Studio 2008 with SP1 installed. Reading through books and webpages about C++ programing, nesting structures should be trivial. But VS2008 doesn't properly recognize variable types from nested structures. Here is the example:

struct RAY_TYPE
{
int RO(3);
int RD(3);
};


struct RAY_TUBE_TYPE
{
double Amplitude, Phase;
RAY_TYPE Ray;
int Region;
int Trace;
int Proper;
} ;

RAY_TUBE_TYPE Rays;

When looking at the Rays, the type of the R0 and RD variables is ??? and I cannot give them values. What am I doing wrong?
 
Minor update.

It is working if the structure is defined globally before the main{}, but not if the structure is defined right after entering function main.
 
If that's a copy/paste of your code, it shouldn't even compile. "int RO(3)" and "int RD(3)" are not valid member variable declarations.

If you're using the Visual Studio Debugger to view the values of your structures, you must ensure that you've compiled under Debug mode and not Release mode. Debug mode enables extra debug information/checking and disables compiler optimisations so that the debugger can work.
 
Yes, the true code is with [], not ().

I removed the array from the RD and R0 to test it when it is a single variable, and then mistakenly added the wrong brackets while writing this post.

It is complied under Debug mode. I can see values of variables declared in a single (i.e. not nested) structure.

Also, everything works if I declare structures outside the main function, but not if the declaration is inside the main?
 
This is probably a scope issue.

if you have something like

Code:
...
main()
{
     RAY_TUBE_TYPE Rays;
     ....
     castRays(&Rays);
}

castRays(RAY_TUBE_TYPE *psThisRay)
{
      ....
}

The variable Rays will be examinable whilst you are looking at the main function , but once you step into castRays you will not be able to examine Rays because the castRays function does not know anything about the variable Rays, what it knows about is a pointer psThisRay, which just so happens to point to the variable Rays in the main function. This is becuase the Scope of Rays is local to the main function.

If you move the Rays variable to outside of the main function then it has global scope and can be seen by both the main function and the castRays function (and therfore the debugger as well whilst you are in either of these functions).

CC
 
First, thank everyone on reply's.

The funny thing is that it happens when I do not call any functions - but stay in main. Just by allocating a variable

RAY_TUBE_TYPE Rays;

and then updating some variable inside Rays. I can access all variables in "wider" structure but not in nested one (RAY_TYPE).

As this is a small project, I will use global declarations, but it is frustrating when I cannot understand why it doesn't work.

Just one question regarding scoping. Could I declare the structure twice (inside main and castRays) for instance or is the global declaration the only choice?
 
If you declare it twice you will have two seperate copies of the variable Rays. One that exists in main, and one that exists in CastRays.

Try changing your structure definition to
Code:
typedef struct _RAY_TYPE_
{
int RO[3];
int RD[3];
}RAY_TYPE;

CC
 
This works for me, VS2008 was a bit slow at updating intellisene for the Rays varibale but after compiling it once it worked;

Code:
struct RAY_TYPE
{
	int RO[3];
	int RD[3];
};


struct RAY_TUBE_TYPE
{
	double Amplitude, Phase;
	RAY_TYPE Ray;	
	int Region;	
	int Trace;	
	int Proper;	
} ;

RAY_TUBE_TYPE Rays;

int main(int argc, char *argv[])
{
	Rays.Ray.RO;
}

See how you access RO through Ray (of type RAY_TYPE) in the RAY_TUBE_TYPE struct.
 
This is probably a scope issue.

if you have something like

Code:
...
main()
{
     RAY_TUBE_TYPE Rays;
     ....
     castRays(&Rays);
}

castRays(RAY_TUBE_TYPE *psThisRay)
{
      ....
}
The variable Rays will be examinable whilst you are looking at the main function , but once you step into castRays you will not be able to examine Rays because the castRays function does not know anything about the variable Rays, what it knows about is a pointer psThisRay, which just so happens to point to the variable Rays in the main function. This is becuase the Scope of Rays is local to the main function.

If you move the Rays variable to outside of the main function then it has global scope and can be seen by both the main function and the castRays function (and therfore the debugger as well whilst you are in either of these functions).

CC
That's not true. The debugger doesn't care if the pointer actually points to anything - it can still dereference it and give you whatever values are in it because it knows its static type.

In other words, the debugger will have absolutely no trouble with the above.

Just one question regarding scoping. Could I declare the structure twice (inside main and castRays) for instance or is the global declaration the only choice?
Yes. But it won't do anything. You can have as many declarations as you want, as long as you don't violate C++'s One Definition Rule (ODR).

If you declare it twice you will have two seperate copies of the variable Rays. One that exists in main, and one that exists in CastRays.

Try changing your structure definition to
Code:
typedef struct _RAY_TYPE_
{
int RO[3];
int RD[3];
}RAY_TYPE;
CC
No, he won't have 2 separate copies. A struct declaration is not a variable definition. The declaration of the RAY_TYPE or RAY_TUBE_TYPE structures does not constitute the definition of a variable that you can do anything with.

typedef'ing structs should have no impact. It's an anachronism brought over from C because in C, structs have their own namespace and so this typedef mechanism is used to prevent having to place the struct keyword before every definition. It's not required in C++.
 
Last edited by a moderator:
This works for me, VS2008 was a bit slow at updating intellisene for the Rays varibale but after compiling it once it worked;

Code:
struct RAY_TYPE
{
	int RO[3];
	int RD[3];
};


struct RAY_TUBE_TYPE
{
	double Amplitude, Phase;
	RAY_TYPE Ray;	
	int Region;	
	int Trace;	
	int Proper;	
} ;

RAY_TUBE_TYPE Rays;

int main(int argc, char *argv[])
{
	Rays.Ray.RO;
}

See how you access RO through Ray (of type RAY_TYPE) in the RAY_TUBE_TYPE struct.

This works for me also, but you have defined your structures outside main. Try defining them inside. Then I have problems accessing the nested structure variables.
 
One more, more-or-less related question. Can I send a pointer to the undefined structure inside function and then define the structure inside the function. Something like this

Code:
int Ellipse_Ray_Intersect (ELLIPSE_TYPE *Ellipse, RAY_TUBE_TYPE *RayTube, VERTEX_TYPE *Intersection[5], VERTEX_TYPE *Normal[5], double *Distance, int InOut)
{

struct RAY_TUBE_TYPE
{
    double Amplitude, Phase;
	RAY_TYPE *Ray[5];	
	int Region;	
	int Trace;	
	int Proper;	
};

}
 
Yes, you can. You just need a forward declaration of your RAY_TUBE_TYPE structure before the declaration and definition of your function. But why would you want to?

Regardless of where the variable is defined (and where the type of the variable is defined), if it's in scope then it's accessible just fine and the debugger can see it using VS2008 SP1. Show us the exact code you're using, and where you're placing your breakpoint. That means copy and paste it. I cannot emphasise this enough; all too often I encounter people who think they know what's wrong and post completely irrelevant code (or post code with inaccuracies). It makes it hard to diagnose the problem.
 
That's not true. The debugger doesn't care if the pointer actually points to anything - it can still dereference it and give you whatever values are in it because it knows its static type.

In other words, the debugger will have absolutely no trouble with the above.

If he tries to look at the variable that exists in main in the debugger whilst he is in main he will not be able to see it without using the call stack window and moving up the stack into the main function. As he seems to be a bit unfamiliar with C /Visual Studio I thought this would be a bit too much information at one point.

No, he won't have 2 separate copies. A struct declaration is not a variable definition. The declaration of the RAY_TYPE or RAY_TUBE_TYPE structures does not constitute the definition of a variable that you can do anything with.
I read his statement as trying to declare the variable Rays twice. There seemed no point in declaring the structure definition twice.

typedef'ing structs should have no impact. It's an anachronism brought over from C because in C, structs have their own namespace and so this typedef mechanism is used to prevent having to place the struct keyword before every definition. It's not required in C++.
Agreed, it shouldn't have any affect. I thought it worth trying in case he is using a C compiler. Not sure now, but it used to be the case that if you used .c rather than .cpp as your file extension then it would use the C compiler rather than C++. Although to be honest I would expect compiler errors rather than weird debugger behaviour.

CC
 
Code:
#include "stdafx.h"
#include <iostream>
#include <math.h>

using namespace std;

struct RAY_TYPE
{
	double RO[3];
	double RD[3];
};

struct RAY_TUBE_TYPE
{
    double Amplitude, Phase;
	RAY_TYPE Ray[5];	//0 - central ray, 1-4 tube surrounding rays
	int Region;	//Region where ray is currently, 1 free space (source region), 2 (first layer), 3 (second layer)...
	int Trace;	// Flag for determining if ray has no intersections left
	int Proper;	//1 - proper ray, 2 - total inner-reflection
};

struct ELLIPSE_TYPE
{
	double MajorAx;
	double MinorAx;
	double Er;
};
struct VERTEX_TYPE
{
	double x;
	double y;
	double z;
};

int main(int argc, _TCHAR* argv[])
{
	
RAY_TUBE_TYPE *Rays;
ELLIPSE_TYPE *Ellipses;

int NumRays;
int NumEllipse;	

NumRays = 10000;
NumEllipse = 10;

Rays = new RAY_TUBE_TYPE [NumRays];
Ellipses = new ELLIPSE_TYPE [NumEllipse];

Rays[0].Amplitude=(double)1.0;
Rays[0].Ray[0].RD[0]=(double)1.0;

delete Rays;
delete Ellipses;

return 0;
}

This way it works, but if I move the struct definitions inside main it doesn't work. Of course, I remove delete statements when trying to see the variables at the return 0 stage where I have a breakpoint.

It is not that important, I can use global definitions for this assignment.
 
Ah, I see now. The Visual Studio Debugger is having some sort of trouble when dealing with local type definitions. Although I'm not sure why that would be - may be a problem with the debugger.

But in any case, it's idiomatic in both C and C++ to place type definitions at global or namespace scope. Locally scoped type definitions are rare, and I've only ever used them for single-use functors when dealing with the STL.
 
Back
Top