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
"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
> 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
"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
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.
"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.
> >>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
"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
> > 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
"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
This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
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;
|
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
|
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.
|
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?
|
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...
| |
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...
|
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...
|
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,...
|
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...
|
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...
|
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...
| |
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
|
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...
| |