I'm working with WinAPI's CreateDialogIndirect function, which has some requirements on the DLGTEMPLATE and DLGTEMPLATEEX structures pointed to by the second parameter. My code works well, however, I would like to get rid of the #define macros.
I created a simplified example to focus on the macros. This is a working program with macros, it can be compiled, and outputs what is expected:
#include <iostream>
int wmain()
{
#define TITLE L"Title"
struct {
wchar_t title[ sizeof( TITLE ) / sizeof( TITLE[ 0 ] ) ];
int font_size;
} s = {
TITLE,
12,
};
std::wcout
<< L"s.title = " << s.title << std::endl
<< L"s.font_size = " << s.font_size << std::endl;
return 0;
}
In Visual Studio 2022, I see three dots at the #define macro, and I can read the following tooltip:
Macro can be converted to constexpr
Show potential fixes
Convert macro to constexpr
I would like to see it converted to something to avoid macros, so I click on it, and the code is changed to this:
#include <iostream>
int wmain()
{
constexpr auto TITLE = L"Title";
struct {
wchar_t title[ sizeof( TITLE ) / sizeof( TITLE[ 0 ] ) ];
int font_size;
} s = {
TITLE,
12,
};
std::wcout
<< L"s.title = " << s.title << std::endl
<< L"s.font_size = " << s.font_size << std::endl;
return 0;
}
If I hit F7 to compile, I get the following error message:
example.cpp(10,9): error C2440: 'initializing': cannot convert from 'const wchar_t *const ' to 'wchar_t'
I would not like to enter L"Title" two times, and I would not like to calculate the length of the string manually. So, what can be a good substitute for the macro, which is capable of both initializing the struct and determining the size of the array in the struct?
A template is a reasonably common replacement for macro usage. Since you don't want to manually calculate the length of the string (I don't blame you), let's make a length (the array length, not the string length) the template parameter. Your anonymous struct becomes a likely candidate for being the templated entity, as you do end up with a different type each time you change the length of your title.
The actual conversion to a template is simple enough (given the level of the question) that I won't go over the details here. The nifty part comes when you write a constructor. By using the template parameter in the argument list, the compiler will be able to deduce it. This gives you the ease-of-use you appear to be looking for, albeit at the cost of some additional setup.
Caveat: Deducing the template parameter via an argument to the constructor is a C++17 feature. Anyone stuck on C++11 or 14 (hopefully not many of you) can get a similar result by writing a separate function template that constructs and returns a struct. I'll leave that as an exercise.
#include <iostream>
#include <cstring> // For memcpy
template <size_t N>
struct DlgTemplate {
wchar_t title[N];
int font_size;
// Constructor that will deduce `N`.
// For those not familiar with this syntax: the incoming title_ is a
// reference to an array with exactly N elements.
DlgTemplate(const wchar_t (&title_)[N], int font_size_) :
font_size(font_size_)
{
// Copy the title.
std::memcpy(title, title_, sizeof(title));
}
// Reminder: N is the array length, which includes the null terminator.
// The string length is N-1.
};
int main()
{
// As of C++17, the template argument can be deduced here.
auto s = DlgTemplate(L"Title", 12);
std::wcout
<< L"s.title = " << s.title << std::endl
<< L"s.font_size = " << s.font_size << std::endl;
}
The next consideration is probably how to deal with all the fields that were mercifully left out of the question. One option is to add more parameters to the constructor to handle all of the fields. However, in the interest of readability, I might be inclined to remove font_size_ as a constructor parameter (remembering to mark the constructor explicit) then set each field after construction. The following is what I have in mind for the initialization.
auto s = DlgTemplate(L"Title");
s.font_size = 12;
//s.other_field = value;
// etc.
There is one important detail to note from the question. The "potential fix" implemented by Visual Studio caused the length information to be lost.
constexpr auto TITLE = L"Title";
defines TITLE to be a pointer (to const wchar_t). Its size is fixed, independent of the length of the title. The calculation sizeof( TITLE ) / sizeof( TITLE[ 0 ] ) does not give the length of the title, and this TITLE will not work with the template.
constexpr wchar_t TITLE[] = L"Title";
defines TITLE to be an array, with the length information kept as part of the type. This TITLE can be used with the template.
Depends what you really want. One way is to use std::wstring_view instead of the array, but this may suit your needs or not.
If it does, it's pretty easy:
struct {
std::wstring_view title = L"Title";
int font_size{12};
} s;
DLGTEMPLATEEX is a special case. In fact, there is no structures with such a name in the wndows headers. If you want to use a structure, you must create you own, with custom array sizes.4
Example
constexpr TCHAR TITLE[] = _T("Title"); // IMPORTANT! To be 100% sure that's a array,
// declare it explicitely.
struct MyDlgTemplateEx {
WORD dlgVer;
WORD signature;
DWORD helpID;
DWORD exStyle;
DWORD style;
WORD cDlgItems;
short x;
short y;
short cx;
short cy;
TCHAR menu[1];
TCHAR WwindowClass[1];
TCHAR title[sizeof(TITLE) / sizeof(TITLE[0]);
WORD pointsize;
WORD weight;
BYTE italic;
BYTE charset;
TCHAR typeface[1]; // a NULL string.
};
The first thing that's obvious it that there are quite a few member variables. Doing unnamed in-place initialization (as in your example), with no explicit member names can very easily lead to mistakes and bugs.
The most common way of initializing such large structures is explicitely:
// ...
MyDlgTemplateEx tmpl = {}; // this declatres and fills structure with zeroes.
// initialize all non-zero members explicitely.
// cutting and pasting the structure declaration and editing around that is fairly fast.
tmpl.dlgVer = 1;
tmpl.signature = 0xFFFF; // this is a DLGTEMPLATEEX struct.
tmpl.exStyle = WS_EX_DLGMODALFRAME;
tmpl.style = WS_CAPTION;
tmpl.cDlgItems = 1;
tmpl.x = 10;
tmpl.y = 10;
tmpl.cx = 100;
tmpl.cy = 100;
_tcscpy_s(tmpl.title, TITLE); // must copy into array that's in structure.
Related
I am trying to make a keyword-recognizing subroutine under OSX Yosemite, see the listing below. I do have a couple of strange things.
I am using the "playground" for making MWE, and the project builds seemingly OK, but does not want to run:
"My Mac runs OS X 10.10.5, which is lower than String sort's minimum deployment target."
I do not understand even the message, and especially not what my code makes with sorting?
Then, I pasted the relevant code to my app, where the project was generated using CMake, and the same compiler, and the same IDE, in the same configuration presents with the message
"Non-aggregate type 'vector cannot be initialized with an initializer list"
in the "vector QInstructions={..}" construction.
When searching for similar error messages, I found several similar questions, and the suggested solutions use default constructor, manual initialization, and the like. I wonder if standard-resistant compact initialization is possible?
#include <iostream>
using namespace std;
#include <vector>
enum KeyCode {QNONE=-1,
QKey1=100, QKey2
};
struct QKeys
{ /** The code command code*/
std::string Instr; ///< The command string
unsigned int Length; ///< The significant length
KeyCode Code; //
};
vector<QKeys> QInstructions={
{"QKey1",6,QKey1},
{"QKey2",5,QKey2}
};
KeyCode FindCode(string Key)
{
unsigned index = (unsigned int)-1;
for(unsigned int i=0; i<QInstructions.size(); i++)
if(strncmp(Key.c_str(),QInstructions[i].Instr.c_str(),QInstructions[i].Length)==0)
{
index = i;
cout << QInstructions[i].Instr << " " <<QInstructions[i].Length << " " << QInstructions[i].Code << endl;
return QInstructions[i].Code;
break;
}
return QNONE;
}
int main(int argc, const char * argv[]) {
string Key = "QKey2";
cout << FindCode(Key);
}
In your code
vector<QKeys> QInstructions={
("QKey1",6,QKey1),
{"QKey2",5,QKey2}
};
the first line of data is using parenthesis "()". Replace them with accolades "{}" and it will work.
Also, i see you have written unsigned index = (unsigned int)-1;. This is undefined behavior according to the standard. This is also bad because you are using a C-style cast (see here). You should replace it with:
unsigned index = std::numeric_limits<unsigned int>::max();
Finally, I found the right solution as
Initialize a vector of customizable structs within an header file . Unfortunately, replacing parenthesis did not help.
Concerning setting an unsigned int to its highest possible value using -1, I find as overkill to use std::numeric_limits<unsigned int>::max() for such a case, a kind of over-standardization. I personally think that as long as we are using two's complement representation, the assignment will be correct. For example, at
http://www.cplusplus.com/reference/string/string/npos/
you may read:
static const size_t npos = -1;
...
npos is a static member constant value with the greatest possible
value for an element of type size_t.
...
This constant is defined with a value of -1, which because size_t is
an unsigned integral type, it is the largest possible representable
value for this type.
I do not understand why the pointer addition is failing.
DWORD *pipebuf=new DWORD[10001];
Command *cr= (Command*)pipebuf;
cr->command=2;
DWORD* rooms=(pipebuf+1); //should work fine..sets the room pointer equal to pipe[2]
*rooms=buff3; //where buff3=100
Yet, the value of pipebuf only contains the value of command, it does not contain the value of buff3. Yet, when I remove the new keyword it works fine...Why?
DWORD=unsigned_int
Command is a class with a DWORD variable of command.. something like this
Class Command {
DWORD command;
}
The addition moves the pointer forward one, causing it to point at the second DWORD in your array. *(pipebuf+1) is precisely equivalent to pipebuf[1]; after your code runs, *pipebuf aka pipebuf[0] aka cr->command is equal to 2, while *(pipebuf+1) aka *rooms aka pipebuf[1] is equal to 100.
Note however that typecasting between pointer types in C++ is often considered bad style and can in many circumstances have undesirable results. If you are allocating an array of Command's, then use new Command[...]; if you want DWORD's, then don't cast into Command*.
Sometimes you have to cast pointers between types, but generally you should only do that if you know exactly what you're doing and why you can't avoid doing so.
Furthermore, if you do need to, you should either be using static_cast (in cases like this) or dynamic_cast (in cases where the types are related by inheritance; this usage is much safer generally).
class Command is a user defined type and DWORD is a primitive data type ( unsigned int ). In that case, why doing this -
Command *cr= (Command*)pipebuf;
class Command {
public : // Added public keyword
DWORD command; // DWORD is a typedef for unsigned int as you mentioned.
}; // class definition should end with a semi-colon
So, this is the way to do -
Command *cr = new Command[10001] ;
DWORD *pipebuf=new DWORD[10001];
// After assigining values to DWORD pointed locations. Then you can do this -
cr->command = pipebuf[0] ; // this sets the value of cr[0].command.
I'd make this a comment, but I can't do code formatting in those.
I ran this code, and the output is "2 100" as expected:
#include <iostream>
using namespace std;
typedef unsigned int DWORD;
class Command {
public:
DWORD command;
};
int main()
{
DWORD buff3 = 100;
DWORD *pipebuf = new DWORD[10001];
Command *cr = (Command*)pipebuf;
cr->command = 2;
DWORD *rooms = (pipebuf+1);
*rooms = buff3;
std::cout << pipebuf[0] << " " << pipebuf[1] << endl;
}
AFAICT that's the simplest way you could expand your question into a complete program.
Could you try taking this and adding more stuff from the original code until you get the problem to appear?
I am passing an array to a function, and i am initializing it globally with some values.
I am using empty string in end of array to determine the array length.
Now, Is there some way to automatically initialize the array to have extra empty item in the end of it, so i have no chances to forget it from there? Just like the char[] works, it adds extra null to the end IIRC.
Here is my code what im using now:
struct twostrings {
string s1, s2;
};
twostrings options[] = {
{"text1", "more text1"},
{"text2", "more text2"},
{"text3", "more text3"},
{""}, // tells that the array ends here
}
int get_len(twostrings opt[]){
int p = 0;
while(1){
if(opt[p].s1 == ""){
return p;
}
p++;
// now here is a possibility to go in infinite loop if i forgot the empty string.
// currently i have a code here that checks if p > 10000 and gives error message to me if i manage to forget that empty string in accident.
}
return p;
}
void dosomething(twostrings options[]){
int len = get_len(options);
for(int p = 0; p < len; p++){
// do stuff
}
}
int main(){ // yes its not valid written main function. dont bother about it.
dosomething(options);
}
Passing around C arrays is not very idiomatic in C++. Try using a std::vector instead:
#include <vector>
#include <string>
struct twostrings {
std::string s1, s2;
};
typedef std::vector<twostrings> option_type;
twostrings options[] = {
{"text1", "more text1"},
{"text2", "more text2"},
{"text3", "more text3"}
};
int get_len(const option_type& options){
return options.size();
}
void dosomething(const option_type& options){
int len = get_len(options);
for(int p = 0; p < len; p++){
// do stuff
}
}
int main() { // This main function is perfectly fine!
option_type opt_vector(options, options + (sizeof options / sizeof options[0]));
dosomething(opt_vector);
}
Unforunately, you're not correct. The char array does not end automatically in a null, this is only a side effect of assigning it with a string literal (which has the automatic null at the end).
char x[] = "ABC"; // size 4, contains A, B, C, \0.
char x[] = {'A','B','C'}; // size 3, contains no terminating null.
So the short answer is no, there's no way to automatically end arrays with an automatic entry. There are a bunch of other options though, such as STL vectors which have other means of determining when you've reached the end. In C++0x there'll probably (IIRC) be a way to initialize the vector just like you'd like.
HTH.
EDIT:
Personally, I prefer to add the extra 0 at the end of the array myself, but I suppose there are ways to work around it using macros.
#define ARRAY(...) {__VA_ARGS__, {0}}
and use it like so
struct foo { char* x; char* y; }
struct foo x[] = ARRAY({"abc", "xyz"}, {"def","uvw"});
I have no idea if this works (and I have no preprocessor handy), and as I said, personally I don't like it. It also requires the first element in the struct to be something which can be assigned 0 to mark the end of the array.
Of course, this forces you to remember to wrap it in the macro call, which is pretty much as bad as forcing you to remember to terminate the array.
EDIT:
I just had a chance to test this and it works. Turns out variadic macros are, so far anyway, C only. However some (most?) C++ compilers support them anyway, a quick search turned up g++ and visual studio. Still I wouldn't favor this approach, I just added it for completeness.
Pass the length or the end instead of using a sentinel:
template<class T, int N>
int len(T (&)[N]) { // exists in a more general form as boost::size
return N;
}
typedef std::pair<std::string, std::string> twostrings;
// std::pairs have first and second members of the given types
void dosomething(twostrings options[], int size);
// call as: dosomething(array, len(array));
# or:
template<class T, int N>
T* end(T (&a)[N]) { // exists in a more general form as boost::end
return a + N;
}
void dosomething(twostrings* options_begin, twooptions* options_end);
// call as: dosomething(array, end(array));
// usage example:
void dosomething(twostrings* options_begin, twooptions* options_end) {
// you might name the parameters just 'begin' and 'end'
for (; options_begin != options_end; ++options_begin) {
// the 'begin' var advances through the entire sequence
// use for (twostrings* current = options_begin; current != options_end; ++current)
// if a separate copy is required
cout << options_begin->first << ": " << options_begin->second << '\n';
}
}
Note the [begin, end) iterator pattern (that's inclusive begin, exclusive end) is common in the stdlib (e.g. look at std::sort from <algorithm>).
This is a good halfway measure between arrays and containers such as std::vector, and allows you to keep the easy initialization syntax you have now (C++0x gives you that same syntax with containers such as std::vector, but 0x is not quite yet ready).
Don't use C style arrays in C++, they're just not worth the effort compared to vector.size(). You should use a boost::array<twostrings, length> for a static array.
Hell, you should probably just not use a static value.
There are better ways of finding array lengths. You can use:
1. sizeof(options) / sizeof(twostrings);
2. sizeof(options) / sizeof(options[0]);
3. std::vector<twostrings> options;
options.size();
4. ARRAYSIZE(options); (windows only)
Btw, if(opt[p].s1 == "") is checking 2 const char * pointers for equality, not 2 strings. Although compiller usualy optimizes equal string constants to point to one place, it is still an error.
You should use a NULL sentinell as it was adviced by Svisstack earlier.
edit: Proof
#include <stdio.h>
const char *one = "the string";
void main(){
const char *other = "the string";
printf("adress of 'one' = %x, it contains \"%s\"\n", one, one);
printf("adress of 'other' = %x, it contains \"%s\"\n", other, other);
if(one == other){
printf("one == other\n", one);
} else {
printf("one != other\n", one);
}
}
Output:
k:\temp>cl test.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
/out:test.exe
test.obj
k:\temp>test.exe
adress of 'one' = 3d8140, it contains "the string"
adress of 'other' = 3d814c, it contains "the string"
one != other
I know C++ and know the function sizeof itself but I need to write my own sizeof function so please explain how it works exactly? What does it do with the parameter?
sizeof is a compiler built-in operator. It is evaluated at compile-time by the compiler, and there is no runtime code behind it. You cannot write your own.
Asking this is akin to asking how you would write your own version of return.
You haven't provided any meaningful details about what it is you want to do, so it is hard to figure out what you need.
You can "wrap" sizeof by you own template function like
template <typename T> size_t my_sizeof() {
return sizeof(T);
}
and then use it as
size_t s = my_sizeof<int>();
From time to time one can come across a request to implement sizeof-like functionality without using sizeof. Requests like that make no practical sense whatsoever, yet sometimes are used as homework assignments. One can probably do it as follows
template <typename T> size_t my_sizeof() {
T t;
return (char *) (&t + 1) - (char *) &t;
}
which would require a default-constructible T. A less restricting but formally illegal solution (a hack) would be something like
template <typename T> size_t my_sizeof() {
return (char *) ((T *) NULL + 1) - (char *) (T *) NULL;
}
The above implementations implement type-based sizeof.
An attempt to emulate the functionality of value-based sizeof might look as follows
template <typename T> size_t my_sizeof(const T& obj) {
return my_sizeof<T>();
}
but this will not be even remotely equivalent to the built-in sizeof, at least because the built-in sizeof does not evaluate its argument.
Finally, neither of these implementations will produce integral constant expressions (ICE), as the built-in sizeof does. Producing an ICE that way is impossible to achieve in the current version of the language.
In any case this all, of course, is totally devoid of any practical value. Just use sizeof when you want to know the size.
A non-portable way to write your own sizeof() function is to take advantage of how stack-based variables are often laid out in memory:
#include <iostream>
using namespace std;
template <typename T>
int mysizeof(T)
{
T temp1;
T temp2;
return (int)&temp1 - (int)&temp2;
}
int main()
{
cout << "sizeof mysizeof" << endl;
char c = 0; short s = 0; int i = 0; long l = 0;
float f = 0; double d = 0; long double ld = 0;
cout << "char: " << mysizeof(c) << endl;
cout << "short: " << mysizeof(s) << endl;
cout << "int: " << mysizeof(i) << endl;
cout << "long: " << mysizeof(l) << endl;
cout << "float: " << mysizeof(f) << endl;
cout << "double: " << mysizeof(d) << endl;
cout << "long double: " << mysizeof(ld) << endl;
}
See it in action.
A 0-parameter version.
A version that uses one array instead of two variables.
Warning: This was a fun puzzle, but you should never use this in real code. sizeof is guaranteed to work. This is not. Just because it works on this version of this compiler for this platform does not mean it will work for any other.
The real operator takes advantage of being a part of the compiler. Sizeof knows how big each type of variable is because it has to know. If the compiler doesn't know how big each type is, it wouldn't be able to lay your program out in memory.
Edit: Note that all of these flawed examples rely on the original sizeof operator. It's used to space the stack variables, and to create and index array variables.
As already said it is an operator not a function, but additionally it is one of the operators for which operator overloading is not allowed:
Bjarne Stroustrup's C++ Style and Technique FAQ: Why can't I overload dot, ::, sizeof, etc.?
I can think of no conceivable reason why you would want to overload this in any case. If you have an class for which size information other than that which sizeof yields is required, then simply add a member function to provide that information; as for example in std::string:size() which returns the length of the string managed by the object rather than the size of the object which is semantically different; you do not want to monkey with the semantics of sizeof!
sizeof is an C++ operator which yields the number of bytes in the object representation of its operand. Result of sizeof is an implementation-defined constant of type size_t, but should meet the requirements set forth in C++ Standard 5.3.3. You could write your own type traits that will work similar to built-in sizeof operator.
template<typename T> struct get_sizeof;
template<> struct get_sizeof<char> { static const size_t value = 1; };
template<> struct get_sizeof<unsigned char> { static const size_t value = 1; };
template<> struct get_sizeof<int> { static const size_t value = 4; };
template<> struct get_sizeof<long> { static const size_t value = 4; };
// etc.
...
// sample of use
static const size_t size = get_sizeof<int>::value;
char x[get_sizeof<int>::value];
But this have no sense since only creators of the compiler are knows actual values of value for the implementation.
sizeof isn't a function, and you can't write your own version. The compiler works out the type of the argument (unless it's already a type), then substitutes the expression with an integer constant.
I saw this post when searching for a way to get the same functionality as the sizeof operator. It turned out that I implemented a function called bit_sizeof() that looks a lot like the operator sizeof, but which returns the number of bits of a given type instead. I implemented a global template function like this:
#include <limits.h> //For CHAR_BIT
//Global function bit_sizeof()
template<typename TSizeOfType>
constexpr uint32_t bit_sizeof(TSizeOfType)
{
return (sizeof(TSizeOfType) * CHAR_BIT);
}
This function requires the use of the c++11 standard, as it uses the keyword constexpr. Without the keyword constexpr, the function will compile still. But the compiler may not optimize properly and put in a function call at each call site of using the bit_sizeof function. With the use of constexpr, the whole function evaluates to a constant, which in my knowledge should be exactly equivalent to how the sizeof operator works? Correct me if I am wrong. In use I call the function like this, with an added parantesis after the type:
uint32_t uiBitsInType = bit_sizeof(char());
The function can be useful when creating bit masks for example:
uint32_t uiMask = (((uint32_t(0x1) << bit_sizeof(char())) - 0x1) << bit_sizeof(char()));
Which could be more readable than this:
uint32_t uiMask2 = (((uint32_t(0x1) << (sizeof(char) * 0x8)) - 0x1) << (sizeof(char) * 0x8));
Personally I have other uses for this function also.
If he wants to write his own sizeof he just needs to grab the source code of a C++ compiler and go ahead. The source will also show how sizeof can be implemented.
sizeof is evaluated at compile-time (Boost and Loki make use of it). So, I think, it is impossible to write sizeof - complain function for dynamically allocated buffer.
sizeof isn't a function. It's an operator in C.
We can implement its functionality something like follows.
#include <stdio.h>
#define mysizeof(X) \
({ \
__typeof(X) x; \
(char *) (&x+1) - (char*) (&x); \
})
int main()
{
struct sample
{
int a;float b; char c;
};
printf("%d", mysizeof(struct sample));
return 0;
}
Answer : 12
In C/C++, how do I determine the size of the member variable to a structure without needing to define a dummy variable of that structure type? Here's an example of how to do it wrong, but shows the intent:
typedef struct myStruct {
int x[10];
int y;
} myStruct_t;
const size_t sizeof_MyStruct_x = sizeof(myStruct_t.x); // error
For reference, this should be how to find the size of 'x' if you first define a dummy variable:
myStruct_t dummyStructVar;
const size_t sizeof_MyStruct_x = sizeof(dummyStructVar.x);
However, I'm hoping to avoid having to create a dummy variable just to get the size of 'x'. I think there's a clever way to recast 0 as a myStruct_t to help find the size of member variable 'x', but it's been long enough that I've forgotten the details, and can't seem to get a good Google search on this. Do you know?
Thanks!
In C++ (which is what the tags say), your "dummy variable" code can be replaced with:
sizeof myStruct_t().x;
No myStruct_t object will be created: the compiler only works out the static type of sizeof's operand, it doesn't execute the expression.
This works in C, and in C++ is better because it also works for classes without an accessible no-args constructor:
sizeof ((myStruct_t *)0)->x
I'm using following macro:
#include <iostream>
#define DIM_FIELD(struct_type, field) (sizeof( ((struct_type*)0)->field ))
int main()
{
struct ABC
{
int a;
char b;
double c;
};
std::cout << "ABC::a=" << DIM_FIELD(ABC, a)
<< " ABC::c=" << DIM_FIELD(ABC, c) << std::endl;
return 0;
}
Trick is treating 0 as pointer to your struct. This is resolved at compile time so it safe.
You can easily do
sizeof(myStruct().x)
As sizeof parameter is never executed, you'll not really create that object.
Any of these should work:
sizeof(myStruct_t().x;);
or
myStruct_t *tempPtr = NULL;
sizeof(tempPtr->x)
or
sizeof(((myStruct_t *)NULL)->x);
Because sizeof is evaluated at compile-time, not run-time, you won't have a problem dereferencing a NULL pointer.
In C++11, this can be done with sizeof(myStruct_t::x). C++11 also adds std::declval, which can be used for this (among other things):
#include <utility>
typedef struct myStruct {
int x[10];
int y;
} myStruct_t;
const std::size_t sizeof_MyStruct_x_normal = sizeof(myStruct_t::x);
const std::size_t sizeof_MyStruct_x_declval = sizeof(std::declval<myStruct_t>().x);
From my utility macros header:
#define FIELD_SIZE(type, field) (sizeof(((type *)0)->field))
invoked like so:
FIELD_SIZE(myStruct_t, x);