Dynamic indexing (multi-dimensional-indexing) (probably my most important/valuable posting up to thi

S

Skybuck Flying

Yeah this is some very nice code:

Enumerator successfully buid into TDynamicIndex ! ;) =D

alternative version 0.07:

// *** Begin of Test Program ***

program TestProgram;


{$APPTYPE CONSOLE}

{

TDynamicIndex

alternative version 0.06 created on 3 july 2011 by Skybuck Flying.

TDynamicIndex reduced to the most basic/simpelst form so that it can be used
for many other types/arrays and so forth.

Instead TMemory is created which accepts TDynamicIndex as parameters to do
lookups. TMemory also has been made more generic so it can contain
different kinds of types.

A more realistic example.

There might still be room to improve this technique if TDynamicIndex could
be used as the loop variable. This will be examined in a next (alternative)
version ! ;)


(It's all about reducing the ammount of code and keep it as simple and well
readable/understandable/self documenting as possible
with quick insight into what everthing does which is good for algorithm
design/development/inspection)

(re-created from my usenet posting from my archive, delphi overwrite
this example with the project file of another folder ?!
fortunately nothing was lost in the process except this text slightly
reformatted.)

}

{

alternative version 0.07 created on 3 july 2011 by Skybuck Flying.

Very nice :

TDynamicIndex improvements:

+ Build-in support for enumerators
+ Build-in enumerator for TDynamicIndex
+ Implicit conversion to integer (index is returned as integer)
+ Implicit conversion to string (index is returned as string)
+ Additional properties to get value (index) and dimension.

DynamicIndex can now be used in for in loops ! ;) =D

TMemory improvements:
+ memory cleaned up via setting count property to zero


}

uses
SysUtils;

type
{
TDynamicIndexEnumerator = record
private
FArray: TBytes;
FIndex: Integer;
function GetCurrent : integer;
public

end;
}

TDynamicIndex = record
private
mIndex : integer;
mDimension : integer;

function GetCurrent : TDynamicIndex; inline;

function StoreIndex( ParaIndex : integer ) : TDynamicIndex; inline;
public
constructor Create( ParaDimension : integer );

property IndexOperator[ ParaIndex : integer ] : TDynamicIndex read
StoreIndex; default;

property Dimension : integer read mDimension write mDimension;
property Value : integer read mIndex write mIndex;

class operator Multiply( ParaA, ParaB : TDynamicIndex ) : TDynamicIndex;

// enumerator functions
function MoveNext : Boolean; inline;
property Current : TDynamicIndex read GetCurrent;

function GetEnumerator : TDynamicIndex;

// implicit operator so .Value doesn't need to be used when assinging the
dynamic index to an integer ;)
class operator Implicit( ParaDynamicIndex : TDynamicIndex ) : integer;

// another implicit operator so it automatically gets converted to a
string ! ;) :)
class operator Implicit( ParaDynamicIndex : TDynamicIndex ) : string;
end;

constructor TDynamicIndex.Create( ParaDimension : integer );
begin
mIndex := 0;
mDimension := 1;

if ParaDimension > 1 then
begin
mDimension := ParaDimension;
end;
end;

function TDynamicIndex.StoreIndex( ParaIndex : integer ) : TDynamicIndex;
begin
mIndex := ParaIndex;
result.mIndex := mIndex;
result.mDimension := mDimension;
end;

class operator TDynamicIndex.Multiply( ParaA, ParaB : TDynamicIndex ) :
TDynamicIndex;
begin
result.mIndex := ParaA.mIndex + (ParaA.mDimension * ParaB.mIndex);
result.mDimension := ParaA.mDimension * ParaB.mDimension;
end;

function TDynamicIndex.MoveNext : Boolean;
begin
result := false;

mIndex := mIndex + 1;
if mIndex < mDimension then
begin
result := true;
end;
end;

function TDynamicIndex.GetCurrent : TDynamicIndex;
begin
result.mIndex := mIndex;
result.mDimension := mDimension;
end;

function TDynamicIndex.GetEnumerator : TDynamicIndex;
begin
result.mIndex := -1;
result.mDimension := mDimension;
end;

class operator TDynamicIndex.Implicit( ParaDynamicIndex : TDynamicIndex ) :
integer;
begin
result := ParaDynamicIndex.mIndex;
end;

class operator TDynamicIndex.Implicit( ParaDynamicIndex : TDynamicIndex ) :
string;
begin
result := IntToStr( ParaDynamicIndex.mIndex );
end;

