Creating anonymous local variables on-the-fly and more...

G

giuseppe.greco

Hi guys,

Given the following structure

typedef struct _MyStruct
{
int a;
int b;
} MyStruct;

.... end the following function

void foo(MyStruct *myStruct)
{
...
}

is it possible to implement something like

int main()
{
/* traditional way */
MyStruct s = {1, 2};
foo(&s); /* OK */

/* instead of declaring the local variable s, my_macro should
automatically create
a MyStruct variable onto the stack and return its address; is
that possible?
*/
foo(my_macro(1, 2)); /* How? Is that possible? */
}

Thanks,
j3d.
 
C

Chris Thomasson

Hi guys,

Given the following structure [...]

... end the following function [...]

is it possible to implement something like
[...]

I have no idea why you want to do that. Anyhow, this is basically all I can
think of for now:


__________________________

typedef struct _MyStruct {
int a;
int b;
} MyStruct;

void foo(MyStruct *myStruct) {

}

#define MY_MACRO(mp_func, mp_sinit) { \
MyStruct Temp = mp_sinit(); \
foo(&Temp); \
}


int main(void) {
#define FOO_SINIT() {1, 2}
MY_MACRO(foo, FOO_SINIT);
return 0;
}

__________________________


Weird...
 
C

Chris Thomasson

[...]
__________________________
[...]

#define MY_MACRO(mp_func, mp_sinit) { \
MyStruct Temp = mp_sinit(); \
foo(&Temp); \
}

oops! that should read as:


#define MY_MACRO(mp_func, mp_sinit) { \
MyStruct Temp = mp_sinit(); \
mp_func(&Temp); \
}


[...]
__________________________

Sorry for any confusion.
 
M

Mark Bluemel

Hi guys,

Given the following structure

typedef struct _MyStruct
{
int a;
int b;
} MyStruct;

... end the following function

void foo(MyStruct *myStruct)
{
...
}

is it possible to implement something like

int main()
{
/* traditional way */
MyStruct s = {1, 2};
foo(&s); /* OK */

/* instead of declaring the local variable s, my_macro should
automatically create
a MyStruct variable onto the stack and return its address; is
that possible?
*/
foo(my_macro(1, 2)); /* How? Is that possible? */
}

Apart from Chris Thomasson's suggestion, which has its own problems
(name clashes between the temporary variable and other variables; what
if you want to use the results of the call to foo()?; etc.), I can think
of no way to do what you want in C.

Perhaps you'd like to explain what you are trying to achieve and we may
have some other suggestions.
 
D

Duncan Muirhead

Hi guys,

Given the following structure

typedef struct _MyStruct
{
int a;
int b;
} MyStruct;

... end the following function

void foo(MyStruct *myStruct)
{
...
}

is it possible to implement something like

int main()
{
/* traditional way */
MyStruct s = {1, 2};
foo(&s); /* OK */

/* instead of declaring the local variable s, my_macro should
automatically create
a MyStruct variable onto the stack and return its address; is
that possible?
*/
foo(my_macro(1, 2)); /* How? Is that possible? */
}

Thanks,
j3d.
Is this use of compound literals C99, or just a GCC extension?
#include <stdio.h>
#include <stdlib.h>

typedef struct { int a; double b; } bob;

int a( bob* S) { return S->a;}

int main( int argc, char** argv)
{
printf( "%d\n", a( &(bob){17,3.1}));
return EXIT_SUCCESS;
}
 
M

Mark Bluemel

Duncan said:
typedef struct _MyStruct ....
is it possible to implement something like

int main()
{ ....
/* instead of declaring [a] local variable, my_macro should
automatically create
a MyStruct variable onto the stack and return its address; is
that possible?
*/
foo(my_macro(1, 2)); /* How? Is that possible? */
}
Is this use of compound literals C99, or just a GCC extension? ....
typedef struct { int a; double b; } bob; ....

printf( "%d\n", a( &(bob){17,3.1}));


I'm not up on C99, but my quick scan of the specification suggests this
is valid. Others can comment on whether you should rely on C99 features...
 
G

giuseppe.greco

Is this use of compound literals C99, or just a GCC extension?
#include <stdio.h>
#include <stdlib.h>

typedef struct { int a; double b; } bob;

int a( bob* S) { return S->a;}

int main( int argc, char** argv)
{
printf( "%d\n", a( &(bob){17,3.1}));
return EXIT_SUCCESS;



}- Hide quoted text -

- Show quoted text -- Hide quoted text -

- Show quoted text -

Yeah, that's exactly what I wanted... and it runs!

For instance, I'm writing an object-oriented C library and I use to
define object structures in the source files, while header files just
contain a statement like "typedef _MyType MyType". That means that for
each type I define, I have to provide a function that actually creates
it (e.g. MyType * mylib_mytpye_new()). I was just looking for a
mechanism to avoid heap allocations in some circumstances. That's it.

Anyway, many thanks for your help,
j3d.
 
C

cr88192

Yeah, that's exactly what I wanted... and it runs!

