What is this Macro/Pointer declaration doing? - c

anyone familiar with this macro definition:
#define CrashData (*((CRASH_DATA *)CRASHDATA_ADDRESS))
where
CRASH_DATA is a typedef struct
CRASHDATA_ADDRESS is 0xF3F80UL
I suspect that we are creating a struct variable called CrashData that is placed from the addrees and forward right?
Thank you for your help, Pointer declaration is kind of confusing.

I suspect that we are creating a struct variable called CrashData that is placed from the addrees and forward right?
No, not exactly.
In the first place, there is no variable anywhere in sight. You spoke correctly when you called the code a macro definition; therefore the code defines a macro named CrashData, which is not at all the same thing as a variable.
So let's look at the macro's replacement text:
(*((CRASH_DATA *)CRASHDATA_ADDRESS))
Starting from the inside, you claimed that CRASHDATA_ADDRESS is 0xF3F80UL, which I interpret to mean that it is actually a macro, with that unsigned long constant as its replacement text.
(CRASH_DATA *) can only be a cast operator, so it is unsurprising to hear that CRASH_DATA is a typedefed type alias, or perhaps a macro expanding to such. The result of the cast is a pointer to CRASH_DATA. It might in particular point to a block of memory at the address specified by CRASHDATA_ADDRESS, but the standard only says
the result is implementation-defined, might not be correctly aligned,
might not point to an entity of the referenced type, and might be a
trap representation.
the result of the cast is enclosed in parentheses and the dereferencing operator (unary *) is applied to it. The result of dereferencing a pointer is an lvalue designating the object to which the pointer points.
the dereferenced result is enclosed in parentheses, which serve their ordinary grouping role. This is useful so that operator precedence does not cause surprising effects where the macro is used.
Overall, then, the intent of the macro seems to be to represent an expression that presents a block of memory starting at CRASHDATA_ADDRESS as if it were an object of type CRASH_DATA. Since CRASH_DATA is a structure type, you would access its members via the . operator:
if (CrashData.member1 == y) {
CrashData.member2 = x;
}
Although you might write similar code if CrashData were a variable, it is not a variable, and there are ways in which it would behave differently than a variable.

First, ((CRASH_DATA *)(CRASHDATA_ADDRESS)) is a typecast, telling the compiler to treat the address defined in CRASHDATA_ADDRESS as if it were a pointer to an item of type CRASH_DATA.
Next the star (*) operator is dereferencing the pointer. Since it is a pointer to a struct, once referenced you can access any of the struct's members via the dot (.) operator.
You should be able to access the data like this:
CrashData.some_struct_member
Anyways, what is important is to understand you are not 'creating' a new struct variable, you are only telling the compiler to treat the data stored at memory address 0xF3F80UL as a variable of type CRASH_DATA.

Related

Is there a standard way to prohibit reading (via assignment) of a variable?

It is known and useful features that:
const type qualifier prohibits writing (modification) of a variable
register storage-class specifier prohibits taking address of a variable
However, is there a standard way to prohibit reading (via assignment) of a variable?
For example, for such variable only writing and/or taking address is permitted.
Reason of the question: need to conditionally prohibit reading (via assignment) of some variable. Does the language provide any way to do it? If no, then why?
UPD. Readers may be interested as well: C: check at compile time or at run time that variable has static storage-class specifier.
No, not as far as I know.
I don't know why, one reason might be that it's something that is only fantastically rarely useful. You (in my opinion) don't actually explain why you want this, which further emphasizes that's a rather convoluted/weird thing to want.
It is known and useful features that:
const type qualifier prohibits writing (modification) of a variable
Yes.
register storage-class specifier prohibits taking address of a variable
True, but that's not the primary purpose of the register storage class.
However, is there a standard way to prohibit reading (via assignment) of a variable?
I take it that you want to forbid ...
_Write_only int x = 1;
int y = x;
... but no, there is no way to do that. If you have an lvalue expression designating an existing object, such as is required to set the value of that object, then that expression can be used to read the current value of the object, too.
Reason of the question: need to conditionally prohibit reading (via
assignment) of some variable.
That's not much of a reason. You seem to just be saying, "I need it because I need it."
Does the language provide any way to do
it? If no, then why?
If by "why" you are asking for us to support our answers, then I refer you to paragraph 6.3.2.1/2 of the standard, where you will find this:
Except when it is the operand of the sizeof operator, the _Alignof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue)
That does not leave any room for the kind of semantics you asked about.
If you mean something else by the "why" question then we can only speculate, but I don't personally find the situation in any way surprising. In particular, I don't find the existence of const and register as suggesting that there should be a qualifier with the effect you describe.
If you want an object that can only be written, not read, by a piece of code X then you can declare it outside the scope of X and with linkage that does not afford access from X, and provide a function that X can call to modify the object's value. For example, the object might be declared static at file scope in a different translation unit, with an external writer function declared in that unit:
static int protected;
void set_protected(int value) {
protected = value;
}
Code in other translation units could then use the function to set the variable's value, but could not access the object directly to read its value.
Note well that that all goes out the window if you allow X to get the address of the protected object, as that can be dereferenced to gain access.
You need to hide your variables from the program code
#define CREATE_PROTECTED(var, type, val) type set_##var(type v){static type var = val; return var;}
#define GET(var) set_##var(val)
CREATE_PROTECTED(myvar, size_t, 500);
size_t foo(void)
{
return GET(myvar)
}

Will a cast ever fail in C?

