473,796 Members | 2,464 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Structs

Can anyone explain the logic behind structs being allowed neither memeber
initialisers or default constructors.

Doesn't this just encourage developers to create constructors with dummy
arguments?

Thanks in advance,

Jasper Kent.
Nov 16 '05
19 2128
> A struct is created, generally, in null memory. I'm pretty sure the .NET
memory model ensures that a variable created on the stack retains a zero
value, even if its unassigned. I could be wrong but it would seem unlikely.

No. Locals and structs are created on the stack which does *not* contain
zeros, but instead data of previous method invocations.
If a method returns it would have to overwrite the stack with zeros to clean
up, if you want the behavour that every struct is generated in "null
memory".

C# forces you to initialize *every* local variable completely before first
use. In the case of structs a ctor call is not needed if you assign all
fields manually.
The difference in
Point p;

and
Point p = new Point();

is new Point() issues an initobj instruction in IL. That initobj instruction should zero memory in most case(structs written in other languages may not
zero, AFAICT), however the original structure on the stack should already be zeroed(someone correct me if I am wrong, I'm pretty sure I'm not though).
Your example does indeed zero twice: once explicitly(duri ng new Point()) and once implicitly at stack construction. In that case I would expect the JIT
to effectivly remove the initobj instruction whenever it knows that the
initalization is pointless. new Point() would be more valuable when the
value in p has been used. It would clear that value back out.
Think: Would the initobj call would make sense in any circumstance when
structs would already zeroed out a creation time?
As a matter of technical fact, I don't believe that its required to init a
struct before use. C# tends to disallow it, however, under assignment
rules(I've run into one situation where it seems to be allowed, which I have to check on). I think that is more for the purposes of correct, well though out code more so than it is a problem with the underlying platform.


Which situation? I'd like to hear.

--
cody

Freeware Tools, Games and Humour
http://www.deutronium.de.vu || http://www.deutronium.tk
Nov 16 '05 #11
"cody" <no************ ****@gmx.net> wrote in message
news:uz******** ******@TK2MSFTN GP11.phx.gbl...
A struct is created, generally, in null memory. I'm pretty sure the .NET
memory model ensures that a variable created on the stack retains a zero
value, even if its unassigned. I could be wrong but it would seem unlikely.

No. Locals and structs are created on the stack which does *not* contain
zeros, but instead data of previous method invocations.
If a method returns it would have to overwrite the stack with zeros to
clean
up, if you want the behavour that every struct is generated in "null
memory".

That is partially incorrect, as was my original statement.

[quote from CIL Partition 1, page 87 of the MSWord version]
A local variable may hold any data type. However, a particular slot shall
be used in a type consistent way (where the type system is the one described
in clause 11.3.2.1). Local variables are initialized to 0 before entry if
the initialize flag for the method is set (see Section 11.2). The address
of an individual local variable may be taken using the ldloca instruction.
[end quote]

Note "Local variables are initialized to 0 before entry if the initalize
flag for the method is set". This shows that variables are initalized to 0
in almost every case(I've *NEVER* seen IL without that flag), and in this
case the C# compiler generates superflous code with the initobj instruction.
So, indeed, there is generally no reason to do this(and, actually, reference
variables will always be null at calltime, both in and outside of valuetypes
on the stack). Other tests have shown that booleans are set to false as
well(I've yet to manage to make it have a different value). I do wonder
about performance here...it seems to me that it would be as or perhaps more
efficient to zero the small local block(which is almost always small) than
it would be to analyze the local block and zero out only select fields. That
does seem odd to me.

Also, this same document virtualizes the stack as a singly linked list,
meaning that there is no apparent explicit requirement for saving stack
frames in any given place or for using a traditional growing stack. While I
do think the current implementation does use that for ease of implementation
reasons, it isn't definite and assuming that a new stack frame would exist
where an old one did will probably be incorrect at some point.
C# forces you to initialize *every* local variable completely before first
use. In the case of structs a ctor call is not needed if you assign all
fields manually.

Yes, but I don't think it has much to do with the underlying system as much
as clean coding. Forcing explicit definition forces you to know what is
assigned(and makes life easier since you don't have to worry about the
differing defaults that can come up). The CLR doesn't require it, its
strictly a convention forced by C#(which also sets the init flag, causing
double zeroing). Also, while this looks like a constructor call, it isn't,
its C# sugar(at least in most cases, I havn't tested valuetypes with default
constructors. C++ should allow this, but it may or may not be consumable by
C#). For a value type, a call instruction is issued to call the constructor,
vs a newobj instruction which is used for a reference type. The entire
purpose of initobj is to initalize to zero\null\0.0\f alse(although for
pimatives like bool, the C# compiler emits ldc.i4.0 instead of initobj).

Think: Would the initobj call would make sense in any circumstance when
structs would already zeroed out a creation time?
No, but its there, one would hope the JIT would ignore it. This is an
artifiact of the compiler. I would assume the C# compiler flow control
doesn't interlink with the codegen, the compiler doesn't explicitly need to
emit initobj because it sets the local init flag, however instead of
attempting an optimization of tracking variable usage and deciding when to
issue the initobj instruction, the compiler prefers to do a literal(and
simplier) translation of your code and emits the initobj instruction.
However, due to some strange inconsistencies in the runtime, there is a
chance that initobj is needed in the case you are using strange valuetypes.
As a matter of technical fact, I don't believe that its required to init
a
struct before use. C# tends to disallow it, however, under assignment
rules(I've run into one situation where it seems to be allowed, which I have
to check on). I think that is more for the purposes of correct, well

though
out code more so than it is a problem with the underlying platform.


Which situation? I'd like to hear.


There isn't one, per se. It is either 1) a bug in this complier or 2) the
convention is being dropped. Sometime in the near future I'll make an
inquiry about that, but its irrelevent right now.

Now, if you have proof(empirical , anecdotal, or documented) of an error
here, I am quite interested. The docs aren't particularly clear and my
reading may or may not be correct. I am not interested in C++ or x86's
memory or call models however.
--
cody

Freeware Tools, Games and Humour
http://www.deutronium.de.vu || http://www.deutronium.tk

Nov 16 '05 #12
> No, but its there, one would hope the JIT would ignore it. This is an
artifiact of the compiler. I would assume the C# compiler flow control
doesn't interlink with the codegen, the compiler doesn't explicitly need to emit initobj because it sets the local init flag, however instead of
attempting an optimization of tracking variable usage and deciding when to
issue the initobj instruction, the compiler prefers to do a literal(and
simplier) translation of your code and emits the initobj instruction.
However, due to some strange inconsistencies in the runtime, there is a
chance that initobj is needed in the case you are using strange

valuetypes.
What do you mean with strange valuetype?

--
cody

[Freeware, Games and Humor]
www.deutronium.de.vu || www.deutronium.tk
Nov 16 '05 #13

"cody" <pl************ *************@g mx.de> wrote in message
news:uK******** ******@TK2MSFTN GP12.phx.gbl...
No, but its there, one would hope the JIT would ignore it. This is an
artifiact of the compiler. I would assume the C# compiler flow control
doesn't interlink with the codegen, the compiler doesn't explicitly need to
emit initobj because it sets the local init flag, however instead of
attempting an optimization of tracking variable usage and deciding when
to
issue the initobj instruction, the compiler prefers to do a literal(and
simplier) translation of your code and emits the initobj instruction.
However, due to some strange inconsistencies in the runtime, there is a
chance that initobj is needed in the case you are using strange

valuetypes.
What do you mean with strange valuetype?


Well, the document doesn't explicitly state that it zeroes byte or IntPtr,
so that may be an issue. Also, treatment of enums, DateTime or other system
provided value types aren't explicitly defined. One would assume that the
fields are treated as any other value is, but I don't want to explicitly
state that they behave one way without being able to find definite
documentation.

It also covers any value type with unique charactersitics that I'm not
thinking of or don't know of. Things like TypedReference or Nullable<T> in
2.0 may or may not have special behaviour\tream ent that I don't know
of(those are just examples of value types that could potentially have
different behavior at the language or runtime level, I doubt they have any
particular special behavior but I don't know.). While its nice to assume
there are no edge cases, until I find documentation(o r a knowledgable member
of the design team) that can say there aren't, I don't want to make that
assumption.

Hence, strange value types. Valuetypes that don't behave like others.
Whether they exist or not is difficult to say...they may or may not today
and they may or may not someday. If one exists now...I wouldn't even be
comfortable saying that it'll exist in the next framework. If one exists, it
may well be entirely invisible to user mode code as well, making it
literally undectable without digging through the source of the CLR. Its just
too transient and implementation specific, I think, but its a minor case I
would worry about if I was writing a paper on this issue.
--
cody

[Freeware, Games and Humor]
www.deutronium.de.vu || www.deutronium.tk

Nov 16 '05 #14
Daniel,
Note "Local variables are initialized to 0 before entry if the initalize
flag for the method is set". This shows that variables are initalized to 0
in almost every case(I've *NEVER* seen IL without that flag), and in this
case the C# compiler generates superflous code with the initobj instruction.


If you compile with /unsafe, no methods have the initlocals flag.

Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Nov 16 '05 #15

"Mattias Sjögren" <ma************ ********@mvps.o rg> wrote in message
news:uz******** ******@TK2MSFTN GP12.phx.gbl...
Daniel,
Note "Local variables are initialized to 0 before entry if the initalize
flag for the method is set". This shows that variables are initalized to 0
in almost every case(I've *NEVER* seen IL without that flag), and in this
case the C# compiler generates superflous code with the initobj
instruction .
If you compile with /unsafe, no methods have the initlocals flag.


Really now, that seems a touch odd. One would think it would only happen in
methods that use unsafe code.

Thanks for the info, thats probably yet another reason to avoid compiling
with /unsafe except when absolutly nessecery.
Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.

Nov 16 '05 #16
> >>Note "Local variables are initialized to 0 before entry if the initalize
flag for the method is set". This shows that variables are initalized to 0in almost every case(I've *NEVER* seen IL without that flag), and in thiscase the C# compiler generates superflous code with the initobj
instruction .
If you compile with /unsafe, no methods have the initlocals flag.


Really now, that seems a touch odd. One would think it would only happen

in methods that use unsafe code.

Thanks for the info, thats probably yet another reason to avoid compiling
with /unsafe except when absolutly nessecery.

C# enforces you to intialialize *all* locals anyway. If his statement is
really true (I'll try it),
compiling with unsafe could lead to higher performance.
But I expect this to be true only in unsafe code blocks, not the entire
assembly.

--
cody

Freeware Tools, Games and Humour
http://www.deutronium.de.vu || http://www.deutronium.tk
Nov 16 '05 #17

"cody" <no************ ****@gmx.net> wrote in message
news:e0******** ******@tk2msftn gp13.phx.gbl...
>>Note "Local variables are initialized to 0 before entry if the
>>initalize
>>flag for the method is set". This shows that variables are initalized
>>to 0 >>in almost every case(I've *NEVER* seen IL without that flag), and in this >>case the C# compiler generates superflous code with the initobj
>>instruction .
>
> If you compile with /unsafe, no methods have the initlocals flag.
Really now, that seems a touch odd. One would think it would only happen

in
methods that use unsafe code.

Thanks for the info, thats probably yet another reason to avoid compiling
with /unsafe except when absolutly nessecery.

C# enforces you to intialialize *all* locals anyway. If his statement is
really true (I'll try it),
compiling with unsafe could lead to higher performance.


I wouldn't count on it. The JIT is a factor here that you are ignoring. It
should be capable of detecting useless assignments like that. Beyond that,
the assignment time should be less than a fraction of a percent of execution
time. Even if unsafe changes performance, I think it'd be so utterly
indetectable, it would be entirely wasteful to do so. There is a chance that
if the JIT catches the situation where this code may be slower, if
initalization at call frame build time is faster than at runtime during
instruction execution.

I'm looking forward to your results.
But I expect this to be true only in unsafe code blocks, not the entire
assembly.
--
cody

Freeware Tools, Games and Humour
http://www.deutronium.de.vu || http://www.deutronium.tk

Nov 16 '05 #18
> > C# enforces you to intialialize *all* locals anyway. If his statement is
really true (I'll try it),
compiling with unsafe could lead to higher performance.
I wouldn't count on it. The JIT is a factor here that you are ignoring. It
should be capable of detecting useless assignments like that. Beyond that,
the assignment time should be less than a fraction of a percent of

execution time. Even if unsafe changes performance, I think it'd be so utterly
indetectable, it would be entirely wasteful to do so. There is a chance that if the JIT catches the situation where this code may be slower, if
initalization at call frame build time is faster than at runtime during
instruction execution.

I'm looking forward to your results.

I now tried it and that are my results:

unsafe long Test()
{
long a=0;
long b=0;
long c=0;
long d=0;
long e=0;
long f=0;
long g=0;
long h=0;
return a+b+c+d+e+f+g+h ;
}

// release, no ide 0,8692856
// debug, no ide 0,8926981
// release, ide 5,033917
// debug, ide 5,515041

safe or unsafe appeared to change nothing. but I found running the app
outside the ide was 5,5 times faster.
the release mode was always slightly fast than debug mode in both ide and
without ide.

So I do not believe that the unsafe modifier affects initialisation of
variables.

--
cody

[Freeware, Games and Humor]
www.deutronium.de.vu || www.deutronium.tk
Nov 16 '05 #19

"cody" <pl************ *************@g mx.de> wrote in message
news:u0******** ******@tk2msftn gp13.phx.gbl...
> C# enforces you to intialialize *all* locals anyway. If his statement
> is
> really true (I'll try it),
> compiling with unsafe could lead to higher performance.
I wouldn't count on it. The JIT is a factor here that you are ignoring.
It
should be capable of detecting useless assignments like that. Beyond
that,
the assignment time should be less than a fraction of a percent of

execution
time. Even if unsafe changes performance, I think it'd be so utterly
indetectable, it would be entirely wasteful to do so. There is a chance

that
if the JIT catches the situation where this code may be slower, if
initalization at call frame build time is faster than at runtime during
instruction execution.

I'm looking forward to your results.

I now tried it and that are my results:

unsafe long Test()
{
long a=0;
long b=0;
long c=0;
long d=0;
long e=0;
long f=0;
long g=0;
long h=0;
return a+b+c+d+e+f+g+h ;
}

// release, no ide 0,8692856
// debug, no ide 0,8926981
// release, ide 5,033917
// debug, ide 5,515041

safe or unsafe appeared to change nothing. but I found running the app
outside the ide was 5,5 times faster.
the release mode was always slightly fast than debug mode in both ide and
without ide.

So I do not believe that the unsafe modifier affects initialisation of
variables.


About what I expected. Even if the init flag isn't set, I'm pretty sure the
JIT would equalize the two situations. And, as I've said, if not, its
probably not significant enough to matter.
--
cody

[Freeware, Games and Humor]
www.deutronium.de.vu || www.deutronium.tk

Nov 16 '05 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
3132
by: Paminu | last post by:
Why make an array of pointers to structs, when it is possible to just make an array of structs? I have this struct: struct test { int a; int b;
5
2920
by: Bilgehan.Balban | last post by:
Hi, I am currently brushing up my c++ knowledge and I would like to ask you about the differences between classes and C structs, in the function/method perspective. 1) Is it correct to say that, a structure definition that includes function pointers only defines the function prototypes to be used with them, but not the actual implementations, whereas in C++, member functions cannot be changed *unless* virtual functions are used, or the
61
3783
by: Marty | last post by:
I am new to C# and to structs so this could be easy or just not possible. I have a struct defined called Branch If I use Branch myBranch = new Branch(i); // everything works If I use Branch (myBranch + x) = new Branch(i); // it doesn't x is a loop iterator, i is an int for the constructor to define an array. What am I doing wrong here.
29
2792
by: Dom | last post by:
I'm really confused by the difference between a Struct and a Class? Sometimes, I want just a group of fields to go together. A Class without methods seems wrong, in that it carries too much overhead (I think). A Struct seems more appropriate. At least it is what I would have used in other languages. But since a Struct *can* hold methods, I wander if I am saving anything. If not, why use it?
43
3840
by: JohnQ | last post by:
Are a default constructor, destructor, copy constructor and assignment operator generated by the compiler for a struct if they are not explicitely defined? I think the answer is yes, because "there is no difference between a struct and a class except the public/private access specification" (and a few minor other things). When I create a class, I always start by declaring the default constructor, copy constructor and assignment operator...
0
10456
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10230
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10174
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10012
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9052
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7548
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5575
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3731
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2926
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.