type
TMemory<GenericType> = class
private

protected
mMemory : array of GenericType;
mCount : integer;

procedure SetCount( ParaCount : integer );

function GetElement( ParaIndex : TDynamicIndex ) : GenericType;
procedure SetElement( ParaIndex : TDynamicIndex; ParaValue :
GenericType );

public
constructor Create;
destructor Destroy; override;

property Count : integer read mCount write SetCount;

property Element[ ParaIndex : TDynamicIndex ] : GenericType read
GetElement write SetElement; default;
end;

constructor TMemory<GenericType>.Create;
begin
inherited Create;

end;

destructor TMemory<GenericType>.Destroy;
begin
Count := 0;

inherited Destroy;
end;

procedure TMemory<GenericType>.SetCount( ParaCount : integer );
begin
mCount := ParaCount;
SetLength( mMemory, mCount );
end;

function TMemory<GenericType>.GetElement( ParaIndex : TDynamicIndex ) :
GenericType;
begin
result := mMemory[ParaIndex.Value];
end;

procedure TMemory<GenericType>.SetElement( ParaIndex : TDynamicIndex;
ParaValue : GenericType );
begin
mMemory[ParaIndex.Value] := ParaValue;
end;


procedure Main;
var
mBlockCount : integer;
mElementCount : integer;

mMemory : TMemory<integer>;

mBlock : TDynamicIndex;
mElement : TDynamicIndex;

vBlockIndex : TDynamicIndex;
vElementIndex : TDynamicIndex;
begin
// smaller values set to make the program end soon to test clean up too ;)
mBlockCount := 2;
mElementCount := 800;

mMemory := TMemory<integer>.Create;
mMemory.Count := mBlockCount * mElementCount;

// functions as a dimension holder ;)
mBlock := TDynamicIndex.Create( mBlockCount );
mElement := TDynamicIndex.Create( mElementCount );

// functions as index iterators
vBlockIndex := mBlock;
vElementIndex := mElement;

for vBlockIndex in mBlock do
begin
for vElementIndex in mElement do
begin
mMemory[ vBlockIndex * vElementIndex ] := vElementIndex; // nice and
short ! ;)
end;
end;

for vBlockIndex in mBlock do
begin
for vElementIndex in mElement do
begin
writeln( 'BlockIndex: ' + vBlockIndex + ' ElementIndex: ' + vElementIndex
+ ' mMemory: ', mMemory[ vBlockIndex * vElementIndex ] );

// I would still ike to be able to write it like this, but I don't know
if it's possible to make writeln recgonized it
// and how to do it ;) :) the above method is better for dialogs though
;)
// writeln( 'BlockIndex: ', vBlockIndex, ' ElementIndex: ', vElementIndex,
'mMemory: ', mMemory[ vBlockIndex * vElementIndex ] );
end;
end;

mMemory.Free;
end;

begin
try
Main;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
ReadLn;
end.

/// *** End of Test Program ***

Bye,
Skybuck.
 
S

Skybuck Flying

I forgot how important it was to start with the lowest dimension first when
multiplieing dimensions.

This is the only slightly dangerous issue/problem remaining which could
probably be solved by a compiler.

The compiler could perhaps put it in the correct order somehow.

Maybe the programmer would need to indicate the order of the dimensions like
so:

Block.Order := 2;
Element.Order := 1;

Corrected version 0.07 test program:

// *** Begin of Test Program ***

program TestProgram;


{$APPTYPE CONSOLE}

{

TDynamicIndex

alternative version 0.06 created on 3 july 2011 by Skybuck Flying.

TDynamicIndex reduced to the most basic/simpelst form so that it can be used
for many other types/arrays and so forth.

Instead TMemory is created which accepts TDynamicIndex as parameters to do
lookups. TMemory also has been made more generic so it can contain
different kinds of types.

A more realistic example.

There might still be room to improve this technique if TDynamicIndex could
be used as the loop variable. This will be examined in a next (alternative)
version ! ;)


(It's all about reducing the ammount of code and keep it as simple and well
readable/understandable/self documenting as possible
with quick insight into what everthing does which is good for algorithm
design/development/inspection)

(re-created from my usenet posting from my archive, delphi overwrite
this example with the project file of another folder ?!
fortunately nothing was lost in the process except this text slightly
reformatted.)

}