Specifically, my question is, given this macro:
#define FAKE_VAL(type) ((type)0)
...is there any value of type (including structures, function pointers, etc.) where FAKE_VAL(type) will cause a compile-time error?
I'm asking because I have a macro that take a function pointer as an argument, and needs to find the size of its return value. I know the types and number of arguments the function pointer takes, so I'm planning to write something like:
sizeof(fptr(FAKE_VAL(arg_type_1), FAKE_VAL(arg_type_2)))
arg_type_1 and 2 could be literally anything.
Of course there is.
struct fred (i.e. not a pointer) - how do you convert 0 (scalar type) to a struct (non scalar type)?
Any literal value FAKE_VAL("hi") gives (("hi")0) - what does that mean?
You can't cast an int to an array type, so
FAKE_VAL(int[5]);
will fail. Try it!
To give it a more systematic answer. In C cast are only allowed for arithmetic and pointer types. So anything that is a struct, union or array type would lead to a compile time error.
typecast is used to inform the compiler that the programmer has already considered the side effects of using the variable in a different way than it was declared as. This causes the compiler to switch off its checks. So with typecasts you wont get warnings/errors.
Yeah. it does type conversion of any type to the typecasted one. My bad.
But this can cause segmentation faults/errors when the program is actually run.

Is it bad style or incorrect to access va_arg macro by reference?

I got a line of code where this is pretty useful:
void *test;
/*...*/
test = &va_arg(arg_list, int);
I was just trying this, as i thought, this is a macro and not a function, so it might work.
I didn't really was expecting it to work, but it does exactly what I want.
But now I'm not sure about the lifetime of the address and other risks which may occur of this style.
Could anyone tell me why using the reference of the va_arg 's value this way is safe / unsafe?
C99 standard, section 7.15.1.1 (emphasis mine):
The va_arg macro expands to an expression that has the specified
type and the value of the next argument in the call.
This implies that va_arg does not necessarily evaluate to an lvalue; taking the address of whatever it expands to is unsafe: an lvalue can be used as an expression, but not every expression is an lvalue. Consider the expression 3+4. It doesn't make sense to take the address of that.
So, no, you shouldn't do it.
UPDATE: As pointed out in the comments, taking the address of an expression that is not an lvalue will cause a compilation error. So, if the code compiles, then it should be safe. The unportability issues arise from the fact that it may not compile in other platforms where va_arg() expands to something that is not an lvalue.

How are these two pointers different from each other?

I'm new to C language and pointers in general. So my understanding of these two things is basic.
I've been trying to create a structure that hold pointers to functions, nothing fancy. While doing so; I noticed that this statement:
int *func()
doesn't work. while this one actually works:
int (*func)()
What's the difference between them? Is it because the first statement is only a pointer to integer. while the other pointer, somehow, points to a function? How so?
int *func(void)
Defines a function named func that has no parameters and returns a pointer to an integer
int(*func)(void)
Defines a pointer to a function that has no parameters and returns an integer
The reason for this difference is operator precedence. Parerenteses have a higher precendence than *. Therefore in the first expression int *func() the function-parenthesis have the highest precedence and are considered first, so associate with the symbol func so the compiler knows that func is a symbol for a function. Therefore the rest is the return.
In the second instance int(*func)() there is an extra set of parenthesis. Inside the first parenthesis we see *func. As the parenthesis is the highest precendence (left-to-right) the compiler must interpret the contents of this set... *func is a pointer. OK a pointer to what? Look right and we see () so it is a pointer to a function. Then look left to see the return type.
Hope this makes sense :) Also try How to interpret complex C/C++ declarations on CodeProject.com. It talks about something called the "Right-left rule", which is "...a simple rule that allows you to interpret any declaration...". It's a little more than half way down the page...
Also try cdecl: C gibberish ↔ English. It's quite a nice implementation of the cdecl utility.

C structure assignment of same address valid?

If I have something like this in my code:
void f(struct foo *x, struct foo *y)
{
*x = *y; // structure copy (memcpy?)
}
If x and y point to the same address, what happens?
Is this valid code, and what if the compiler converts the assignment into a memcpy call with potentially-invalid operands (they aren't allowed to overlap)?
[Yes, I know I can use "restrict" in this case, but the actual code we found which made us consider this is automatically-generated by bison so we were wondering if it should always be valid and whether the compiler should use memmove or something else which allows overlap..]
Structure assignment is perfectly legal. Therefore the compiler will generate the correct code (compiler bugs notwithstanding).
This looks perfectly valid to me. Yes, this will result in a sort of memcpy.
Two pointers to struct like that should only either be the same or not overlap at all. So you could do a check if the pointers are equal, before.
(You can certainly trick your code to have a real overlap, but there'd have to be a really special reason to do that.)
This is valid code. The compiler can not assume x != y, so it must use safe memmove.
[Yes, answering my own question as I saw this after looking in the standard a bit and searching harder for related questions on here]
Actually, this is answered by part of the answer to Are there any platforms where using structure copy on an fd_set (for select() or pselect()) causes problems? (in this answer), which I will paste here:
One of the following shall hold:
...
the left operand has a qualified or unqualified version of a structure or union type compatible with the type of the right;
...
If the value being stored in an object is read from another object that overlaps in any way the storage of the first object, then the overlap shall be exact and the two objects shall have qualified or unqualified versions of a compatible type; otherwise, the behavior is undefined.
Hence as long as the pointers are the same (i.e. total overlap) then this is fine. Still seems odd that the compiler inserts a call to memcpy sometimes for this despite the spec of memcpy saying that overlap is not allowed. Perhaps the compiler knows more about the particular implementation of memcpy than the documentation eludes to..

Resources