Discussion:
sizeof
(too old to reply)
Jeremy
2009-08-04 21:37:38 UTC
Permalink
Does VC not support this?

size_t x = sizeof (int[]){0,1,2};
Victor Bazarov
2009-08-04 22:13:46 UTC
Permalink
Post by Jeremy
Does VC not support this?
size_t x = sizeof (int[]){0,1,2};
What's that supposed to accomplish?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jeremy
2009-08-04 23:01:04 UTC
Permalink
Post by Victor Bazarov
Post by Jeremy
Does VC not support this?
size_t x = sizeof (int[]){0,1,2};
What's that supposed to accomplish?
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
It would yield the same results as the following, without having to
declare "w"
int w[] = {0,1,2};
size_t x = sizeof( x );

So I could do something like..
#define amacro( var_name, ... ) var_name = sizeof (int[])
{__VA_ARGS__}

amacro(x, 0, 1, 2);

- Jeremy
Victor Bazarov
2009-08-04 23:58:40 UTC
Permalink
Post by Jeremy
Post by Victor Bazarov
Post by Jeremy
Does VC not support this?
size_t x = sizeof (int[]){0,1,2};
What's that supposed to accomplish?
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
It would yield the same results as the following, without having to
declare "w"
int w[] = {0,1,2};
size_t x = sizeof( x );
So I could do something like..
#define amacro( var_name, ... ) var_name = sizeof (int[])
{__VA_ARGS__}
amacro(x, 0, 1, 2);
OK. What would be the point? What problem are you trying to solve
using that [non-existent] construct?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jeremy
2009-08-05 00:41:38 UTC
Permalink
Post by Jeremy
Post by Victor Bazarov
Post by Jeremy
Does VC not support this?
size_t x = sizeof (int[]){0,1,2};
What's that supposed to accomplish?
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
It would yield the same results as the following, without having to
declare "w"
int w[] = {0,1,2};
size_t x = sizeof( x );
So I could do something like..
#define amacro( var_name, ... ) var_name = sizeof  (int[])
{__VA_ARGS__}
amacro(x, 0, 1, 2);
OK.  What would be the point?  What problem are you trying to solve
using that [non-existent] construct?
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask- Hide quoted text -
- Show quoted text -
I wanted to use it to count the number of arguments represented by
__VA_ARGS__ in a macro, knowing they were a specific type. Here's a
more complete example of what I'm doing now..

template < size_t NumberOfElements >
struct VariableSizedRecord {
int data[NumberOfElements];
};