{

alternative version 0.07 created on 3 july 2011 by Skybuck Flying.

Very nice :

TDynamicIndex improvements:

+ Build-in support for enumerators
+ Build-in enumerator for TDynamicIndex
+ Implicit conversion to integer (index is returned as integer)
+ Implicit conversion to string (index is returned as string)
+ Additional properties to get value (index) and dimension.

DynamicIndex can now be used in for in loops ! ;) =D

TMemory improvements:
+ memory cleaned up via setting count property to zero

!!! CAUTION !!!:

It is important to write the lowest dimensions first and the highest
dimensions later
when multiplieing otherwise it won't work properly.

!!!!!!!!!!!!!!!


}


uses
SysUtils;

type
{
TDynamicIndexEnumerator = record
private
FArray: TBytes;
FIndex: Integer;
function GetCurrent : integer;
public

end;
}

TDynamicIndex = record
private
mIndex : integer;
mDimension : integer;

function GetCurrent : TDynamicIndex; inline;

function StoreIndex( ParaIndex : integer ) : TDynamicIndex; inline;
public
constructor Create( ParaDimension : integer );

property IndexOperator[ ParaIndex : integer ] : TDynamicIndex read
StoreIndex; default;

property Dimension : integer read mDimension write mDimension;
property Value : integer read mIndex write mIndex;

class operator Multiply( ParaA, ParaB : TDynamicIndex ) : TDynamicIndex;

// enumerator functions
function MoveNext : Boolean; inline;
property Current : TDynamicIndex read GetCurrent;

function GetEnumerator : TDynamicIndex;

// implicit operator so .Value doesn't need to be used when assinging the
dynamic index to an integer ;)
class operator Implicit( ParaDynamicIndex : TDynamicIndex ) : integer;

// another implicit operator so it automatically gets converted to a
string ! ;) :)
class operator Implicit( ParaDynamicIndex : TDynamicIndex ) : string;
end;

constructor TDynamicIndex.Create( ParaDimension : integer );
begin
mIndex := 0;
mDimension := 1;

if ParaDimension > 1 then
begin
mDimension := ParaDimension;
end;
end;

function TDynamicIndex.StoreIndex( ParaIndex : integer ) : TDynamicIndex;
begin
mIndex := ParaIndex;
result.mIndex := mIndex;
result.mDimension := mDimension;
end;

class operator TDynamicIndex.Multiply( ParaA, ParaB : TDynamicIndex ) :
TDynamicIndex;
begin
result.mIndex := ParaA.mIndex + (ParaA.mDimension * ParaB.mIndex);
result.mDimension := ParaA.mDimension * ParaB.mDimension;
end;

function TDynamicIndex.MoveNext : Boolean;
begin
result := false;

mIndex := mIndex + 1;
if mIndex < mDimension then
begin
result := true;
end;
end;

function TDynamicIndex.GetCurrent : TDynamicIndex;
begin
result.mIndex := mIndex;
result.mDimension := mDimension;
end;

function TDynamicIndex.GetEnumerator : TDynamicIndex;
begin
result.mIndex := -1;
result.mDimension := mDimension;
end;

class operator TDynamicIndex.Implicit( ParaDynamicIndex : TDynamicIndex ) :
integer;
begin
result := ParaDynamicIndex.mIndex;
end;

class operator TDynamicIndex.Implicit( ParaDynamicIndex : TDynamicIndex ) :
string;
begin
result := IntToStr( ParaDynamicIndex.mIndex );
end;

type
TMemory<GenericType> = class
private

protected
mMemory : array of GenericType;
mCount : integer;

procedure SetCount( ParaCount : integer );

function GetElement( ParaIndex : TDynamicIndex ) : GenericType;
procedure SetElement( ParaIndex : TDynamicIndex; ParaValue :
GenericType );

public
constructor Create;
destructor Destroy; override;

property Count : integer read mCount write SetCount;

property Element[ ParaIndex : TDynamicIndex ] : GenericType read
GetElement write SetElement; default;
end;

constructor TMemory<GenericType>.Create;
begin
inherited Create;

end;

destructor TMemory<GenericType>.Destroy;
begin
Count := 0;

inherited Destroy;
end;

procedure TMemory<GenericType>.SetCount( ParaCount : integer );
begin
mCount := ParaCount;
SetLength( mMemory, mCount );
end;

function TMemory<GenericType>.GetElement( ParaIndex : TDynamicIndex ) :
GenericType;
begin
result := mMemory[ParaIndex.Value];
end;