For instance, I'm writing an object-oriented C library and I use to
define object structures in the source files, while header files just
contain a statement like "typedef _MyType MyType". That means that for
each type I define, I have to provide a function that actually creates
it (e.g. MyType * mylib_mytpye_new()). I was just looking for a
mechanism to avoid heap allocations in some circumstances. That's it.

note that if you intend to return said values, then it is not valid to
return things on the stack.

partial reason:
there is nothing to say that the stack wont expand again and randomly thrash
your data.


now, what I do:
I narrow the problem to things where I would have to use a heap (of some
sort, I often implement customized memory managers, which are often garbage
collectors), and where one can get by with purely temporary memory.


in this latter case (the memory is only temporary, but should probably last
at least until I am done with it...), I tend to implement what I call a
"rotating allocator".

basically:
I allocate some chunk of memory (say, 64KiB, 256KiB, or 1MiB, for good
measure);
I retain a pointer into the chunk of memory;
as I allocate, I slide along this pointer, and if an allocation would cross
the end, the pointer is reset back to the start again (no allocations are
remembered, so I simply overwrite any old data...).

usually, I try to keep the number of such allocators small, in order to
avoid using too much extra memory...


I often use this kind of setup for temporary strings, string buffers, and
similar. if the data needs any real 'permanence', I transfer it to an actual
heap.

or such...
 
J

Jack Klein

Hi guys,

Given the following structure

typedef struct _MyStruct

First of all, don't do this. You have no right to define an
identifier '_MyStruct', you are invading the implementation's
namespace.

All identifiers beginning with two underscores, or an underscore
followed by an upper case letter (as in '_MyStruct') are reserved for
the implementation in all contexts.

In general, avoid defining any identifiers beginning with an
underscore. Quite a few other such patterns are reserved in certain
sets of circumstances. I can remember all the rules, and I still
don't ever use leading underscores.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 
G

giuseppe.greco

note that if you intend to return said values, then it is not valid to
return things on the stack.

partial reason:
there is nothing to say that the stack wont expand again and randomly thrash
your data.

now, what I do:
I narrow the problem to things where I would have to use a heap (of some
sort, I often implement customized memory managers, which are often garbage
collectors), and where one can get by with purely temporary memory.

in this latter case (the memory is only temporary, but should probably last
at least until I am done with it...), I tend to implement what I call a
"rotating allocator".

basically:
I allocate some chunk of memory (say, 64KiB, 256KiB, or 1MiB, for good
measure);
I retain a pointer into the chunk of memory;
as I allocate, I slide along this pointer, and if an allocation would cross
the end, the pointer is reset back to the start again (no allocations are
remembered, so I simply overwrite any old data...).

usually, I try to keep the number of such allocators small, in order to
avoid using too much extra memory...

I often use this kind of setup for temporary strings, string buffers, and
similar. if the data needs any real 'permanence', I transfer it to an actual
heap.

or such...




- Show quoted text -- Hide quoted text -

- Show quoted text -

I understand what you mean, but let me explain what I'm doing...

I'm implementing a String class and, of course, I provide some
functions to create and manipulate it:

GekkotaString* gekkota_string_new();
....
int32_t gekkota_string_append(GekkotaString *string, const
GekkotaString *value);
int32_t gekkota_string_insert(GekkotaString *string, const
GekkotaString *value, int32_t index);
....

The first parameter always refers the object being manipulated, while
the second parameter is the value to append, insert, and so on. As you
can see, the second parameter is also a pointer to a String object,
but I want to be able to specify also a const character string without
having to create an extra String object. Let me provide an example:

/* Pedantic way */
GekkotaString *s1 = gekkota_string_new("Hello");
GekkotaString *s2 = gekkota_string_new(", World");
gekkota_string_append(s1, s2); /* The value of s1 is now "Hello,
World" */

/* easy way */
GekkotaString *s1 = gekkota_string_new("Hello");
gekkota_string_append(s1, _str(", World")); /* The value of s1 is now
"Hello, World" */

Function _str() just does the trick we discussed yesterday.

Of course, I could have defined a second variant of the append()
function like this:
int32_t gekkota_string_append_1(GekkotaString *string, const char_t
*value);

but that's less elegant in my opinion.

That's it.
j3d.
 
G

giuseppe.greco

I understand what you mean, but let me explain what I'm doing...

I'm implementing a String class and, of course, I provide some
functions to create and manipulate it:

GekkotaString* gekkota_string_new();
...
int32_t gekkota_string_append(GekkotaString *string, const
GekkotaString *value);
int32_t gekkota_string_insert(GekkotaString *string, const
GekkotaString *value, int32_t index);
...

The first parameter always refers the object being manipulated, while
the second parameter is the value to append, insert, and so on. As you
can see, the second parameter is also a pointer to a String object,
but I want to be able to specify also a const character string without
having to create an extra String object. Let me provide an example:

/* Pedantic way */
GekkotaString *s1 = gekkota_string_new("Hello");
GekkotaString *s2 = gekkota_string_new(", World");
gekkota_string_append(s1, s2); /* The value of s1 is now "Hello,
World" */