#define DeclareVariableSizedRecord( Name, ... ) \
int __rgtemp ##Name[] = {__VA_ARGS__}; \
VariableSizedRecord< sizeof(__rgtemp ##Name) / sizeof(int)> Name =
{{__VA_ARGS__}}

DeclareVariableSizedRecord(RecordA, 0, 1, 2, 3);
DeclareVariableSizedRecord(RecordB, 4, 5, 6);
DeclareVariableSizedRecord(RecordC, 7, 8, 9, 10, 11, 12);

I noticed that GCC supports the "compound literal" syntax which
would've allowed me to use something like this as my macro:

#define DeclareVariableSizedRecord( Name, ... ) \
VariableSizedRecord< sizeof( ((int[]){__VA_ARGS__}) ) / sizeof(int) >
Name = {{__VA_ARGS__}}

It works with what I'm doing now, but I was hoping I could avoid the
_rgtemp##Name declaration and save some space. The types I'm declaring
in the macro are more complex than this example, but that's the idea.

- Jeremy
Victor Bazarov
2009-08-05 03:43:10 UTC
Permalink
Post by Jeremy
[..]
I wanted to use it to count the number of arguments represented by
__VA_ARGS__ in a macro, knowing they were a specific type. Here's a
more complete example of what I'm doing now..
template < size_t NumberOfElements >
struct VariableSizedRecord {
int data[NumberOfElements];
};
#define DeclareVariableSizedRecord( Name, ... ) \
int __rgtemp ##Name[] = {__VA_ARGS__}; \
VariableSizedRecord< sizeof(__rgtemp ##Name) / sizeof(int)> Name =
{{__VA_ARGS__}}
DeclareVariableSizedRecord(RecordA, 0, 1, 2, 3);
DeclareVariableSizedRecord(RecordB, 4, 5, 6);
DeclareVariableSizedRecord(RecordC, 7, 8, 9, 10, 11, 12);
Ah, OK, it makes sense. Easier to maintain if you don't have to count
those elements, especially if there is quite a few of them, right?

On the other hand, how often do you really need to change the
initialiser list, honestly? Yes, otherwise you have to type the size of
the array yourself (ugh!)...

VariableSizedRecord<4> RecordA = { 0,1,2,3 };
VariableSizedRecord<3> RecordA = { 4,5,6 };

Do you really consider that "Declare..." macro so much better?
Post by Jeremy
I noticed that GCC supports the "compound literal" syntax which
#define DeclareVariableSizedRecord( Name, ... ) \
VariableSizedRecord< sizeof( ((int[]){__VA_ARGS__}) ) / sizeof(int) >
Name = {{__VA_ARGS__}}
It works with what I'm doing now, but I was hoping I could avoid the
_rgtemp##Name declaration and save some space. The types I'm declaring
in the macro are more complex than this example, but that's the idea.
The support for those things is patchy. You could try using VS 2010
(now in beta), they probably have array literals.

As to saving space, you need to verify whether those arrays are ever
actually created, or perhaps they are optimized away by the linker since
there is no reference to them anywhere in the code... As a potential
improvement, try declaring them 'static' as well. As in

#define DeclareVariableSizedRecord( Name, ... ) \
static int __rgtemp ##Name[] = {__VA_ARGS__}; \
//^^^^^^
VariableSizedRecord< sizeof(__rgtemp ##Name) \
/ sizeof(int)> Name = {{__VA_ARGS__}}

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jeremy
2009-08-05 20:28:19 UTC
Permalink
Post by Jeremy
[..]
I wanted to use it to count the number of arguments represented by
__VA_ARGS__ in a macro, knowing they were a specific type. Here's a
more complete example of what I'm doing now..
template < size_t NumberOfElements >
struct VariableSizedRecord {
 int data[NumberOfElements];
};
#define DeclareVariableSizedRecord( Name, ... ) \
 int __rgtemp ##Name[] = {__VA_ARGS__}; \
 VariableSizedRecord< sizeof(__rgtemp ##Name) / sizeof(int)> Name =
{{__VA_ARGS__}}
DeclareVariableSizedRecord(RecordA, 0, 1, 2, 3);
DeclareVariableSizedRecord(RecordB, 4, 5, 6);
DeclareVariableSizedRecord(RecordC, 7, 8, 9, 10, 11, 12);
Ah, OK, it makes sense.  Easier to maintain if you don't have to count
those elements, especially if there is quite a few of them, right?
On the other hand, how often do you really need to change the
initialiser list, honestly?  Yes, otherwise you have to type the size of
the array yourself (ugh!)...
    VariableSizedRecord<4> RecordA = { 0,1,2,3 };
    VariableSizedRecord<3> RecordA = { 4,5,6 };
Do you really consider that "Declare..." macro so much better?
For a simple array it wouldn't be much better. The actual data I'm
declaring is more complex than the example and a maco makes it less
error prone and easier to reuse.
As to saving space, you need to verify whether those arrays are ever
actually created, or perhaps they are optimized away by the linker since
there is no reference to them anywhere in the code...  As a potential
improvement, try declaring them 'static' as well.  As in
  #define DeclareVariableSizedRecord( Name, ... ) \
   static int __rgtemp ##Name[] = {__VA_ARGS__}; \
//^^^^^^
   VariableSizedRecord< sizeof(__rgtemp ##Name) \
      / sizeof(int)> Name = {{__VA_ARGS__}}
They seem to be optimized away in release builds with the proper
switches. What benefit does declaring the types as 'static' give?

- Jeremy
Victor Bazarov
2009-08-05 20:54:28 UTC
Permalink
Post by Jeremy
Post by Victor Bazarov
As to saving space, you need to verify whether those arrays are ever
actually created, or perhaps they are optimized away by the linker since
there is no reference to them anywhere in the code... As a potential
improvement, try declaring them 'static' as well. As in
#define DeclareVariableSizedRecord( Name, ... ) \
static int __rgtemp ##Name[] = {__VA_ARGS__}; \
//^^^^^^
VariableSizedRecord< sizeof(__rgtemp ##Name) \
/ sizeof(int)> Name = {{__VA_ARGS__}}
They seem to be optimized away in release builds with the proper
switches. What benefit does declaring the types as 'static' give?
The types aren't static. The objects are static. Declaring an object
static gives the name internal linkage, and makes it easier for the
compiler to remove them if the same file doesn't contain any reference
to them (sizeof doesn't count), I guess. How did you learn that they
are optimized away? Did you check the object module? Did you
disassemble the resulting executable? Did you print out the assembly?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jeremy
2009-08-05 22:06:08 UTC
Permalink
Post by Jeremy
Post by Victor Bazarov
As to saving space, you need to verify whether those arrays are ever
actually created, or perhaps they are optimized away by the linker since
there is no reference to them anywhere in the code...  As a potential
improvement, try declaring them 'static' as well.  As in
  #define DeclareVariableSizedRecord( Name, ... ) \
   static int __rgtemp ##Name[] = {__VA_ARGS__}; \
//^^^^^^
   VariableSizedRecord< sizeof(__rgtemp ##Name) \
      / sizeof(int)> Name = {{__VA_ARGS__}}
They seem to be optimized away in release builds with the proper
switches. What benefit does declaring the types as 'static' give?
The types aren't static.  The objects are static.  Declaring an object
static gives the name internal linkage, and makes it easier for the
compiler to remove them if the same file doesn't contain any reference
to them (sizeof doesn't count), I guess.  How did you learn that they
are optimized away?  Did you check the object module?  Did you
disassemble the resulting executable?  Did you print out the assembly?
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask- Hide quoted text -
- Show quoted text -
If the array is declared as "const" then it is discarded. I verified
this using the /FAs compiler option to generate the assembly listing.
- Jeremy
Igor Tandetnik
2009-08-05 16:34:05 UTC
Permalink
Post by Jeremy
I wanted to use it to count the number of arguments represented by
__VA_ARGS__ in a macro, knowing they were a specific type.
If you are happy to limit yourself to some fixed maximum number, you
could do something like this:

namespace detail {
template <typename T1>
char (&size_calculator(T1))[1];

template <typename T1, typename T2>
char (&size_calculator(T1, T2))[2];

template <typename T1, typename T2, typename T3>
char (&size_calculator(T1, T2, T3))[3];

// Follow the pattern up to a desired maximum.
// You don't need to implement these functions, just declare them.
}

#define ArgCount(...) sizeof(detail::size_calculator(__VA_ARGS__))

If you only need to count ints, then size_calculator doesn't need to be
a template.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Jeremy
2009-08-05 20:42:31 UTC
Permalink
Post by Igor Tandetnik
Post by Jeremy
I wanted to use it to count the number of arguments represented by
__VA_ARGS__ in a macro, knowing they were a specific type.
If you are happy to limit yourself to some fixed maximum number, you
namespace detail {
template <typename T1>
char (&size_calculator(T1))[1];
template <typename T1, typename T2>
char (&size_calculator(T1, T2))[2];
template <typename T1, typename T2, typename T3>
char (&size_calculator(T1, T2, T3))[3];
// Follow the pattern up to a desired maximum.
// You don't need to implement these functions, just declare them.
}
#define ArgCount(...) sizeof(detail::size_calculator(__VA_ARGS__))
If you only need to count ints, then size_calculator doesn't need to be
a template.
--
With best wishes,
    Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
That's clever and could work. A template function that returns a
reference to an array of char, and the compiler chooses the correct
overload based on the number of arguments?

- Jeremy
Alex Blekhman
2009-08-08 07:40:49 UTC
Permalink
Post by Jeremy
That's clever and could work. A template function that
returns a reference to an array of char, and the compiler
chooses the correct overload based on the number of
arguments?
Exactly. Also, this trick is used with ARRAYSIZE Platform
SDK's macro and CRT's _countof macro. So, you don't need to
type "sizeof(array)/sizeof(array_element)" where you need a
number of array elements.

Alex

Barry Schwarz
2009-08-04 23:47:50 UTC
Permalink
Post by Jeremy
Does VC not support this?
size_t x = sizeof (int[]){0,1,2};
It is called a compound literal and is a new feature in C99. I don't
think VC made any attempt to support it.

If you do use a C99 compiler, I believe you need an extra set of
parentheses
size_t x = sizeof ((int[]){0,1,2});
because the operand of sizeof is a type and not an object.
--
Remove del for email
Continue reading on narkive:
Loading...