procedure TMemory<GenericType>.SetElement( ParaIndex : TDynamicIndex;
ParaValue : GenericType );
begin
mMemory[ParaIndex.Value] := ParaValue;
end;


procedure Main;
var
mBlockCount : integer;
mElementCount : integer;

mMemory : TMemory<integer>;

mBlock : TDynamicIndex;
mElement : TDynamicIndex;

vBlockIndex : TDynamicIndex;
vElementIndex : TDynamicIndex;
begin
// smaller values set to make the program end soon to test clean up too ;)
mBlockCount := 5;
mElementCount := 20;

mMemory := TMemory<integer>.Create;
mMemory.Count := mBlockCount * mElementCount;

// functions as a dimension holder ;)
mBlock := TDynamicIndex.Create( mBlockCount );
mElement := TDynamicIndex.Create( mElementCount );

// functions as index iterators
vBlockIndex := mBlock;
vElementIndex := mElement;

for vBlockIndex in mBlock do
begin
for vElementIndex in mElement do
begin
mMemory[ vElementIndex * vBlockIndex ] := (vElementIndex *
vBlockIndex).Value; // nice and short ! ;)
end;
end;

for vBlockIndex in mBlock do
begin
for vElementIndex in mElement do
begin
writeln( 'BlockIndex: ' + vBlockIndex + ' ElementIndex: ' + vElementIndex
+ ' mMemory: ', mMemory[ vElementIndex * vBlockIndex ] );

// I would still ike to be able to write it like this, but I don't know
if it's possible to make writeln recgonized it
// and how to do it ;) :) the above method is better for dialogs though
;)
// writeln( 'BlockIndex: ', vBlockIndex, ' ElementIndex: ', vElementIndex,
'mMemory: ', mMemory[ vElementIndex * vBlockIndex ] );
end;
readln;
end;

mMemory.Free;
end;

begin
try
Main;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
ReadLn;
end.

// *** End of Test Program ***

Bye,
Skybuck.
 
S

Skybuck Flying

It's not that hard really, I had some free leisure time and spended it on
implementation it for you since you seem to have troubles thinking about it
and understanding it, granted the original was a bit more complex the
necessary, the C-only example below has been simplified to it's bare
minimum:

I did this for you because your reply seemed to be somewhat sincere,
interested and kind ! ;) =D

// *** Begin of C-only implementation + test Program ***

// ConlyImplementation.cpp : Defines the entry point for the console
application.
//
// TDynamicIndex
//
// C-only-version 0.01 created on 3 july 2011 by Skybuck Flying
//
// Note: dynamic indexes must be supplied from lowest to highest dimension
in the call to MultiplyDynamicIndexes.
//

#include "stdafx.h"
#include <stdarg.h>
#include <stdlib.h>

struct TDynamicIndex
{
int mIndex;
int mDimension;
};

TDynamicIndex CreateDynamicIndex( int ParaDimension )
{
struct TDynamicIndex result;

result.mIndex = 0;
result.mDimension = 1;

if (ParaDimension > 1)
{
result.mDimension = ParaDimension;
}

return result;
}

TDynamicIndex MultiplyDynamicIndexes( int ParaCount, ... )
{
struct TDynamicIndex vResult;
struct TDynamicIndex vOperand;
int vIndex;
va_list vParameterList;

if (ParaCount > 0)
{
va_start( vParameterList, ParaCount );

vResult = va_arg( vParameterList, struct TDynamicIndex );

if (ParaCount > 1)
{
for (vIndex = 1; vIndex < ParaCount; vIndex++)
{
vOperand = va_arg( vParameterList, struct TDynamicIndex );
vResult.mIndex = vResult.mIndex + (vResult.mDimension *
vOperand.mIndex);
vResult.mDimension = vResult.mDimension * vOperand.mDimension;
}
}

va_end( vParameterList );
}

return vResult;
}