/* easy way */
GekkotaString *s1 = gekkota_string_new("Hello");
gekkota_string_append(s1, _str(", World")); /* The value of s1 is now
"Hello, World" */

Function _str() just does the trick we discussed yesterday.

Of course, I could have defined a second variant of the append()
function like this:
int32_t gekkota_string_append_1(GekkotaString *string, const char_t
*value);

but that's less elegant in my opinion.

That's it.
j3d.- Hide quoted text -

- Show quoted text -

Sorry... but I did a mistacke! What I need is exactly the contrary.

I'd like to create a String object on-the-fly into the stack... so
given the following structure

typedef struct _GekkotaString
{
char_t *value;
uint_t refCount;
...
} GekkotaString;

I need somewhat like (see the function prototypes I sent in my last
post)

....
GekkotaString *string = gekkota_string_new("Hello");
gekkota_string_append(string, &(GekkotaString){", World", 0})

.... but of course, it does not work. Is there a work-around?

Thanks,
j3d.
 
B

Ben Bacarisse

Sorry... but I did a mistacke! What I need is exactly the contrary.

I'd like to create a String object on-the-fly into the stack... so
given the following structure

typedef struct _GekkotaString
{
char_t *value;
uint_t refCount;
...
} GekkotaString;

...
GekkotaString *string = gekkota_string_new("Hello");
gekkota_string_append(string, &(GekkotaString){", World", 0})

... but of course, it does not work. Is there a work-around?

Works for me. What goes wrong?
 
G

giuseppe.greco

(e-mail address removed) writes:

<big snip>








Works for me. What goes wrong?

No idea... it does compile with gcc (but execution crashes on cygwin)
and it DOES NOT compile with Microsoft's C compiler (Visual Studio
2005). I haven't tried on Linux yet.
PS: my library shall compile at least on Linux, MAC, Free/NetBSD, and
Windows.

j3d.
 
G

giuseppe.greco

No idea... it does compile with gcc (but execution crashes on cygwin)
and it DOES NOT compile with Microsoft's C compiler (Visual Studio
2005). I haven't tried on Linux yet.
PS: my library shall compile at least on Linux, MAC, Free/NetBSD, and
Windows.

j3d.

Sorry... the code here below does compile with gcc and it does work
correctly, but if you try to compile it with Microsoft's C compiler
you'll get the following error message:

error C2059: syntax error : '{'

Does anybody know if there is a workaround? As stated in my previous
email, my library shall compile at least on Linux, MAC, Free/NetBSD
and Windows XP or higher.

Thanks,
j3d.

#include <stdio.h>

typedef struct _MyString
{
char *value;
int refCount;
} MyString;

void print_mystring(const MyString *s);

int main()
{
print_mystring(&(MyString){"Hello, World", 0});
}

void print_mystring(const MyString *s)
{
printf("%s\n", s->value);
}
 
B

Ben Bacarisse

Sorry... the code here below does compile with gcc and it does work
correctly, but if you try to compile it with Microsoft's C compiler
you'll get the following error message:

error C2059: syntax error : '{'

I think MS C does not implement C99. Of course, neither does gcc
but it implements most of it. I thought from previous posts that you
new this was a C99 feature. Sorry if I did not make that clear.

For maximum portability between compilers one needs to code in C90 or
even the intersection of value C90 and C99.
 
G

giuseppe.greco

I think MS C does not implement C99. Of course, neither does gcc
but it implements most of it. I thought from previous posts that you
new this was a C99 feature. Sorry if I did not make that clear.

For maximum portability between compilers one needs to code in C90 or
even the intersection of value C90 and C99.

.... so no way to implement what I want... isn't it?
j3d
 
C

CBFalconer

.... snip ...

Sorry... the code here below does compile with gcc and it does work
correctly, but if you try to compile it with Microsoft's C compiler
you'll get the following error message:

error C2059: syntax error : '{'
.... snip ...

typedef struct _MyString
{

Identifiers starting with a '_' are generally reserved for the
implementor, and thus not available to the user.
 
G

giuseppe.greco

(e-mail address removed) wrote:

... snip ...



... snip ...


Identifiers starting with a '_' are generally reserved for the
implementor, and thus not available to the user.

I'm the implementator of MyString... and the code snippet was just an
example...
j3d.
 
F

Flash Gordon

<snip>

Please don't quote peoples signatures unless you are commenting on them.
I'm the implementator of MyString... and the code snippet was just an
example...

By implementer we mean those implementing the C language (compiler,
standard library etc), not writing some library in it. So unless you are
actually producing a C implementation Chuck is correct and you should
not be using _MyString as an identifier.
 
C

CBFalconer

I'm the implementator of MyString... and the code snippet was
just an example...

You said "code here below does compile with gcc and it does work
correctly". I pointed out that it was not legitimate code. And
why do you quote signatures?
 

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
473,981
Messages
2,570,188
Members
46,732
Latest member
ArronPalin

Latest Threads

Top