Reputation: 2628
I want to be able to do something like this:
typedef struct
{
char* c_str;
} string;
string s = "hello";
Is it possible to do that in any way?
I know that it is possible to do this:
typedef struct
{
char* c_str;
} string;
string s = { "hello" };
But I do not like the curly brackets when it is only one member variable.
Upvotes: 20
Views: 3240
Reputation: 17573
Not sure if this is actually canonical and fits the C Standards as Microsoft Visual Studio has the reputation of being a bit loose in interpreting the standard, however here is an approach that compiles and works when viewed in the debugger of Visual Studio 2005.
Though if you do not like curly brace initializers you probably would not care for a macro either.
typedef struct {
char *c_str;
} String;
// following macro assigns the string to the struct member and uses the
// comma operator to make the statement return the original struct variable.
#define xString(x, y) ((x).c_str = (y), (x))
void jjj (void)
{
String b = xString(b,"hello");
}
I was able to define multiple variables at a time so multiple variable definitions on the same line compiles as in:
String b = xString(b,"hello"), c = xString(c,"Jello");
It might be that you would want to have a macro that would do the entire statement in a kind of functional language looking construct though there could only be one per statement so multiple on the same line would require semicolons to separate into individual definition statements.
#define xString(x,y) String x = (x.c_str = (y), x)
and it would be used as
void jjj (void)
{
xString(myStruct, "hello");
int j = 2;
// .. do stuff
}
or you could just use
#define xString(x,y) String x = {y}
Initializer list really does seem to be the best approach if you want a struct
for some reason to allow compile time argument checking on a specific type of char *
.
Where it gets kind of awesome is when you do something like the following to initialize multiple struct
members at the time the struct variable is defined.
typedef struct {
int len;
char *c_str;
} String2;
#define yString(x,y) x = (x.c_str = (y), x.len = strlen(y), x)
void jjj (void)
{
String2 b2 = yString(b2,"Hello");
int j = 2;
// .. do stuff
}
Being curious I tried another variation that looks like the following. This does move away from the specific question and more into what are possibilities of following this approach down the rabbit hole. Using the same struct
with a different macro that allows you to specify a struct
member to initialize along with the value.
typedef struct {
int len;
char *c_str;
} String2;
#define zString(x,y,a,b) x=(x.c_str=(y),x.a=(b),x)
void jjj (void)
{
String2 b3 = zString(b3,"Hello",len,72);
// ... do stuff
}
Upvotes: 3
Reputation: 105992
Is it possible to do that in any way?
No. It is not possible to do it with struct
or union
. Para 16 of section 6.7.9 states that
[...] the initializer for an object that has aggregate or union type shall be a braceenclosed list of initializers for the elements or named members.
There is another way to do the same with different data type as explained in this answer.
Upvotes: 4
Reputation: 9092
You could use a typedef
instead of a struct
:
typedef char* string;
string s = "hello";
But then const string
would make the pointer const, and not the pointed-to data. So const string s
is equivalent to char* const s
. A solution may be to define an additional type for const strings:
typedef char* string;
typedef const char* const_string;
For the original struct, the same is true. (C++ has the same "problem", which is why it has iterator
and const_iterator
in its container types.)
An advantage of a typedef for a pointer type is that you can type
string s1, s2, s3;
instead of
char *s1, *s2, *s3;
Upvotes: 31
Reputation: 6756
In C, it is not possible, but you can do it in C++ if you add constructor that takes one appropriate parameter. Compiler will do the rest. You can mark the constructor as explicit if you want to avoid this implicit conversion behaviour.
In C++:
struct string {
char * m_c_str;
/* explicit */ string(char* c_str) : m_c_str(c_str) { }
};
int main(int argc, char * argv[]) {
string s = "hello";
return 0;
}
Upvotes: 14