int _tmain(int argc, _TCHAR* argv[])
{
int *mMemory;

struct TDynamicIndex mWorld;
struct TDynamicIndex mBlock;
struct TDynamicIndex mElement;

mWorld = CreateDynamicIndex( 3 );
mBlock = CreateDynamicIndex( 5 );
mElement = CreateDynamicIndex( 20 );

mMemory = (int *) (malloc( mWorld.mDimension * mBlock.mDimension *
mElement.mDimension * sizeof(int) ));

struct TDynamicIndex mLinearIndex;

// small little example
/*
mLinearIndex = MultiplyDynamicIndexes( 3, mElement, mBlock, mWorld );

printf("%d %d \n", mLinearIndex.mDimension, mLinearIndex.mIndex );
*/

// big example:

// fill memory any way you want, here the linear index is filled to show it
later on.
for (mWorld.mIndex = 0; mWorld.mIndex < mWorld.mDimension; mWorld.mIndex++)
{
for (mBlock.mIndex = 0; mBlock.mIndex < mBlock.mDimension;
mBlock.mIndex++)
{
for (mElement.mIndex = 0; mElement.mIndex < mElement.mDimension;
mElement.mIndex++)
{
mLinearIndex = MultiplyDynamicIndexes( 3, mElement, mBlock, mWorld );
mMemory[ mLinearIndex.mIndex ] = mLinearIndex.mIndex;
}
}
}

// show linear index per world, block, element
for (mWorld.mIndex = 0; mWorld.mIndex < mWorld.mDimension; mWorld.mIndex++)
{
for (mBlock.mIndex = 0; mBlock.mIndex < mBlock.mDimension;
mBlock.mIndex++)
{
for (mElement.mIndex = 0; mElement.mIndex < mElement.mDimension;
mElement.mIndex++)
{
mLinearIndex = MultiplyDynamicIndexes( 3, mElement, mBlock, mWorld );
printf("World: %d mBlock: %d mElement: %d mMemory: %d \n",
mWorld.mIndex, mBlock.mIndex, mElement.mIndex, mMemory[
mLinearIndex.mIndex ] );
}
}
}

free( mMemory );

return 0;
}

// *** End of C-only implementation + test Program ***

(As far as I know Delphi probably doesn't have such open parameters, but I
might be wrong ;) so I implemented it directly into C).

Bye,
Skybuck.
 
S

Skybuck Flying

N

Nick Keighley

"Billy Mays"  wrote in messageOn 7/1/2011 12:18 AM, Skybuck Flying wrote:



"
Unless you have a question or a C program, please don't post to c.l.c
"

I have a question for you:

Are there C compilers which were written in C++ ?

very likely. Many implementations provide both C and C++ bundled
together (eg. Microsoft, gcc). It would make sense to share some of
the code. It's likely the C++ is largely written in C++ so likely at
least some of the C compiler is written in C++. Things like exceptions
look handy for compiler writers.

So what? Why do you care if a C compiler is written in C++?
 
N

Nick Keighley

On Jul 2, 7:04 am, "Skybuck Flying" <[email protected]>
wrote:

please use standard quoting conventions. Please leave attributions in

However I do not know how to configure Visual Studio 2010 to allow C only..

Visual Studio automatically compiles files with .c extensions as C.

Furthermore it seems a bit a waste of time at least for me, perhaps not for
others which might be stuck using C compilers.

I don't think they think they are "stuck" with a C compiler. If you
want to post C++ programs why not post them to comp.lang.c++?


<snip>
 
S

Skybuck Flying

Ok thanks,

Here is the code modified to be truely C only ;)

I'm a little bit surprised that /* */ is allowed in C or vice versa //

A long time ago I guess // wasn't allowed in C ?!

// *** Begin of Test Program ***

// ConlyImplementation.c : Defines the entry point for the console
application.
//
// TDynamicIndex
//
// C-only-version 0.01 created on 3 july 2011 by Skybuck Flying
//
// Note: dynamic indexes must be supplied from lowest to highest dimension
in the call to MultiplyDynamicIndexes.
//
// Updated on 4 july 2011 by Skybuck Flying to be really C only
//
// Simply rename *.cpp to *.c to compile in C-only mode in Visual Studio
2010
//
// Also disable "compile with pre-compiled-headers" by setting project
option to c/c++->pre compiled headers (first one) to "Not Using Precompiled
Headers".
// This will allow mixing *.cpp and *.c files...
//

// #include "stdafx.h"
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>


struct TDynamicIndex
{
int mIndex;
int mDimension;
};

struct TDynamicIndex CreateDynamicIndex( int ParaDimension )
{
struct TDynamicIndex result;

result.mIndex = 0;
result.mDimension = 1;

if (ParaDimension > 1)
{
result.mDimension = ParaDimension;
}

return result;
}

