 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Harry Guest
|
Posted: Wed Sep 22, 2004 6:34 pm Post subject: Structure pointer |
|
|
Ok..
i am getting a little puzzled. I saw a code snippet as follows:
typedef struct _LISTYPE
{ char *listName;
int len;
char *list[1];
} LISTTYPE, * PLISTTYPE;
// Allocate LISTTYPE to contain a list of length 1000
//and 8 bytes for listName and len
p = (PLISTTYPE) malloc(8+(1000 * sizeof(char *)));
Now the last line is puzzling me. I think that all is OK except it
should be sizeof(char) instaed of sizeof(char *).
Well the above snippet was in an intel white paper, so i wanted to
check it out with others in the group.
Can someone give a more elegant(lucid) way to do the above thing??
hoping for some insight
urs
Harry
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Jack Klein Guest
|
Posted: Thu Sep 23, 2004 7:57 am Post subject: Re: Structure pointer |
|
|
On 22 Sep 2004 14:34:12 -0400, [email]arbhgs00 (AT) fht-esslingen (DOT) de[/email] (Harry) wrote
in comp.lang.c++.moderated:
| Quote: | Ok..
i am getting a little puzzled. I saw a code snippet as follows:
|
This is actually a bad code snippet.
| Quote: | typedef struct _LISTYPE
|
Identifiers beginning with an underscore followed by another
underscore or an upper case letter are reserved for the implementation
in all contexts.
| Quote: | { char *listName;
int len;
char *list[1];
} LISTTYPE, * PLISTTYPE;
// Allocate LISTTYPE to contain a list of length 1000
//and 8 bytes for listName and len
p = (PLISTTYPE) malloc(8+(1000 * sizeof(char *)));
|
This code does not have defined behavior. C has added a flexible
array member type to structures with the 1999 standard update, but
this has not been incorporated in standard C++ yet. The syntax used
by C99 is different.
| Quote: | Now the last line is puzzling me. I think that all is OK except it
should be sizeof(char) instaed of sizeof(char *).
|
That depends. It appears that the intent is to provide a named list
of character strings, since the member 'list' is defined not as a
char, but as a pointer to char.
| Quote: | Well the above snippet was in an intel white paper, so i wanted to
check it out with others in the group.
|
Twenty-five years ago Intel provided application notes containing
broken code quite frequently. Some such code was provided with the
Intel Bubble Memory development kit (anyone else remember when bubble
memory was the wave of the future?). If you built and ran their
example code to drive the bubble memory, it hung in an infinite loop
and never did anything useful.
Since then, I have seen lots of other Intel app notes with bad code.
| Quote: | Can someone give a more elegant(lucid) way to do the above thing??
hoping for some insight
|
In C++, the 'list' member should be a std::vector of pointers to char,
or even more likely a std::vector of pointers to std::string.
In C, the 'list' member should be defined with type char**, and a
pointer to an allocated block of char*.
This type of code is reinvented frequently, even though its behavior
is undefined in both C and C++. The justification is always
efficiency, making one call to malloc() (or new[]) instead of two,
saving one extra pointer dereference when accessing the array.
I have never yet seen any evidence presented and backed up by timing
tests or a profiler of a case where this significantly altered program
execution time.
My own personal opinion is that this sort of thing, it even has a
name, the "struct hack", is usually used by programmers who are not as
clever as they think they are.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
mmm Guest
|
Posted: Thu Sep 23, 2004 7:58 am Post subject: Re: Structure pointer |
|
|
"Harry" wrote:
| Quote: | Ok..
i am getting a little puzzled. I saw a code snippet as follows:
typedef struct _LISTYPE
{ char *listName;
int len;
char *list[1];
} LISTTYPE, * PLISTTYPE;
// Allocate LISTTYPE to contain a list of length 1000
//and 8 bytes for listName and len
p = (PLISTTYPE) malloc(8+(1000 * sizeof(char *)));
Now the last line is puzzling me. I think that all is OK except it
should be sizeof(char) instaed of sizeof(char *).
|
LISTTYPE.list appears to be an array of 1000 strings pointers not a pointer
on a single string of max 1000 chars.
I would prefer this (in C coding context), it does the same thing but ...:
p = (PLISTTYPE) malloc(sizeof(LISTTYPE)+((1000-1) * sizeof(char *)));
p->len=1000 ? I suppose that len is LISTTYPE.list array dimension ?
| Quote: | Can someone give a more elegant(lucid) way to do the above thing??
|
Do you have to write support for this struct in C++ or C ?
In case of C++, do you have to keep this struct in your final code? what
type of lib you can use (stl, ...) ?
How you will use this struct and its strings array ?, ...
Give more details ;-)
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Alberto Barbati Guest
|
Posted: Thu Sep 23, 2004 8:02 am Post subject: Re: Structure pointer |
|
|
Harry wrote:
| Quote: | Ok..
i am getting a little puzzled. I saw a code snippet as follows:
typedef struct _LISTYPE
{ char *listName;
int len;
char *list[1];
} LISTTYPE, * PLISTTYPE;
// Allocate LISTTYPE to contain a list of length 1000
//and 8 bytes for listName and len
p = (PLISTTYPE) malloc(8+(1000 * sizeof(char *)));
Now the last line is puzzling me. I think that all is OK except it
should be sizeof(char) instaed of sizeof(char *).
|
Although ugly and very non-portable, it's correct (for an ix86 platform,
at least). The expression accounts for:
4 bytes for listName (a char*)
+4 bytes for len (an int)
+1000 * sizeof(char*) bytes to hold 1000 char* that will be accessed
throgh list (which is, in fact, an array of char* and _not_ an array of
char)
| Quote: | Can someone give a more elegant(lucid) way to do the above thing??
|
That is probably legacy C code maintained for some obscure reason. The
simple way, which is still not very elegant is to replace the 8 with
sizeofs and getting right of the dreadful C-cast:
p = static_cast<LISTTYPE*>(malloc(
sizeof(char*) + sizeof(int) + 1000*sizeof(char*)));
Notice that, in order for this to work reliably, you have to be sure the
compiler adds no padding to the structure. There should be some #pragma
pack around, somewhere.
But this is a C++ newsgroup, right? So it's time to give a C++ solution,
I guess. What about this:
template <int N>
LISTTYPE* allocate_list()
{
struct LISTTYPE_N
{
char* listName;
int len;
char* list[N];
};
return static_cast<LISTTYPE*>(malloc(sizeof(LISTTYPE_N)));
}
Then you call like it like this:
p = allocate_list<1000>();
This code should also be more portable than the original one. At least
it doesn't depend on paddings.
Hope it helps,
Alberto
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Nevin Liber Guest
|
Posted: Thu Sep 23, 2004 8:05 am Post subject: Re: Structure pointer |
|
|
In article <f997ddc3.0409220416.67bc353a (AT) posting (DOT) google.com>,
Harry <arbhgs00 (AT) fht-esslingen (DOT) de> wrote:
| Quote: | typedef struct _LISTYPE
{ char *listName;
int len;
char *list[1];
} LISTTYPE, * PLISTTYPE;
// Allocate LISTTYPE to contain a list of length 1000
//and 8 bytes for listName and len
p = (PLISTTYPE) malloc(8+(1000 * sizeof(char *)));
Now the last line is puzzling me. I think that all is OK except it
should be sizeof(char) instaed of sizeof(char *).
|
No. The type of "list" is "pointer to char".
| Quote: | Can someone give a more elegant(lucid) way to do the above thing??
|
p = (PLISTTYPE) malloc(offsetof(LISTTYPE, list[1000]));
Note: you may have to #include <stddef.h> (or <cstddef>, if this is C++
and not just C).
--
Nevin " " Liber <mailto:nevin (AT) spies (DOT) com> (773) 961-1620
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dave Harris Guest
|
Posted: Thu Sep 23, 2004 8:07 am Post subject: Re: Structure pointer |
|
|
[email]arbhgs00 (AT) fht-esslingen (DOT) de[/email] (Harry) wrote (abridged):
| Quote: | typedef struct _LISTYPE
{ char *listName;
int len;
char *list[1];
} LISTTYPE, * PLISTTYPE;
// Allocate LISTTYPE to contain a list of length 1000
//and 8 bytes for listName and len
p = (PLISTTYPE) malloc(8+(1000 * sizeof(char *)));
Now the last line is puzzling me. I think that all is OK except it
should be sizeof(char) instaed of sizeof(char *).
|
It looks right to me. The aim is to be able to write code like:
p->list[10] = new char[100];
It is (char *) because the LISTTYPE::list array is an array of char *. It
is trying to allocate enough memory for 1000 array elements. The chars
they point to are not being allocated here. The 8 is sizeof(LISTTYPE) -
sizeof(LISTTYPE::list). Because the LISTTTYPE definition already includes
1 element in the array, the total memory allocated should be the same as
for:
p = (LISTTYPE *) malloc( sizeof(LISTTTYPE) + 999 * sizeof(char *) );
but if you write it like that it looks like the limit is one smaller than
it is. In my view, malloc() should always be wrapped by a macro that does
the cast and any calculation.
#define AllocVariableLengthStruct( s_type, a_type, count )
(s_type *) malloc( sizeof(s_type) - sizeof(a_type) +
count * sizeof(a_type) )
p = AllocVariableLengthStruct( LISTTYPE, char *, 1000 );
-- Dave Harris, Nottingham, UK
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Fri Sep 24, 2004 11:24 am Post subject: Re: Structure pointer |
|
|
[email]arbhgs00 (AT) fht-esslingen (DOT) de[/email] (Harry) wrote in message
news:<f997ddc3.0409220416.67bc353a (AT) posting (DOT) google.com>...
| Quote: | i am getting a little puzzled. I saw a code snippet as follows:
typedef struct _LISTYPE
{ char *listName;
int len;
char *list[1];
} LISTTYPE, * PLISTTYPE;
// Allocate LISTTYPE to contain a list of length 1000
//and 8 bytes for listName and len
p = (PLISTTYPE) malloc(8+(1000 * sizeof(char *)));
Now the last line is puzzling me. I think that all is OK except it
should be sizeof(char) instaed of sizeof(char *).
|
It doesn't matter, since you can't legally access the memory anyway:-).
The code in question is an old, traditional hack to implement variable
length arrays. And in this case, since the array in question is an
array of char*, the multiplication by sizeof(char*) is correct.
The problem, of course, is that accessing list with an index greater
than or equal to 1 is undefined behavior, according to the C standard
(and C++ just copies C in this respect). Regardless of the fact that
the memory is physically allocated. The correct way to implement this
in C, today, is to use a variable length array. The correct way to
implement it in C++ is to use a vector.
| Quote: | Well the above snippet was in an intel white paper, so i wanted to
check it out with others in the group.
|
It's not legal C, and it's not legal C++.
| Quote: | Can someone give a more elegant(lucid) way to do the above thing??
|
struct ListType
{
std::string listName ;
std::vector< std::string > list ;
} ;
(FWIW: I invented a clever way of doing almost exactly what the original
code does, legally, in C++. I posted it here many years back, and Steve
Clamage pointed out a serious problem with it: it doesn't guarantee
correct alignment. In my case, I was using it only for char's, so that
was OK, but someone apparently copied it for the implementation of
std::basic_string in g++. With the results that an std::basic_string<
double > core dumps as soon as the string isn't empty.)
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ulrich Eckhardt Guest
|
Posted: Fri Sep 24, 2004 11:33 am Post subject: Re: Structure pointer |
|
|
Harry wrote:
| Quote: | typedef struct _LISTYPE
{ char *listName;
int len;
char *list[1];
} LISTTYPE, * PLISTTYPE;
// Allocate LISTTYPE to contain a list of length 1000
//and 8 bytes for listName and len
p = (PLISTTYPE) malloc(8+(1000 * sizeof(char *)));
Now the last line is puzzling me. I think that all is OK except it
should be sizeof(char) instaed of sizeof(char *).
|
I'm not going into alignment and size issues, the assumptions here are far
from portable. Also, this code is an ugly mixture of C and C++...
Now, with those assumptions, the size of a LISTTYPE is 8 for 'listName' and
'len', plus the size of a char* for 'list'.
This piece of code then probably uses is the fact that array access is
unchecked in C and C++. For that, in allocates not only space for one char*
in 'list', but space for 1000 of them. That way, you can happily access
list[500] although it is declared as only having a single element. The real
size of the array will probably be stored in 'len'.
BTW: in order to ease such constructs, GCC allows zero-size arrays as last
element instructs. IIRC only in C though, not in C++.
Finally, about your question why sizeof(char*), the reason is that the
elements of 'list' are char* and not char. For that reason, I usually have
a space between the type and the name, i.e.
char* list[1];
instead of
char *list[1];
Uli
--
FAQ: http://parashift.com/c++-faq-lite/
/* bittersweet C++ */
default: break;
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Michiel Salters Guest
|
Posted: Fri Sep 24, 2004 11:38 am Post subject: Re: Structure pointer |
|
|
[email]arbhgs00 (AT) fht-esslingen (DOT) de[/email] (Harry) wrote in message news:<f997ddc3.0409220416.67bc353a (AT) posting (DOT) google.com>...
| Quote: | Ok..
i am getting a little puzzled. I saw a code snippet as follows:
typedef struct _LISTYPE
{ char *listName;
int len;
char *list[1];
} LISTTYPE, * PLISTTYPE;
// Allocate LISTTYPE to contain a list of length 1000
//and 8 bytes for listName and len
p = (PLISTTYPE) malloc(8+(1000 * sizeof(char *)));
Now the last line is puzzling me. I think that all is OK except it
should be sizeof(char) instaed of sizeof(char *).
|
It's wrong either way. The code is suspicious in any case, e.g.
identifiers may not start with _[A-Z]. _LISTYPE is illegal.
| Quote: | Well the above snippet was in an intel white paper, so i wanted to
check it out with others in the group.
|
Doesn't make it standard C++. Most likely, it's C.
| Quote: | Can someone give a more elegant(lucid) way to do the above thing??
|
struct LISTTYPE
{
std::string listName;
std::vector<std::string> list;
};
HTH,
Michiel Salters
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Maxim Yegorushkin Guest
|
Posted: Fri Sep 24, 2004 3:34 pm Post subject: Re: Structure pointer |
|
|
Jack Klein <jackklein (AT) spamcop (DOT) net> wrote:
| Quote: | Identifiers beginning with an underscore followed by another
underscore or an upper case letter are reserved for the implementation
in all contexts.
|
Actually, the requirement is even worse:
<quote>
17.4.3.1.2 Global names
Each name that contains a double underscore (__) or begins with an
underscore followed by an uppercase letter is reserved to the
implementation for any use.
</quote>
--
Maxim Yegorushkin
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Sat Sep 25, 2004 5:41 am Post subject: Re: Structure pointer |
|
|
Jack Klein <jackklein (AT) spamcop (DOT) net> wrote
| Quote: | On 22 Sep 2004 14:34:12 -0400, [email]arbhgs00 (AT) fht-esslingen (DOT) de[/email] (Harry) wrote
in comp.lang.c++.moderated:
Ok..
i am getting a little puzzled. I saw a code snippet as follows:
This is actually a bad code snippet.
typedef struct _LISTYPE
Identifiers beginning with an underscore followed by another
underscore or an upper case letter are reserved for the implementation
in all contexts.
{ char *listName;
int len;
char *list[1];
} LISTTYPE, * PLISTTYPE;
// Allocate LISTTYPE to contain a list of length 1000
//and 8 bytes for listName and len
p = (PLISTTYPE) malloc(8+(1000 * sizeof(char *)));
This code does not have defined behavior. C has added a flexible
array member type to structures with the 1999 standard update, but
this has not been incorporated in standard C++ yet. The syntax used
by C99 is different.
Now the last line is puzzling me. I think that all is OK except it
should be sizeof(char) instaed of sizeof(char *).
That depends. It appears that the intent is to provide a named list
of character strings, since the member 'list' is defined not as a
char, but as a pointer to char.
Well the above snippet was in an intel white paper, so i wanted to
check it out with others in the group.
Twenty-five years ago Intel provided application notes containing
broken code quite frequently.
|
Twenty-five years ago, or even fifteen, this code would have been
considered legal by most C experts. There was no standard, so "legal"
meant simply that it worked just about everywhere.
The C standard banned it intentionally, as part of a more general
clean-up, with the goal to allow a checking implementation with fat
pointers. As far as I know, Centerline is the only compiler which ever
took advantage of this liberty.
[...]
| Quote: | I have never yet seen any evidence presented and backed up by timing
tests or a profiler of a case where this significantly altered program
execution time.
|
I have. In fact, I developped a way to do it legally (in C++), because
I did have a performance problem. (My "legal" implementation did have a
potential problem with alignment. The g++ basic_string class uses it,
and actually does fail for any time requirement a stricter alignment
than size_t.)
But that was over ten years ago -- the quality of standard memory
allocators has since improved enormously, and I'm very sceptical of its
relevance today.
| Quote: | My own personal opinion is that this sort of thing, it even has a
name, the "struct hack", is usually used by programmers who are not as
clever as they think they are.
|
Thanks:-). But I'll agree, since you say "usually". I'd also add
"today"; I can remember an epoque when memory allocation was very
expensive, and cutting the number of allocations in half could make a
real difference. I can remember speeding up a program by a factor of
100 with the Zortech compiler, just by using a specialized fixed size
allocator for one particular type. But I can't think of a single case
in the last 7 or 8 years where tuning allocation, or avoiding
allocation, would have made a measurable difference.
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Sat Sep 25, 2004 5:42 am Post subject: Re: Structure pointer |
|
|
Alberto Barbati <AlbertoBarbati (AT) libero (DOT) it> wrote
| Quote: | Harry wrote:
Ok..
i am getting a little puzzled. I saw a code snippet as follows:
typedef struct _LISTYPE
{ char *listName;
int len;
char *list[1];
} LISTTYPE, * PLISTTYPE;
// Allocate LISTTYPE to contain a list of length 1000
//and 8 bytes for listName and len
p = (PLISTTYPE) malloc(8+(1000 * sizeof(char *)));
Now the last line is puzzling me. I think that all is OK except it
should be sizeof(char) instaed of sizeof(char *).
Although ugly and very non-portable, it's correct (for an ix86
platform, at least).
|
It's formally illegal. Or rather, it will be formally illegal when he
tries to access p->list[i] with an i greater than 0.
In practice, it works on most systems.
| Quote: | The expression accounts for:
4 bytes for listName (a char*)
+4 bytes for len (an int)
+1000 * sizeof(char*) bytes to hold 1000 char* that will be accessed
throgh list (which is, in fact, an array of char* and _not_ an array of
char)
Can someone give a more elegant(lucid) way to do the above thing??
That is probably legacy C code maintained for some obscure reason. The
simple way, which is still not very elegant is to replace the 8 with
sizeofs and getting right of the dreadful C-cast:
|
He definitly should replace the 8 by sizeof LISTTYPE.
If it's legacy C code, I'm not sure that getting rid of the dreadful
C-cast is a good idea. You may still have to compile it with a C
compiler. If he can translate it to C++, the obvious solution is to
replace "char* list[1]" with std::vector< std::string >. If for some
reason, minimizing the number of allocations really is important (which
would surprise me very much), the above can be legally implemented in
C++ by something like:
struct LISTTYPE
{
char const* listName ;
int length ;
char** buffer()
{
return reinterpret_cast< char** >( this + 1 ) ;
}
} ;
The one time I did this, I also added a placement new and a constructor,
to prevent things like :
LISTTYPE* p = new LISTTYPE ;
Today, I'd probably go all the way, making the placement new and the
constructor private, and providing a static factory method.
Note that even this fails if char** has stricter alignment requirements
than char* or int; in practice, you are probably safe, however. Just
don't do anything stupid like making it a template.
| Quote: | p = static_cast<LISTTYPE*>(malloc(
sizeof(char*) + sizeof(int) + 1000*sizeof(char*)));
Notice that, in order for this to work reliably, you have to be sure
the compiler adds no padding to the structure. There should be some
#pragma pack around, somewhere.
|
On a Sparc in 64 bit mode, you cannot access a pointer whose address is
not a multiple of 8. A better solution (the "classical" solution) is to
use sizeof( LISTTYPE ) + n * sizeof( char* ).
| Quote: | But this is a C++ newsgroup, right? So it's time to give a C++ solution,
I guess. What about this:
template <int N
LISTTYPE* allocate_list()
{
struct LISTTYPE_N
{
char* listName;
int len;
char* list[N];
};
return static_cast
}
Then you call like it like this:
p = allocate_list<1000>();
|
And what is the type of p? You've made the length part of the type,
which probably isn't what is wanted. Typically, too, the length is NOT
a compile time constant, so the template solution won't work either.
If I were writing this today, I'd simply write:
struct ListType
{
std::string name ;
std::vector< std::string >
list ;
} ;
And I'd need some very conclusive evidence from the profiler before I'd
accept anything else.
-
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Alberto Barbati Guest
|
Posted: Sat Sep 25, 2004 6:12 pm Post subject: Re: Structure pointer |
|
|
[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote:
| Quote: |
He definitly should replace the 8 by sizeof LISTTYPE.
|
But sizeof(LISTTYPE) is greater than 8 because LISTTYPE includes a
1-element char* array. A solution proposed by other posters is to
replace 8 with sizeof(LISTTYPE) - sizeof(char*).
| Quote: |
But this is a C++ newsgroup, right? So it's time to give a C++ solution,
I guess. What about this:
template <int N
LISTTYPE* allocate_list()
{
struct LISTTYPE_N
{
char* listName;
int len;
char* list[N];
};
return static_cast
}
Then you call like it like this:
p = allocate_list<1000>();
And what is the type of p? You've made the length part of the type,
which probably isn't what is wanted. Typically, too, the length is NOT
a compile time constant, so the template solution won't work either.
|
The type of p is LISTTYPE*. You seem that have misread the static_cast
up there. I am exploiting the fact that the two types LISTTYPE and
LISTTYPE_N<> share a common initial sequence. If you think this is not
correct enough, we may rewrite my helper function using a union:
template <int N>
LISTTYPE* allocate_list()
{
union LISTTYPE_N
{
LISTTYPE lt;
struct {
char* listName;
int len;
char* list[N];
} ltn;
};
LISTTYPE_N* p = static_cast<LISTTYPE_N*>(malloc(sizeof(LISTTYPE_N)));
return &(p->lt);
}
I know that it's still not 100% correct to access the ltn subobject
through a pointer to lt, but I find it very difficult to imagine an
implementation satisfying 9.2/16 where that wasn't true.
Notice that it's correct to call free() on the returned pointer because
of 9.2/17.
| Quote: |
If I were writing this today, I'd simply write:
struct ListType
{
std::string name ;
std::vector< std::string
list ;
} ;
And I'd need some very conclusive evidence from the profiler before I'd
accept anything else.
|
Of course I agree with you on this point. I just wanted to amuse myself
by finding more ways to do that, by changing as little of the original
problem as possible ;-)
Alberto
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Maxim Yegorushkin Guest
|
Posted: Sun Sep 26, 2004 4:08 pm Post subject: Re: Structure pointer |
|
|
<kanze (AT) gabi-soft (DOT) fr> wrote:
| Quote: | I can remember an epoque when memory allocation was very
expensive, and cutting the number of allocations in half could make a
real difference. I can remember speeding up a program by a factor of
100 with the Zortech compiler, just by using a specialized fixed size
allocator for one particular type. But I can't think of a single case
in the last 7 or 8 years where tuning allocation, or avoiding
allocation, would have made a measurable difference.
|
I disagree that it does not make a difference today.
I am working on an immutable string library [1], whose sole purpose is to
reduce the number of allocations. And it has been reported [2] to have
sped up certain applications.
[1] http://conststring.sourceforge.net/
[2] http://lists.boost.org/MailArchives/boost/msg71549.php
http://lists.boost.org/MailArchives/boost/msg71753.php
--
Maxim Yegorushkin
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Bill Wade Guest
|
Posted: Mon Sep 27, 2004 8:42 pm Post subject: Re: Structure pointer |
|
|
"Maxim Yegorushkin" <e-maxim (AT) yandex (DOT) ru> wrote
| Quote: | kanze (AT) gabi-soft (DOT) fr> wrote:
I can remember an epoque when memory allocation was very
expensive, and cutting the number of allocations in half could make a
real difference. I can remember speeding up a program by a factor of
100 with the Zortech compiler, just by using a specialized fixed size
allocator for one particular type. But I can't think of a single case
in the last 7 or 8 years where tuning allocation, or avoiding
allocation, would have made a measurable difference.
|
I'd probably change "measurable" to "significant".
In addition to avoiding the number of allocations, your code almost
certainly reduced the number of copies (and the active memory
footprint). It may be that the real speed-up comes from those
savings.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|