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.
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;
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;
}
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.
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
}
Related
I have a structure like this
struct {
int id;
char str00[10];
char str01[10];
char str03[10];
char str04[10];
...
} myStructure;
All strXX have the same size. I would like to access them via an array (strArray), like this :
strcpy(strArray[i], strValue);
How to declare strArray ?
I used this:
char (*strArray)[][10] = (void *)&myStructure.str00;
It's working, but I have to code the strcpy like this
strcpy((*strArray)[i], strValue);
... and I don't like this :-)
Is there another way to declare strArray ?
Thanks for your ideas and help.
You almost had it, the correct pointer type is simply char (*ptr)[10].
Naively, you could use this pointer type to iterate over the struct members, but doing so would invoke undefined behavior. Because strictly speaking, a pointer can only point at single item or an array, and if we use pointer arithmetic to go beyond that single item/array, we invoke undefined behavior.
I'll include an example still, for the sake of demonstrating array pointer arithmetic:
// BAD CODE, it relies on undefined behavior!
#include <stdio.h>
#include <string.h>
typedef struct {
int id;
char str00[10];
char str01[10];
char str02[10];
char str03[10];
} myStructure;
int main(void)
{
myStructure ms = { 0 };
char (*ptr)[10] = &ms.str00;
for(size_t i=0; i<4; i++)
{
strcpy(ptr[i], "hello ");
strcat(ptr[i], (char[]){i+'0', '\0'});
}
puts(ms.str00);
puts(ms.str01);
puts(ms.str02);
puts(ms.str03);
return 0;
}
The proper solution is to instead use a union, so that you can access the members either individually, or as an array:
typedef union {
struct // anonymous struct, requires a standard C compiler
{
char str00[10];
char str01[10];
char str02[10];
char str03[10];
};
char array[4][10];
} str_t;
typedef struct {
int id;
str_t str;
} myStructure;
strcpy(ms.str.array[i], ...); // access as array
puts(ms.str.str00); // access as individual item
The cleanest way to define strArray as requested would be to make it an array of pointers to the (first elements of the) arrays in myStructure:
char *strArray[] = { myStructure.str00, myStructure.str01, myStructure.str03, myStructure.Str04, … };
With this definition, strArray[i] is initialized to the corresponding member of the structure, such as myStructure.str01. Note that myStructure.str01 will be automatically converted to a pointer to its first element, so strArray[i] is a pointer to the first char in one of the arrays.
Then strArray[i][j] is char j of array i.
(Incidentally, you skip str02 in your sample code. I do not know why but have retained that in the code above.)
An alternative method would be to use a union, which can be done in various ways, one of which is:
struct
{
int id;
union
{
struct
{
char str00[10];
char str01[10];
char str03[10];
char str04[10];
...
};
char strArray[number of arrays][10];
};
} myStructure;
That is generally a poor design, as it is needlessly confusing. (While this has a technical possibility of failure due to padding between the individually defined arrays, assertions can be used to ensure this does not occur, or rather to detect when it does.)
Most often, we would simply define the strings as an array of arrays:
struct
{
int id;
char str[number of arrays][10];
} my Structure;
Then the members would always be referred to by index, such as myStructure.str[1], and not by individual names, such as myStructure.str01.
I have a C function which needs a large amount of variables to be passed, so I came to the idea of "packing" them all in a single array (matrix of variables). The point is, these variables are of a very different type, some int, some arrays (strings and vectors), and many of them float. Is there a way to leave unspecified the type of data stored into the matrix? (I unsuccessfully explored the void "data type")
The elements of an array are always of a single type, that's the point.
Collecting variables of multiple types is the job for a structure, i.e. a struct.
This is a quite common way to solve this particular problem. If the structure becomes large, you might find it convenient to pass a pointer to an instance of it, rather than copying the entire thing in the call.
You can use va_list but struct is the best way to do it
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
enum type {
INT,
FLOAT,
PCHAR,
};
struct any_type {
enum type type_;
union {
int int_;
float float_;
char* pchar_;
};
};
#define MYSIZE 10
void process(size_t size, struct any_type* array)
{
for(int i = 0; i < size; i++) {
switch(array[i].type_) {
case INT :
printf("INT: %d\n", array[i].int_);
break;
case FLOAT :
printf("FLOAT: %f\n", array[i].float_);
break;
case PCHAR :
printf("PCHAR: %s\n", array[i].pchar_);
break;
default:
printf("UNKNOWN TYPE PROVIDED\n");
break;
}
}
}
int main(int argc, char *argv[])
{
struct any_type *array;
array = malloc(MYSIZE*(sizeof(struct any_type)));
array[0].type_ = INT;
array[0].int_ = 10;
array[1].type_ = FLOAT;
array[1].float_ = 2.5;
array[2].type_ = PCHAR;
array[2].pchar_ = "hello char";
process(3, array);
return 0;
}
You can extend type and union as needed. However using nameless unions require -std=c11.
Expanding on my comment above:
Needing to pass a large number of parameters1 to a function can be a sign that there is a problem in your design - your function may be trying to do too many things at once, and you would be better off refactoring it into several smaller functions, each of which only takes a subset of the parameters.
Assuming that's not the case, how are your parameters logically related to each other? Can they be considered attributes of a single data item? For example, a person may be described by the following attributes: surname, given name, birth date, sex. These can be collected together into a single struct type such as
#include <time.h>
struct person {
char *surname;
char *name;
struct tm birthdate; // struct tm defined in time.h
char sex;
};
void write_to( struct person *p )
{
p->surname = strdup( "McGillicuddy" );
p->name = strdup( "Aloysius" );
p->sex = 'M';
p->birthdate.tm_year = 32; // tm_year starts at 1900, so this is 1932
p->birthdate.tm_mon = 11; // december
p->birthdate.tm_day = 1;
};
int main( void )
{
struct person p;
...
write_to( &p );
...
}
Note that members of struct types can themselves be struct types - struct tm is a type defined in time.h that specifies a datetime value using multiple attributes.
Some notes on syntax:
When you want to access a member of a struct instance, use the . operator. When you want to access a member of a struct through a pointer, use the -> operator. In the function write_to, p is a pointer to struct person, so to access each member of p we use ->. The birthdate member is an instance of struct tm, not a pointer, so we use the . operator to access each member of birthdate.
p->m is equivalent to (*p).m.
Like I said in my comment, you should not collect otherwise unrelated items into a struct type just to reduce the number of parameters being passed to a function. They should all be attributes of a more complex type. Some other examples of what I mean:
// A node in a list
struct node {
data_t data; // for some data type data_t;
struct node *next;
struct node *prev;
};
// A street address
struct addr {
char *number; // to handle things like 102A, 102B
char *street;
char *city;
char state[3];
char *zip;
};
It's possible that you're really passing only a couple of distinct data items to your function, each of which is composed of a lot of different attributes. Take a step back and look at your variables and see how they relate to each other.
"Large" depends on context, and of course there are always exceptions to any rule, but in general passing more than 7 distinct, unrelated parameters is a sign you may need to refactor your function into several smaller functions.
I came across this code.
typedef __mpz_struct MP_INT;
typedef __mpz_struct mpz_t[1];
Here the struct __mpz_struct is a struct that is typedefed to an array of single element. I understand that this is a trick to pass by reference in C. Then mpz_t has been used as a type to declare variables and pass them to function as parameters. Also, There was one more comment
/*
MP_INT*, MP_RAT* and MP_FLOAT* are used because they don't have side-effects
of single-element arrays mp*_t
*/
What kind of side effects are they talking about?
Passing an array to a function let's the array decay to a pointer to it's 1st element.
One can achieve the same effect by applying the Address-Of operator & to a simple variable of the same type as the array's elements.
Examples:
struct S
{
int i;
float f;
};
This
void set_S(struct S * ps)
{
ps->i = 40;
ps->f = 2.;
}
is equivalent to
void set_S(struct S ps[1])
{
ps->i = 40;
ps->f = 2.;
}
is equivalent to
void set_S(struct S * ps)
{
ps[0].i = 40;
ps[0].f = 2.;
}
is equivalent to
void set_S(struct S ps[1])
{
ps[0].i = 40;
ps[0].f = 2.;
}
One-Element-Array approach:
typedef struct S Array_of_S_with_size_1[1];
int main(void)
{
Array_of_S_with_size_1 array_of_S_with_size_1;
array_of_S_with_size_1[0].i = 0;
array_of_S_with_size_1[0].f = 0.;
set_S(array_of_S_with_size_1);
...
}
The above main() provides the same functionality as the following:
int main(void)
{
struct S s;
s.i = 0;
s.f = 0.;
set_S(&s);
...
}
I do not see any gain using the "One-Element-Array" approach. An expection might be if the &-key is broken on ones keyboard ... ;-)
I see two parts to your question. The first part, how the typedef works for passing arguments to functions, would better be illustrated with an example. Without it, I'll have to guess a bit.
In C function declarations, an array parameter is equivalent to a pointer. That's why you see (for example) equivalently for the main function,
int main(int argc, char **argv)
and
int main(int argc, char *argv[])
Similarly, if a function in your program would be declared
int func(__mpz_struct *arg)
it would be equivalent to
int func(__mpz_struct arg[])
and hence to
int func(mpz_t arg)
Also, on the calling side, if you have a variable of type mpz_t, hence the array, and you pass it to a function, the "pointer decay" takes effect: in an expression, if you use (the name of) an array it "decays" into a pointer to its first element.
This way you can call the function:
mpz_t value;
func(value);
Of course, to modify these mpz_t objects outside of the API functions, you still have to be aware of their true nature.
The side effects that you mention, I would also have to guess about them. Possibly it is meant that you have to be aware you're working with pointers inside the functions. It might be considered better to make that explicit by using the pointer syntax.
You can assign an MP_INT to another but you can not assign an mpz_t to another since assignment is not defined for arrays. If you do not want your clients to assign variables other than by your methods (which might do memory managements and stuff) this is the trick for you.
Look at this sample code
typedef char type24[3];
Same as your, but well known data type 'char' insted of your struct __mpz_struct type.
above type def means, I am using above typedef to represent char[3].
So in your sample code,
typedef __mpz_struct mpz_t[1];
mpz_t should be __mpz_struct type.
Not entirely sure my question title describes what I want to do, but couldn't think how better to word it!! I'm using C, and perhaps the pseudocode below will describe what I'm trying to do:
typedef struct obj
{
char *str1;
char *str2;
char *str3;
} object;
/* global variable */
object *glob;
void black_box_function(local, member) ????
{
/* Do something with glob->member and local->member */
}
void main()
{
object *ob1, *ob2;
/* Initialise glob, ob1 and ob2 somewhere */
black_box_function(ob1, str1);
black_box_function(ob2, str3);
}
Hopefully, you can see what I'm trying to do. I have a "black-box" function that will do something with a particular member, and I need to be able to tell the black-box function which member to use.
I don't want to just pass the member directly to the function, like in this code, as that won't fit into the rest of my code easily.
black_box_function(ob1->member, glob->member)
You could do the following magic (with GCC extensions):
#define black_box(local, member) black_box_function((local), __builtin_offsetof(object, member))
void black_box_function(object *local, int offset)
{
char *lmember = ((void *)local) + offset;
char *gmember = ((void *)global) + offset;
/* do stuff */
}
However, you must know in advance the type of your members. Keep in mind that C is not a dynamically typed language, so you have no runtime introspection at all.
EDIT: You can implement offsetof() functionality without resorting to GCC extensions, like this:
#define offsetof(type, field) ((int) (unsigned long) &((type *) 0)->field)
Perhaps you could create accessor functions for your struct and pass those accessors as function pointer arguments instead of passing the members directly
typedef struct
{
int a;
int b;
} foo;
typedef int* (*accessor)(foo*);
int* get_a(foo* f) { return &f->a; }
int* get_b(foo* f) { return &f->b; }
void black_box_function(foo* object, accessor fn)
{
int* p = fn(object);
}
int main(void)
{
foo bar1;
foo bar2;
black_box_function(&bar1, get_a);
black_box_function(&bar2, get_b);
return 0;
}
Since all are char*, you can redefine the struct like:
typedef struct obj
{
char **str; // Array of c
} object;
Then you can send the index of str from main which you want work with:
black_box_function(obj1, index)
So you can it like obj1->str[i] in your blackbox.
Btw, black-box_function will not compile.
On a side note: A little more info/code on your blackbox function and compilable code would give a better picture of what you are trying to do.
I have some code with multiple functions very similar to each other to look up an item in a list based on the contents of one field in a structure. The only difference between the functions is the type of the structure that the look up is occurring in. If I could pass in the type, I could remove all the code duplication.
I also noticed that there is some mutex locking happening in these functions as well, so I think I might leave them alone...
If you ensure that the field is placed in the same place in each such structure, you can simply cast a pointer to get at the field. This technique is used in lots of low level system libraries e.g. BSD sockets.
struct person {
int index;
};
struct clown {
int index;
char *hat;
};
/* we're not going to define a firetruck here */
struct firetruck;
struct fireman {
int index;
struct firetruck *truck;
};
int getindexof(struct person *who)
{
return who->index;
}
int main(int argc, char *argv[])
{
struct fireman sam;
/* somehow sam gets initialised */
sam.index = 5;
int index = getindexof((struct person *) &sam);
printf("Sam's index is %d\n", index);
return 0;
}
You lose type safety by doing this, but it's a valuable technique.
[ I have now actually tested the above code and fixed the various minor errors. It's much easier when you have a compiler. ]
Since structures are nothing more than predefined blocks of memory, you can do this. You could pass a void * to the structure, and an integer or something to define the type.
From there, the safest thing to do would be to recast the void * into a pointer of the appropriate type before accessing the data.
You'll need to be very, very careful, as you lose type-safety when you cast to a void * and you can likely end up with a difficult to debug runtime error when doing something like this.
I think you should look at the C standard functions qsort() and bsearch() for inspiration. These are general purpose code to sort arrays and to search for data in a pre-sorted array. They work on any type of data structure - but you pass them a pointer to a helper function that does the comparisons. The helper function knows the details of the structure, and therefore does the comparison correctly.
In fact, since you are wanting to do searches, it may be that all you need is bsearch(), though if you are building the data structures on the fly, you may decide you need a different structure than a sorted list. (You can use sorted lists -- it just tends to slow things down compared with, say, a heap. However, you'd need a general heap_search() function, and a heap_insert() function, to do the job properly, and such functions are not standardized in C. Searching the web shows such functions exist - not by that name; just do not try "c heap search" since it is assumed you meant "cheap search" and you get tons of junk!)
If the ID field you test is part of a common initial sequence of fields shared by all the structs, then using a union guarantees that the access will work:
#include <stdio.h>
typedef struct
{
int id;
int junk1;
} Foo;
typedef struct
{
int id;
long junk2;
} Bar;
typedef union
{
struct
{
int id;
} common;
Foo foo;
Bar bar;
} U;
int matches(const U *candidate, int wanted)
{
return candidate->common.id == wanted;
}
int main(void)
{
Foo f = { 23, 0 };
Bar b = { 42, 0 };
U fu;
U bu;
fu.foo = f;
bu.bar = b;
puts(matches(&fu, 23) ? "true" : "false");
puts(matches(&bu, 42) ? "true" : "false");
return 0;
}
If you're unlucky, and the field appears at different offsets in the various structs, you can add an offset parameter to your function. Then, offsetof and a wrapper macro simulate what the OP asked for - passing the type of struct at the call site:
#include <stddef.h>
#include <stdio.h>
typedef struct
{
int id;
int junk1;
} Foo;
typedef struct
{
int junk2;
int id;
} Bar;
int matches(const void* candidate, size_t idOffset, int wanted)
{
return *(int*)((const unsigned char*)candidate + idOffset) == wanted;
}
#define MATCHES(type, candidate, wanted) matches(candidate, offsetof(type, id), wanted)
int main(void)
{
Foo f = { 23, 0 };
Bar b = { 0, 42 };
puts(MATCHES(Foo, &f, 23) ? "true" : "false");
puts(MATCHES(Bar, &b, 42) ? "true" : "false");
return 0;
}
One way to do this is to have a type field as the first byte of the structure. Your receiving function looks at this byte and then casts the pointer to the correct type based on what it discovers. Another approach is to pass the type information as a separate parameter to each function that needs it.
You can do this with a parameterized macro but most coding policies will frown on that.
#include
#define getfield(s, name) ((s).name)
typedef struct{
int x;
}Bob;
typedef struct{
int y;
}Fred;
int main(int argc, char**argv){
Bob b;
b.x=6;
Fred f;
f.y=7;
printf("%d, %d\n", getfield(b, x), getfield(f, y));
}
Short answer: no. You can, however, create your own method for doing so, i.e. providing a specification for how to create such a struct. However, it's generally not necessary and is not worth the effort; just pass by reference. (callFuncWithInputThenOutput(input, &struct.output);)
I'm a little rusty on c, but try using a void* pointer as the variable type in the function parameter. Then pass the address of the structure to the function, and then use it he way that you would.
void foo(void* obj);
void main()
{
struct bla obj;
...
foo(&obj);
...
}
void foo(void* obj)
{
printf(obj -> x, "%s")
}