On an old C compiler that only passes structures by pointers I fortunately have a structure that is 4 bytes long. Which is the size of a long (not int) on this system.
The code I'm porting (awk V7 or 32V) has many functions that return this structure by value.
I'm trying to find a way to cast the structure a long and visa versa and while I have managed this for variables the cast fails with the return value of a function. I would be forced to use a temp long and then cast that. This means more than a simple define to solve my issue and means avoidable recoding.
Is there a way I can do this with just defines?
I have some sample code here that I'm playing around with. Sample code from different system has long of 64 bits so using int32 as long.
#include <stdio.h>
typedef struct _obj { char a; char b; short c; } Obj;
#define OBJ2INT *(int32*)&
#define INT2OBJ *(Obj*)&
/* Obj */ int32 newObj(a, b, c) /* was returing Obj */
char a; char b; int c;
{
Obj newobj;
newobj.a = a;
newobj.b = b;
newobj.c = c;
return OBJ2INT newobj;
}
int main(argc, argv)
int argc; char *argv[];
{
Obj a, b;
int32 t;
t = newObj('a', '1', 1));
a = INT2OBJ t; /* this works but require recoding with a temp variable */
b = INT2OBJ newObj('b', '2', 2); /* this is not allowed. even though the value is on the stack there is no address for return value */
printf("a = %c %c %d\n", a.a, a.b, a.c);
printf("b = %c %c %d\n", b.a, b.b, b.c);
}
I was missing the whole point. K & R C cannot assign or pass structures/unions.
So converting the int32 to a structure and assigning to another structure is never going to work. Can't assign structures! So the structure must always be converted to an int32. because int32 can be assigned and passed. The solution was to change this :
b = INT2OBJ newObj('b', '2', 2); /* this is not allowed. even though the value is on the stack there is no address for return value */
to this :
OBJ2INT b = newObj('b', '2', 2);
INT2OBJ is never required. What was required was moving the INT2OBJ from the right to a OBJ2INT on the left of the assignment!
Related
For the problem, consider below two structures.
struct type1_A
{
int a;
char b;
char rsvd[10];
char c;
int d;
}
struct type1_B
{
int d;
char rsvd[12];
char c;
char b;
int a;
}
I need to read fields a, b, c & d from the structs. I will have a buffer address and that buffer will have one of the struct. A flag can tell what kind of struct it is.
if (flag == TYPE1_A) {
a = ((struct type1_A*) (buffer))->a;
}
else if (flag == TYPE1_B) {
a = ((struct type1_B*) (buffer))->a;
}
But when there are many such reads, I dont want to keep on having if-else like above. Is there some way (hack) that this can be done without if-else. The field names will be same but at a different offset.
You can do the pointer arithmetic manually and store the offsets in a table indexed by type. That'd replace the if-else ladder with a table lookup:
if(flag_is_within_type_range(flag))
a=*(int*) ((char*)buffer+offset_table_indexed_by_type[flag]);
Essentially the resulting assembly needs to do a dynamic_type_number-to-an_offset lookup and you having the same overloaded name (i.e., the a member) for those different offsets doesn't help anything. There's hardly any good way to exploit it.
I would use macro like this:
#define TYPE_1 1
#define GETMEMBER(type, buff, field) ((type) == TYPE_1 ? ((struct type1_A *)(buff)) -> field : ((struct type1_B *)(buff)) -> field)
void foo(void *buff)
{
int type1a = GETMEMBER(TYPE_1, buff, a);
int type2a = GETMEMBER(0, buff, a);
printf("Type1: %d, type2:%d\n", type1a, type2a);
}
If you use a constant expression as type the compiler will optimize out the comparison leaving only the assignment:
https://godbolt.org/z/a73YsorMe
I defined a struct like below (in C).
struct Temp {
int C;
int F;};
and it is always true that
(C × 9/5) + 32 = F
Since I have several variables in type of "struct Temp", it would not be easy to define a subroutine to make the calculation and call it per each variable.
It would be a solution if the following code was possible.
struct Temp {
int C;
int F = (C × 9/5) + 32;};
How can I apply this relationship Automatically when a new variable in type of "struct Temp" is defined.
Thank you in advance.
You can do it by initializing the array, but for that, you have to first assign a value to C. E.g.
struct abc{
int a;
int b;
};
int z = 97;
struct abc pqr = {z, z+9/4};
Now the value of variable a in pqr is 4 and b is 6
You can do it by defining a macro as well. E.g.
#define MYSTRUCT(NAME, VAL) struct abc NAME = {VAL, VAL+9/4};
Then create a new struct as :
MYSTRUCT(pqr, 97);
printf("%d, %d", pqr.a, pqr.b);
Structs are data types so you can't initialize a data type with a new value just like you can't manipulate the inner properties of an "int" data type. But we can define "ints" afterwards and so we can also do the same with "structs". Like the others said, you have to write a function to do this
the below is an example of using a function macro to do this painlessly. Note however that your types for C and F are both integer so they'll get truncated when trying to convert. Better to declare them as float or double.
#include <stdio.h>
#define initF(x) (x.F = (x.C * 9/5) + 32)
struct Temp {
int C;
int F;
};
int main(int argc, char** argv) {
struct Temp t;
t.C = 32;
initF(t);
printf("Temp F = %d\n", t.F);
}
What you want is called a Property which is not supported in C. You can do this in two ways, the first way is to define a function to do the calculation each time, like code below. This method is non-cached.
int GetF(struct Temp temp)
{
return temp.C * 1.8 + 32;
}
The other way (cached) is to set the C value with a function in a way that calculates and saves the F value and you can use it later quickly.
int SetC(struct Temp temp, int c)
{
temp.C = c;
temp.F = c * 1.8 + 32;
}
From what I understand, mpz_t are nothing but a single-item array.
According to gmp.h:
{
short int _mp_alloc; /* Number of *limbs* allocated and pointed
to by the D field. */
short int _mp_size; /* abs(SIZE) is the number of limbs
the last field points to. If SIZE
is negative this is a negative
number. */
mp_limb_t *_mp_d; /* Pointer to the limbs. */
} __mpz_struct;
typedef __mpz_struct mpz_t[1];
That means that, given the way C handles arrays, mpz_t is effectively a pointer itself (to the first element of the one-element array).
Now, let's say I create a new mpz_t, within a function, "box" the pointer in an unsigned long long and return, then... chaos. (Since, I guess, the pointer is no longer valid?)
The only way I could in theory make it work is by moving the mpz_t declaration outside the function body (basically, make it a global)
Any other - more sensible - ideas?
Minimal example:
typedef uint64_t Value;
#define addWillOverflow(x,y,z) __builtin_sadd_overflow(x,y,z)
#define BITFIELD 56
#define MASK(x) ((Value)(x) << BITFIELD)
#define UNMASK 0x00FFFFFFFFFFFFFF
#define toI(v) ( (Value)(v & 0xFFFFFFFFu) | MASK(IV) )
#define toG(v) ( (Value)(v) | MASK(GV) )
#define GG(v) ( (v & UNMASK) )
Value addNumbers(int a, int b) {
Int32 res;
if (addWillOverflow(a,b,&res)) {
printf("overflow\n");
mpz_t ret;
mpz_init_set_si(ret,a);
mpz_add_ui(ret,ret,b);
return toG(ret);
}
else {
printf("normal addition\n");
return toI(res);
}
}
int main(int argc, char** argv) {
printf("3 + 5 = ");
printLnValue(addNumbers(1,2));
printf("2b + 2b = ");
Value a = addNumbers(2000000000,2000000000);
printLnValue(a);
printf("pointer: %p\n",GG(a));
Value b = addNumbers(2100000000,2011111111);
printLnValue(b);
printf("pointer: %p\n",GG(b));
}
Output:
3 + 5 = normal addition
3
2b + 2b = overflow
4000000000
pointer: 0x7ffee5b95630
overflow
4111111111
pointer: 0x7ffee5b95630
As you can see, the returned pointer is... the same. Although I would expect a different one.
UPDATE no 2
I'm currently thinking of doing it like this: (I'll see how it goes and then post it as a solution myself)
mpz_t* ret = malloc(sizeof(mpz_t));
mpz_init_set_si(*ret,a);
mpz_add_ui(*ret,*ret,b);
return toG(ret);
I came across this simple program somewhere
#include<stdio.h>
#include<stdlib.h>
char buffer[2];
struct globals {
int value;
char type;
long tup;
};
#define G (*(struct globals*)&buffer)
int main ()
{
G.value = 233;
G.type = '*';
G.tup = 1234123;
printf("\nValue = %d\n",G.value);
printf("\ntype = %c\n",G.type);
printf("\ntup = %ld\n",G.tup);
return 0;
}
It's compiling (using gcc) and executing well and I get the following output:
Value = 233
type = *
tup = 1234123
I am not sure how the #define G statement is working.
How G is defined as an object of type struct globals ?
First, this code has undefined behavior, because it re-interprets a two-byte array as a much larger struct. Therefore, it is writing past the end of the allocated space. You could make your program valid by using the size of the struct to declare the buffer array, like this:
struct globals {
int value;
char type;
long tup;
};
char buffer[sizeof(struct globals)];
The #define is working in its usual way - by providing textual substitutions of the token G, as if you ran a search-and-replace in your favorite text editor. Preprocessor, the first stage of the C compiler, finds every entry G, and replaces it with (*(struct globals*)&buffer).
Once the preprocessor is done, the compiler sees this code:
int main ()
{
(*(struct globals*)&buffer).value = 233;
(*(struct globals*)&buffer).type = '*';
(*(struct globals*)&buffer).tup = 1234123;
printf("\nValue = %d\n",(*(struct globals*)&buffer).value);
printf("\ntype = %c\n",(*(struct globals*)&buffer).type);
printf("\ntup = %ld\n",(*(struct globals*)&buffer).tup);
return 0;
}
The macro simply casts the address of the 2-character buffer buf into a pointer to the appropriate structure type, then de-references that to produce a struct-typed lvalue. That's why the dot (.) struct-access operator works on G.
No idea why anyone would do this. I would think it much cleaner to convert to/from the character array when that is needed (which is "never" in the example code, but presumably it's used somewhere in the larger original code base), or use a union to get rid of the macro.
union {
struct {
int value;
/* ... */
} s;
char c[2];
} G;
G.s.value = 233; /* and so on */
is both cleaner and clearer. Note that the char array is too small.
Is it possible to recast the a variable permanently, or have a wrapper function such that the variable would behave like another type?
I would want to achieve something I posted in the other question:
Typecasting variable with another typedef
Update: Added GCC as compiler. May have a extension that would help?
Yes, you can cast a variable from one type to another:
int x = 5;
double y = (double) x; // <== this is what a cast looks like
However, you cannot modify the type of the identifier 'x' in-place, if that is what you are asking. Close to that, though, you can introduce another scope with that identifier redeclared with some new type:
int x = 5;
double y = (double) x;
{
double x = y; // NOTE: this isn't the same as the 'x' identifier above
// ...
}
// NOTE: the symbol 'x' reverts to its previous meaning here.
Another thing you could do, though it is really a horrible, horrible idea is:
int x = 5;
double new_version_of_x = (double) x; // Let's make 'x' mean this
#define x new_version_of_x
// The line above is pure evil, don't actually do it, but yes,
// all lines after this one will think 'x' has type double instead
// of int, because the text 'x' has been rewritten to refer to
// 'new_version_of_x'. This will likely lead to all sorts of havoc
You accomplish that by casting then assigning.
int f(void * p) {
int * i;
i = (int *)p;
//lots of code here with the i pointer, and every line
//really thinks that it is an int pointer and will treat it as such
}
EDIT From the other question you linked:
typedef struct {
unsigned char a;
unsigned char b;
unsigned char c;
} type_a;
typedef struct {
unsigned char e;
unsigned char f[2];
} type_b;
//initialize type a
type_a sample;
sample.a = 1;
sample.b = 2;
sample.c = 3;
Now sample is initialized, but you want to access it differently, you want to pretend that in fact that variable has another type, so you declare a pointer to the type you want to "disguise" sample as:
type_b * not_really_b;
not_really_b = (type_b*)&sample;
See, that is the whole magic.
not_really_b->e is equal 1
not_really_b->f[0] is equal 2
not_really_b->f[1] is equal 3
Does this answer your question?
The other answers are better (declare a variable of the type you want, and do an assignment). If that's not what you're asking for, you could use a macro:
long i;
#define i_as_int ((int)i)
printf( "i = %ld\n", i);
printf( "i = %d\n", i_as_int);
But wouldn't it be clearer to just say (int) i if that's what you mean?
As long as you realize in C pointers are nothing but addresses of memory
locations of certain types, you should have your answer. For example the
following program will print the name of the file
int main(int argc, char *argv[]) {
int *i;
i = (int *) argv[0];
printf("%s\n", argv[0]);
printf("%s\n", ((char *) i));
}