After understanding that GCC supports Compound Literals, where an anonymous structure can be filled using a {...} initaliser.
Then consider that gcc accepts (with limitations) variable length structures if the last element is variable length item.
I would like to be able to use macros to fill out lots of tables where most of the data stays the same from compile time and only a few fields change.
My structure are complicated, so here is a simpler working example to start with as a demonstration of the how it is to be used.
#include <stdio.h>
typedef unsigned short int uint16_t;
typedef unsigned long size_t;
#define CONSTANT -20
// The data we are storing, we don't need to fill all fields every time
typedef struct dt {
uint16_t a;
const int b;
} data_t;
// An incomplete structure definiton that matches the general shape
typedef struct ct {
size_t size;
data_t data;
char name[];
} complex_t;
// A typedef to make the code look cleaner
typedef complex_t * complex_t_ptr;
// A macro to generate instances of objects
#define CREATE(X, Y) (complex_t_ptr)&((struct { \
size_t size; \
data_t data; \
char name[sizeof(X)]; \
} ) { \
.size = sizeof(X), \
.data = { .a = Y, .b = CONSTANT }, \
.name = X \
})
// Create an array number of structure instance and put pointers those objects into an array
// Note each object may be a different size.
complex_t_ptr data_table[] = {
CREATE("DATA1", 1),
CREATE("DATA2_LONGER", 2),
CREATE("D3S", 3),
};
static size_t DATA_TABLE_LEN = sizeof(data_table) / sizeof(typeof(0[data_table]));
int main(int argc, char **argv)
{
for(uint16_t idx=0; idx<DATA_TABLE_LEN; idx++)
{
complex_t_ptr p = data_table[idx];
printf("%15s = (%3u, %3d) and is %3lu long\n", p->name, p->data.a, p->data.b, p->size);
}
return 0;
}
$ gcc test_macro.c -o test_macro
$ ./test_macro
DATA1 = ( 1, -20) and is 6 long
DATA2_LONGER = ( 2, -20) and is 13 long
D3S = ( 3, -20) and is 4 long
So far so good...
Now, what if we want to create a more complicated object?
//... skipping the rest as hopefully you have the idea by now
// A more complicated data structure
typedef struct dt2 {
struct {
unsigned char class[10];
unsigned long start_address;
} xtra;
uint16_t a;
const int b;
} data2_t;
// A macro to generate instances of objects
#define CREATE2(X, Y, XTRA) (complex2_t_ptr)&((struct { \
size_t size; \
data2_t data; \
char name[sizeof(X)]; \
} ) { \
.size = sizeof(X), \
.data = { .xtra = XTRA, .a = Y, .b = CONSTANT }, \
.name = X \
})
// Again create the table
complex2_t_ptr bigger_data_table[] = {
CREATE2("DATA1", 1, {"IO_TBL", 0x123456L}),
CREATE2("DATA2_LONGER", 2, {"BASE_TBL", 0xABC123L}),
CREATE2("D3S", 3, {"MAIN_TBL", 0x555666L << 2}),
};
//...
But there is a probem. This does not compile as the compiler (preprocessor) gets confused by the commas between the structure members.
The comma in the passed structure members is seen by the macro and it thinks there are extra parameters.
GCC says you can put brackets round terms where you want to keep the commas, like this
MACRO((keep, the, commas))
e.g. In this case, that would be
CREATE_EXTRA("DATA1", 1, ({"IO_TBL", 0x123456L}) )
But that would not work with a structure as we'd get
.xtra = ({"IO_TBL", 0x123456L})
Which is not a valid initaliser.
The other option would be
CREATE_EXTRA("DATA1", 1, {("IO_TBL", 0x123456L)} )
Which results in
.xtra = {("IO_TBL", 0x123456L)}
Which is also not valid
And if we put the braces inside the macro
.xtra = {EXTRA}
...
CREATE_EXTRA("DATA1", 1, ("IO_TBL", 0x123456L) )
We get the same
Obviously some might say "just pass the elements of XTRA one at a time".
Remember this is a simple, very cut down, example and in practice doing that would lose information and make the code much harder to understand, it would be harder to maintain but easer to read if the structures were just copied out longhand.
So the question is, "how to pass compound literal structures to macros as initalisers without getting tripped up by the commas between fields".
NOTE I am stuck with C11 on GCC4.8.x, so C++ or any more recent GCC is not possible.
So there is a way, though I can't find it meantioned on the GCC pages for Macros.
I found what I needed in this article: Comma omission and comma deletion
The following works.
typedef struct _array_data {
size_t size;
char * data;
}array_data_t;
#define ARRAY_DATA(ARRAY...) (char *) \
&(array_data_t) { \
sizeof((char []){ARRAY}), \
(char []){ARRAY} \
}
char * my_array = ARRAY_DATA(1,2,3,4);
size_t sent = send_packet(my_array);
if (len != my_array->size) ERROR("Not all data sent");
There are some interesting aspects to this.
1: Unlike the example in the gcc manual, the brackets are omitted round the {ARRAY}. In the document, the example uses (cast)({structure}) rather than (cast){structure}. In fact it looks like the brackets are never needed and just confuse the compiler in some cases (like when you take the address).
2: The use of the cast (char []) rather than (char *) as one would have thought to be correct.
3: Of course it makes sense but you have to put a cast round the sizeof part too, as otherwise how would it know the size of the individual literals.
For completeness, the macro in the example above expands to:
char * my_array = (char *)&(array_data_t) { \
sizeof((char []){1,2,3,4}),
(char []){1,2,3,4};
}
Any my_array is a pointer to a structure that looks like this.
* my_array = {
size_t size = 4,
char data[4] = {1,2,3,4}
}
Related
std::string (std::basic_string) have assignment operator for 'char' type.
But, for this reason, std::string may assign any integral types.
See little example.
#include <string>
enum MyEnum{ Va = 0, Vb = 2, Vc = 4 };
int main(){
std::string s;
s = 'a'; // (1) OK - logical.
s = Vc; // (2) Ops. Compiled without any warnings.
s = true; // (3) Ops....
s = 23; // (4) Ops...
}
Q: How disable (or add warning ) (2, 3, 4) situations ??
There is a related Question
Given the constraints of C++03 and GCC 4.8 as in the tags, I could not get -Wconversion to do anything useful (and in GCC 7 it doesn't even generate the warnings for me despite telling it that I'm using --std=c++03).
As such, there's a good practical solution that requires only minimal change at your calling site:
Proxy the assignment via a class object that wraps your string and that allows assignment from char but disallows it from int:
#include <string>
enum MyEnum{ Va = 0, Vb = 2, Vc = 4 };
struct string_wr {
string_wr (std::string& s) : val(s) {}
operator std::string& () const { return val; }
// we explicitly allow assigning chars.
string_wr& operator= (char) { return *this; }
// ww explicitly disable assigning ints by making the operator unreachable.
private:
string_wr& operator= (int);
private:
std::string& val;
};
int main(){
std::string s;
s = 'a'; // (1) OK - logical.
s = Vc; // (2) Ops. Compiled without any warnings.
s = true; // (3) Ops....
s = 23; // (4) Ops...
string_wr m(s); // this is the only real change at the calling site
m = 'a'; // (1) OK - logical.
m = Vc; // (2) Should fail with "assignment is private" kind of error.
m = true; // (3) Should fail...
m = 23; // (4) Should fail...
}
However, if your final goal is to specifically get warnings or errors when using std::string, your best option in C++03 is to patch the <string> header to add the private int-assignment operator shown in the class above. But that means patching a system header and the procedure and results will be dependant on your compiler version (and will have to be repeated in each installation and compiler version).
I realize this has been asked before more than once on SO but I couldn't find a question explicitly looking for a current solution to this issue with C++11, so here we go again..
Can we conveniently get the string value of an enum with C++11?
I.e. is there (now) any built-in functionality in C++11 that allows us to get a string representation of enum types as in
typedef enum {Linux, Apple, Windows} OS_type;
OS_type myOS = Linux;
cout << myOS
that would print Linux on the console?
The longstanding and unnecessary lack of a generic enum-to-string feature in C++ (and C) is a painful one. C++11 didn't address this, and as far as I know neither will C++14.
Personally I'd solve this problem using code generation. The C preprocessor is one way--you can see some other answers linked in the comments here for that. But really I prefer to just write my own code generation specifically for enums. It can then easily generate to_string (char*), from_string, ostream operator<<, istream operator<<, is_valid, and more methods as needed. This approach can be very flexible and powerful, yet it enforces absolute consistency across many enums in a project, and it incurs no runtime cost.
Do it using Python's excellent "mako" package, or in Lua if you're into lightweight, or the CPP if you're against dependencies, or CMake's own facilities for generating code. Lots of ways, but it all comes down to the same thing: you need to generate the code yourself--C++ won't do this for you (unfortunately).
In my opinion, the most maintainable approach is to write a helper function:
const char* get_name(OS_type os) {
switch (os) {
case Linux: return "Linux";
case Apple: return "Apple";
case Windows: return "Windows";
}
}
It is a good idea not to implement the "default" case, since doing so will ensure that you get a compiler warning if you forget to implement a case (with the right compiler and compiler settings).
I like a hack using the C preprocessor, which I first saw here:
http://blogs.msdn.com/b/vcblog/archive/2008/04/30/enums-macros-unicode-and-token-pasting.aspx .
It uses the token-pasting operator # .
// This code defines the enumerated values:
#define MY_ENUM(x) x,
enum Fruit_Type {
MY_ENUM(Banana)
MY_ENUM(Apple)
MY_ENUM(Orange)
};
#undef MY_ENUM
// and this code defines an array of string literals for them:
#define MY_ENUM(x) #x,
const char* const fruit_name[] = {
MY_ENUM(Banana)
MY_ENUM(Apple)
MY_ENUM(Orange)
};
#undef MY_ENUM
// Finally, here is some client code:
std::cout << fruit_name[Banana] << " is enum #" << Banana << "\n";
// In practice, those three "MY_ENUM" macro calls will be inside an #include file.
Frankly, it's ugly and. but you end up typing your enums exactly ONCE in an include file, which is more maintainable.
BTW, on that MSDN blog link (see above) a user made a comment with a trick that makes the whole thing much prettier, and avoids #includes:
#define Fruits(FOO) \
FOO(Apple) \
FOO(Banana) \
FOO(Orange)
#define DO_DESCRIPTION(e) #e,
#define DO_ENUM(e) e,
char* FruitDescription[] = {
Fruits(DO_DESCRIPTION)
};
enum Fruit_Type {
Fruits(DO_ENUM)
};
// Client code:
std::cout << FruitDescription[Banana] << " is enum #" << Banana << "\n";
(I just noticed that 0x17de's answer also uses the token-pasting operator)
Here is a simple example using namespaces and structs.
A class is created for each enum item. In this example i chose int as the type for the id.
#include <iostream>
using namespace std;
#define ENUMITEM(Id, Name) \
struct Name {\
static constexpr const int id = Id;\
static constexpr const char* name = #Name;\
};
namespace Food {
ENUMITEM(1, Banana)
ENUMITEM(2, Apple)
ENUMITEM(3, Orange)
}
int main() {
cout << Food::Orange::id << ":" << Food::Orange::name << endl;
return 0;
}
Output:
3:Orange
== Update ==
Using:
#define STARTENUM() constexpr const int enumStart = __LINE__;
#define ENUMITEM(Name) \
struct Name {\
static constexpr const int id = __LINE__ - enumStart - 1;\
static constexpr const char* name = #Name;\
};
and using it once before the first usage of ENUMITEM the ids would not be needed anymore.
namespace Food {
STARTENUM()
ENUMITEM(Banana)
ENUMITEM(Apple)
ENUMITEM(Orange)
}
The variable enumStart is only accessible through the namespace - so still multiple enums can be used.
You can use macro to solve this problem:
#define MAKE_ENUM(name, ...) enum class name { __VA_ARGS__}; \
static std::vector<std::string> Enum_##name##_init(){\
const std::string content = #__VA_ARGS__; \
std::vector<std::string> str;\
size_t len = content.length();\
std::ostringstream temp;\
for(size_t i = 0; i < len; i ++) {\
if(isspace(content[i])) continue;\
else if(content[i] == ',') {\
str.push_back(temp.str());\
temp.str(std::string());}\
else temp<< content[i];}\
str.push_back(temp.str());\
return str;}\
static const std::vector<std::string> Enum_##name##_str_vec = Enum_##name##_init();\
static std::string to_string(name val){\
return Enum_##name##_str_vec[static_cast<size_t>(val)];\
}\
static std::string print_all_##name##_enum(){\
int count = 0;\
std::string ans;\
for(auto& item:Enum_##name##_str_vec)\
ans += std::to_string(count++) + ':' + item + '\n';\
return ans;\
}
As the static variable can only be initialized once, so the Enum_##name##_str_vec will use the Enum_##name##_init() function to initialize itself at first.
The sample code is as below:
MAKE_ENUM(Analysis_Time_Type,
UNKNOWN,
REAL_TIME,
CLOSSING_TIME
);
Then you can use below sentence to print an enum value:
to_string(Analysis_Time_Type::UNKNOWN)
And use below sentence to print all enum as string:
print_all_Analysis_Time_Type_enum()
As mentioned, there is no standard way to do this. But with a little preprocessor magic (similar to AlejoHausner's second contribution) and some template magic, it can be fairly elegant.
Include this code once:
#include <string>
#include <algorithm>
#define ENUM_VALS( name ) name,
#define ENUM_STRINGS( name ) # name,
/** Template function to return the enum value for a given string
* Note: assumes enums are all upper or all lowercase,
* that they are contiguous/default-ordered,
* and that the first value is the default
* #tparam ENUM type of the enum to retrieve
* #tparam ENUMSIZE number of elements in the enum (implicit; need not be passed in)
* #param valStr string version of enum value to convert; may be any capitalization (capitalization may be modified)
* #param enumStrs array of strings corresponding to enum values, assumed to all be in lower/upper case depending upon
* enumsUpper
* #param enumsUpper true if the enum values are in all uppercase, false if in all lowercase (mixed case not supported)
* #return enum value corresponding to valStr, or the first enum value if not found
*/
template <typename ENUM, size_t ENUMSIZE>
static inline ENUM fromString(std::string &valStr, const char *(&enumStrs)[ENUMSIZE], bool enumsUpper = true) {
ENUM e = static_cast< ENUM >(0); // by default, first value
// convert valStr to lower/upper-case
std::transform(valStr.begin(), valStr.end(), valStr.begin(), enumsUpper ? ::toupper : ::tolower);
for (size_t i = 0; i< ENUMSIZE; i++) {
if (valStr == std::string(enumStrs[i])) {
e = static_cast< ENUM >(i);
break;
}
}
return e;
}
Then define each enum like so:
//! Define ColorType enum with array for converting to/from strings
#define ColorTypes(ENUM) \
ENUM(BLACK) \
ENUM(RED) \
ENUM(GREEN) \
ENUM(BLUE)
enum ColorType {
ColorTypes(ENUM_VALS)
};
static const char* colorTypeNames[] = {
ColorTypes(ENUM_STRINGS)
};
You only have to enumerate the enum values once and the code to define it is fairly compact and intuitive.
Values will necessarily be numbered in the default way (ie, 0,1,2,...). The code of fromString() assumes that enum values are in either all uppercase or all lowercase (for converting from strings) that the default value is first, but you can of course change how these things are handled.
Here is how you get the string value:
ColorType c = ColorType::BLUE;
std::cout << colorTypeNames[c]; // BLUE
Here is how you set the enum from a string value:
ColorType c2 = fromString<ColorType>("Green", colorTypeNames); // == ColorType::GREEN
I'm trying to code a simple function to sort the content of a directory. The Thing is, it comes out in alphabetical order, regardless of uppercase or lowercase. I'd like to sort this content in ASCII order.
example: I got 4 files, named Art, boat, Cat and donkey. My actual code sort them in this order, while i'd like to get Art, Cat, boat and donkey.
void list_dir(char *str){
DIR *rep = NULL;
struct dirent* read_file = NULL;
rep = opendir(str);
if (!rep)
{
ft_putstr("ft_ls: ");
perror(str);
ft_putchar('\n');
}
while((read_file = readdir(rep)) != NULL)
{
if (read_file->d_name[0] != '.')
{
ft_putstr(read_file->d_name);
ft_putchar('\n');
}
}
}
readdir(3) does not normally sort at all, it lists the entries in directory order. If the list is sorted, either the files were created sorted, or the OS sorts them.
In order to sort the output yourself, put the list of names into an array then sort it e.g. with qsort(3) and strcmp(3).
Alternatively, just pipe the output through sort(1). Do make sure that the LC_COLLATION environment variable is set proper. For example, run ./yourprogram | (unset LC_ALL; LC_CTYPE=en_US.UTF-8 LC_COLLATE=C sort).
By calling scandir with user defined filter & comparator is a simple solution imho. Here is the code:
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
static int my_dir_filter(const struct dirent* dir);
static int my_dir_comparator(const struct dirent**, const struct dirent**);
int main(int argc, char* const* argv) {
struct dirent** ent_list_ = NULL;
int r = scandir(".", &ent_list_, my_dir_filter, my_dir_comparator);
for (int i = 0; i < r; ++i)
printf("No. %-3d [%s]\n", i + 1, ent_list_[i]->d_name);
for (int i = 0; i < r; ++i)
free(ent_list_[i]);
free(ent_list_);
return r < 0 ? 1 : 0;
}
int my_dir_filter(const struct dirent* dir) {
return (dir->d_type == DT_REG) ? 1 : 0;
}
int my_dir_comparator(const struct dirent** lhs, const struct dirent** rhs) {
return strcasecmp((*lhs)->d_name, (*rhs)->d_name);
}
And test result:
$ ls|LANG=C sort ## in ASCII order
Art
Cat
boat
donkey
$ ../a.out ## in my_dir_comparator order
No. 1 [Art]
No. 2 [boat]
No. 3 [Cat]
No. 4 [donkey]
I found a weird issue while writing an IOCTL for a character device driver for custom hardware connected to an old PowerPC. Here is an abstraction of my code:
u32 mydev_data;
...
static long mydev_ioctl(struct file * file, unsigned int cmd, unsigned long arg)
{
void __user *user_arg = (void __user *)arg;
long result;
switch(cmd) {
case MYDEV_GETDATA:
result = put_user(mydev_data, user_arg);
break;
...
}
return result;
}
Now, this returns garbage. However, when I replace the line
result = put_user(mydev_data, user_arg);
with
result = put_user(mydev_data, (unsigned long __user *) user_arg);
the problem goes away.
What is going on here? Since user_arg is marked as __user *, the only difference is void vs. unsigned long. But I wouldn't think the pointer type would matter here. Obviously I'm mistaken but can someone explain why?
If you look at the definition of the put_user macro, you'll see that it copies data based on size, doing a sizeof(*ptr) to determine how many bytes to copy. sizeof(void) == 1, but sizeof(unsigned long) is larger.
#define __put_user_check(x, ptr, size) \
({ \
long __pu_err = -EFAULT; \
__typeof__(*(ptr)) __user *__pu_addr = (ptr); \
might_sleep(); \
if (access_ok(VERIFY_WRITE, __pu_addr, size)) \
__put_user_size((x), __pu_addr, (size), __pu_err); \
__pu_err; \
})
#define put_user(x, ptr) \
__put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
I am stuck trying to figure out how to initialize a pointer to a 3d array inside a 2d structure array. I had it working fine when I could declare the structure like this:
#define ROUSSEAU 300
#define OSSO 500
#define MOJO 9000
typedef struct x_primitive
{
short avg[ROUSSEAU][OSSO][MOJO];
} xprimitive;
But unfortunately the structure is too large to declare as a global. So I have to calloc the memory (192GB memory available on the system: win 7 64 bit);
typedef struct x_primitive
{
short ***avg;
} xprimitive;
xprimitive **xPmtv, *_xPmtv;
void xallocatePmtvMemory(void)
{
int structureCount = 10;
unsigned __int64 pmtvStructureSize = ROUSSEAU * OSSO * MOJO * sizeof(short);
unsigned __int64 memoryBlockSize = structureCount * pmtvStructureSize;
_xPmtv = (xprimitive *) calloc(structureCount, pmtvStructureSize);
xPmtv = (xprimitive **) calloc(structureCount, sizeof(xprimitive *));
for ( int i = 0; i < structureCount; ++i)
{
unsigned __int64 index = i * pmtvStructureSize;
xPmtv[i] = &_xPmtv[ index ];
// **************** here is the problem ******
xPmtv[i]->avg[ROUSSEAU][OSSO][MOJO] = &_xPmtv[ index + (ROUSSEAU + OSSO + MOJO) ];
}
}
I am trying to assign the "avg" variable to a chunk of memory, and utterly failing.
Pointers and arrays aren't interchangeable in the way you seem to be wanting them to be. I think you can probably be doing something much simpler. Make avg into a pointer:
typedef struct x_primitive
{
short (*avg)[ROUSSEAU][OSSO][MOJO];
} xprimitive;
And then allocate the space for the array at runtime:
xprimitive xPmtv;
xPmtv.avg = calloc(1, ROUSSEAU * OSSO * MOJO * sizeof(short));
Using it is a bit funny looking, though:
(*xPmtv.avg)[1][2][3]
If you have multiple structures, just throw the initialization into a loop. Maybe a better idea is to use a flexible array member to keep the usage syntax looking a bit more normal - it will cost you a dummy entry in the structure - flexible array members aren't allowed to play around on their own. Then again, why do you have a structure with only one field anyway?
typedef struct x_primitive
{
int dummyEntry;
short avg[][OSSO][MOJO];
} xprimitive;
To allocate one, you'd use:
xprimitive *xPmtv = calloc(1, sizeof(xprimitive) + ROUSSEAU * OSSO * MOJO * sizeof(short));
And access the array something like:
xPmtv->avg[1][2][3]