struct TDynamicIndex MultiplyDynamicIndexes( int ParaCount, ... )
{
struct TDynamicIndex vResult;
struct TDynamicIndex vOperand;
int vIndex;
va_list vParameterList;

if (ParaCount > 0)
{
va_start( vParameterList, ParaCount );

vResult = va_arg( vParameterList, struct TDynamicIndex );

if (ParaCount > 1)
{
for (vIndex = 1; vIndex < ParaCount; vIndex++)
{
vOperand = va_arg( vParameterList, struct TDynamicIndex );
vResult.mIndex = vResult.mIndex + (vResult.mDimension *
vOperand.mIndex);
vResult.mDimension = vResult.mDimension * vOperand.mDimension;
}
}

va_end( vParameterList );
}

return vResult;
}

//int _tmain(int argc, _TCHAR* argv[])
int main(int argc, char *argv[])
{
int *mMemory;

struct TDynamicIndex mWorld;
struct TDynamicIndex mBlock;
struct TDynamicIndex mElement;

struct TDynamicIndex mLinearIndex;

mWorld = CreateDynamicIndex( 3 );
mBlock = CreateDynamicIndex( 5 );
mElement = CreateDynamicIndex( 20 );

mMemory = (int *) (malloc( mWorld.mDimension * mBlock.mDimension *
mElement.mDimension * sizeof(int) ));


// small little example
/*
mLinearIndex = MultiplyDynamicIndexes( 3, mElement, mBlock, mWorld );

printf("%d %d \n", mLinearIndex.mDimension, mLinearIndex.mIndex );
*/

// big example:

// fill memory any way you want, here the linear index is filled to show it
later on.
for (mWorld.mIndex = 0; mWorld.mIndex < mWorld.mDimension; mWorld.mIndex++)
{
for (mBlock.mIndex = 0; mBlock.mIndex < mBlock.mDimension;
mBlock.mIndex++)
{
for (mElement.mIndex = 0; mElement.mIndex < mElement.mDimension;
mElement.mIndex++)
{
mLinearIndex = MultiplyDynamicIndexes( 3, mElement, mBlock, mWorld );
mMemory[ mLinearIndex.mIndex ] = mLinearIndex.mIndex;
}
}
}

// show linear index per world, block, element
for (mWorld.mIndex = 0; mWorld.mIndex < mWorld.mDimension; mWorld.mIndex++)
{
for (mBlock.mIndex = 0; mBlock.mIndex < mBlock.mDimension;
mBlock.mIndex++)
{
for (mElement.mIndex = 0; mElement.mIndex < mElement.mDimension;
mElement.mIndex++)
{
mLinearIndex = MultiplyDynamicIndexes( 3, mElement, mBlock, mWorld );
printf("World: %d mBlock: %d mElement: %d mMemory: %d \n",
mWorld.mIndex, mBlock.mIndex, mElement.mIndex, mMemory[
mLinearIndex.mIndex ] );
}
}
}

free( mMemory );

return 0;
}

// *** End of Test Program ***

Bye,
Skybuck.
 
S

Skybuck Flying

I have converted most of the Delphi example to C++ but it's so horrible I
dare not to post it ! LOl.

It's not me but C++ which is just horrible and buggy prone.

This has pretty much convinced me that pascal/delphi for ptx/cuda is
necessary at least from a language point of view.

I am not yet sure if cuda provides better performance than cpu, so I still
have to figure that out... for now these codes will probably do in
combination with others.

Now I go try and find out where this horrible humming is coming from ?!
Probably some machine outside...

Bye,
Skybuck.
 
R

Robert Miles

"
I'd enjoy seeing your implementation in C, if you please. :)
"

a C version can probably be made with "variadic" functions:

http://en.wikipedia.org/wiki/Variadic_function

However I do not know how to configure Visual Studio 2010 to allow C only.

Judging by my experiences with Microsoft Visual C++, the first
step is to make sure that you have a paid version, since the
free version is likely to be missing something needed in order
to be able to compile C at all.
 
R

Robert Miles

Ok thanks,

Here is the code modified to be truely C only ;)

I'm a little bit surprised that /* */ is allowed in C or vice versa //

A long time ago I guess // wasn't allowed in C ?!

A number of things have changed over the years when
going from one version of the C standard to another.
 
B

Bill Reid

Judging by my experiences with Microsoft Visual C++, the first
step is to make sure that you have a paid version, since the
free version is likely to be missing something needed in order
to be able to compile C at all.

Uh...no..."Express" compiles C code just fine, aside from
some irritation when it complains about "unsafe" library
functions...what's missing from the free versions are some
higher-level abilities to create custom "packages" and
whatnot or whatever...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,085
Messages
2,570,597
Members
47,219
Latest member
Geraldine7

Latest Threads

Top