type conversion in embedded C [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
x is a variable, and its type is int, and I need to convert the type of x from int to long or float. But a simple typecasting (long) x; is not working. Only the following line is working: ((long) &(x)); (I copy it from another parts of the code.)
int x;
(long) x; --> it is not working
*((long*) &(x)); --> it is working
I know what (long) x; means, but...
Could you please describe in detail what *((long*) &(x)); mean exactly? How does it work?
Why it is working and why the simple version not?
It is an embedded code, and I am new in embedded system developing.
main(){
float k;
int i=1, j=2;
k = GetSum(i,j);
}
float GetSum(int x, int y){
float z;
z = *((float*) &(x)) + *((float*) &(y)); /*it is working --> compile with this line*/
z = (float)x + (float)y; /*it is not working --> not compile with this line*/
return z;
}

The type of variables is fixed when they are declared. Type conversion doesn't affect that.
So
int x;
(long)x;
doesn't change the type of x. It converts the value of x to a long. So, if y is of type long.
y = (long)x;
converts the value of x to a value of type long, and stores the result of that conversion in y.
To understand what *((long*) &(x)) does ....
Firstly &(x) computes the address of x (the () are unnecessary). That address is of type int *, since x is of type int.
The (long *) then converts that pointer to be a pointer to long (i.e. a long *)
The * around ((long*) &(x)) then dereferences that long *. This effectively tells the compiler to act as if that memory location which contains an int actually contains a long.
If you then use that, for example;
y = *((long*) &(x)); /* store the value retrieved into y
or
*((long*) &(x)) = 42L; /* treat the memory occupied by x AS IF it is a long,
and write 42L to that memory */
then the result in both cases is formally undefined behaviour. The C standard does not describe any constraints on what happens.
The first treats the memory occupied by x as if it contains a long. The problem is that a long may occupy more memory than an int. A typical symptom in such a case is a garbage value stored in y.
The second writes the value 42L to the memory occupied by x, treating that memory AS IF it contains a long. If long is larger than an int, two common results are program crashes (the program modifying memory past x and the operating system therefore terminating the program) or data poisoning (an unrelated variable in your program, that happens to be located in memory just after x, has its value changed).
If it "seems to work" (however you define "work") with your testing then you are getting lucky - for example, long and int happen to be the same size and same representation WITH YOUR PARTICULAR COMPILER. However, the behaviour is still undefined, anything can actually happen - such as code working with one compiler, but crashing when built with another.

Compile with warnings enabled. The reason for failure must be that you're using an obsolete compiler that supports implicit function declarations that were forbidden by C99, i.e. 18 years ago , and C thinks that it is int GetSum() and since the function actually returns float, your code just has undefined behaviour.
Your function would "work" with the latter, i.e.
z = (float)x + (float)y;
if you changed the return type to int.
Please just stop writing code that uses conventions that belong to Dark Middle Ages. If you use gcc, compile with -std=c99 or -std=c11 or similar, and with -pedantic-errors. The year is 2017 (for a few more days).

int x; is a declaration of a variable; you reserve storage space for it.
Your other lines are not declarations. They are expressions. These expressions can only be used in another expression or in the assignment to another variable, for example:
long l = (long) x;
double d = (double) ((long)x/1234);

Related

Passing float to a function with int argument (that is not declared beforehand)

I have read Garbage value when passed float values to the function accepting integer parameters answers. My question goes a bit deeper. I could have also asked there had I more than 50 reputation point. I am adding my code for more clarification:
#include <stdio.h>
#include <string.h>
void p2(unsigned int tmp)
{
printf("From p2: \n");
printf("tmp = %d ,In hex tmp = %x\n", tmp, tmp);
}
int main()
{
float fvar = 45.65;
p1(fvar);
p2(fvar);
printf("From main:\n");
printf("sizeof(int) = %lu, sizeof(float) = %lu\n", sizeof(int),
sizeof(float));
unsigned int ui;
memcpy(&ui, &fvar, sizeof(fvar));
printf("fvar = %x\n", ui);
return 0;
}
void p1(unsigned int tmp)
{
printf("From p1: \n");
printf("tmp = %d ,In hex tmp = %x\n", tmp, tmp);
}
The output is:
From p1:
tmp = 1 ,In hex tmp = 1
From p2:
tmp = 45 ,In hex tmp = 2d
From main:
sizeof(int) = 4, sizeof(float) = 4
fvar = 4236999a8
Passing a float value to a function that is declared beforehand (i.e. p2) with int arguments gives the correct result. When trying the same with a function that is not declared beforehand (i.e. p1) gives incorrect values. And I know the reason that compiler won't assume any type or arity of arguments for the function not declared before handed. That's why float value does not get typecasted to int in the case of p2.
My confusion is, in the case of p2, how exactly does float value get copied to local int variable tmp.
If it is 'bit by bit copy' than reading those locations should yield something (except 1) in hex at least (if not in integer). But that does not sound the case as output shows. I know that float representation is different.
And how p2 may read registers/stack locations that floats weren't copied to? as simonc suggested in the linked question?
I have included the size of int and float both and my compiler is gcc if that helps.
The C programming language is essentially a single-scan language - a compiler doesn't need to reread the code but it can assemble it line by line, retaining information only on how identifiers were declared.
The C89 standard had the concept of implicit declaration. In absence of a declaration, the function p1 is declared implicitly as int p1(); i.e. a function that returns an int and takes unspecified arguments that go through default argument promotions. When you call such a function giving it a float as an argument, the float argument is promoted to a double, as called for by default argument promotions. It would be fine if the function was int p1(double arg); but the expected argument type is unsigned int, and the return value is not compatible either (void vs int). This mismatch will cause the program to have undefined behaviour - there is no point in reasoning what is happening then. However, there are many old C programs that would fail to compile, if the compilers wouldn't support the archaic implicit declarations - thus you just need to consider all these warnings as errors.
Notice that if you change the return value of p1 into an int, you will get less warnings:
% gcc implicit.c
implicit.c:14:5: warning: implicit declaration of function ‘p1’ [-Wimplicit-function-declaration]
p1(fvar);
^~
But the observed behaviour on my compiler would be mostly the same.
Thus the presence of mere warning: implicit declaration of function ‘x’ is quite likely a serious error in newly written code.
Were the function declared before its use, as is case with p2, then the compiler knows that it expects an unsigned long as the argument, and returns void, and therefore it would know to generate correct conversion code from float to unsigned long for the argument.
The C99 and C11 do not allow implicit function declarations in strictly-conforming programs - but they also do not require a conforming compiler to reject them either. C11 says:
An identifier is a primary expression, provided it has been declared as designating an object (in which case it is an lvalue) or a function (in which case it is a function designator).
and a footnote noting that
Thus, an undeclared identifier is a violation of the syntax.
However, it doesn't require a compiler to reject them.
This,
void p1(unsigned int tmp);
would be implicitly declared as
int p1();
by the compiler.
Although the compiler does not throw an error, it should be considered one as you can read in the linked post.
In any event, this is undefined behavior and you can't expect a predictable output.
In binary level, float and int don't look alike at all.
When trying to copy a float into a int, there's an implicit conversion, that's why when you call a function that takes int as argument but you provide a float you get the integer part of it, but in the final test you get to see how ugly it really look like. That's no garbage, that's how a float looks like in memory if you'd print it in hexadecimal. See IEEE 754 for details.
The issue with p1() however is that you are trying to call a function that has not been declared, so it's automatically declared as int p1(). Even though you later define it as void p1(unsigned int tmp), it has already been declared as int p1() (not taking any parameters) so it doesn't work (behavior is undefined). I'm pretty sure the compiler is screaming with warnings and errors about that, those errors aren't meant to be ignored.
Notice there's a big difference between declaring and defining a function. It is perfectly legal to define a function later, the way you are doing, but if you want it to work properly it has to be declared before any attempt to use it.
Example:
// declare functions
void p1(unsigned int tmp);
void p2(unsigned int tmp);
// use functions
int main()
{
p1(1);
p2(1);
}
// define functions
void p1(unsigned int tmp)
{
// do stuff
}
void p2(unsigned int tmp)
{
// do stuff
}

C gives different output based on optimization level (new example)

Based on this very good blog post, The Strict Aliasing Situation is Pretty Bad, I've placed the piece of code online for you to test it:
http://cpp.sh/9kht (output changes between -O0 and -O2)
#include <stdio.h>
long foo(int *x, long *y) {
*x = 0;
*y = 1;
return *x;
}
int main(void) {
long l;
printf("%ld\n", foo((int *)&l, &l));
}
Is there some sort of undefined behaviour here?
What is going on internally when we choose the -O2 level?
Yes, this program has undefined behavior, because of the type-based aliasing rules, which can be summarized as "you cannot access a memory location declared with type A through a pointer of type B, except when B is a pointer to a character type (e.g. unsigned char *)." This is an approximation, but it is close enough for most purposes. Note that when A is a pointer to a character type, B may not be something else—yes, this means the common idiom of accessing a byte buffer "four at a time" through an uint32_t* is undefined behavior (the blog post also touches on this).
The compiler assumes, when compiling foo, that x and y may not point to the same object. From this, it infers that the write through *y cannot change the value of *x, and it can just return the known value of *x, 0, without re-reading it from memory. It only does this when optimization is turned on because keeping track of what each pointer can and cannot point to is expensive (so the compilation is slower).
Note that this is a "demons fly out of your nose" situation: the compiler is entitled to make the generated code for foo start with
cmp rx, ry
beq __crash_the_program
...
(and a tool like UBSan might do just that)
Said another way, the code (int *)&l says treat the pointer as a pointer to an int. It does not convert anything. So, the (int *) tells the compiler to allow you to pass a long* to a function expecting an int*. You are lying to it. Inside, foo expects x to be a pointer to an int, but it isn't. The memory layout is not what it should be. Results are, as you see, unpredictable.
On another note, I wouldn't ever use l (ell) as a variable name. It is too easily confused with 1 (one). For example, what is this?
int x = l;

Typecasting Pointers in C [duplicate]

This question already has answers here:
Assigning Float Pointers in C [closed]
(3 answers)
Closed 9 years ago.
I'm new to C, and I'm writing a very basic function that takes an integer pointer as a parameter. Inside the function, a float pointer must be created. This function must assign the value of the integer pointer to the float and then return the float. Here's my code at the moment:
float * function(const int *x)
{
float *p = (float*)x;
return p;
}
But this results in an error that reads as such when run: "free(): invalid pointer: 0x00007fffc0e6b734". Suffice it to say, I'm very confused. Any insights you can offer would be much appreciated!
Being new to C, are you familiar with the scope of variables? (Part of) the short version of variable scope is that if you don't do a little something extra, a variable created in a function only exists inside that function. Why that's important to you: if you return a pointer to a variable that you created inside a function (without doing that little something extra) that pointer will point to an area of memory that may or may not contain the value that you assigned to it. One way to do what you want is this:
float *makefloat(int *x) {
// static keyword tells C to keep this variable after function exits
static float f;
// the next statement working from right to left does the following
// get value of pointer to int (x) by dereferencing: *x
// change that int value to a float with a cast: (float)
// assign that value to the static float we created: f =
f = (float) *x;
// make pointer to float from static variable: &f
return &f;
}
In general I seem to see more functions that accept a pointer to the variable that is to be modified, then in that function the new value is created and assigned to the area in memory referenced by the pointer. Because that area of memory exists outside of the scope of the function, there is no need to worry as much about scope and static variables. Another cool thing about static variables is that the next time the function is called, the static variable has the same value it did when the function last exited. Explained on Wikipedia.
Good explanation of * and &: Pointers in C: when to use the ampersand and the asterisk
Your function only performs a pointer conversion. A function call of the form
q = function(p); /* p is a "const int *" pointer,
q is assignment comaptible with "float *". */
can be replaced by the expression:
q = (float *) p;
by itself, this doesn't do any harm. The problem is elsewhere in your program.
Note that most type punning, like accessing an object of type int using an expression of type float via pointers, is undefined behavior in the C language. This isn't going on in the example code, but things are headed in that direction; the pointer is probably being prepared for carrying out type punning.
Consider that int and float don't necessarily even have the same size; and that is not the only consideration. In code like this:
int i = 42;
/* now treat i as a float and modify it sneakily */
*((float *) &i) = 3.14;
printf("i = %d\n", i);
the output of the printf can still be 42. The optimizing compiler can put i into a machine register, whereas the sneaky assignment might be performed on the memory location that serves as the "backing storage" for i, and so i appears unchanged since the printf call uses the register-cached copies. The compiler is not required to consider that a modification of an object designated by the type float might affect the value of an object of type i (even if they otherwise have the same size, so there is no collateral damage done by the assignment, like overwriting other objects).
In the real world, sometimes it is necessary to write a code that manipulates floating-point objects as if they were integers: typically unsigned int integers, to gain access to the bitwise representation of the float. When this is done, you have to use unions, or perhaps compiler-specific features, like GCC's -fno-strict-aliasing option which causes the compiler to optimize more cautiously in the face of type punning. in that kind of code, you make sure that the assumptions are all warranted about the sizes of types and such, with #ifdef-s for different platforms, perhaps based on values pulled from running configured scripts to detect platform features.
Needless to say, this is not a good way to be learning C at a beginner level.

What could be case of use `int x = x;` expression (C language)?

I have a lib written in C. In code i found a few lines like this int x = x;. I need to rewrite all this pieces of code for compilation with /Zw flag. In some places that mean's int x = some_struct->x;, but in another cases i don't understand what is it. In some places it first use of x variable. So in which cases could be used such int x = x; expression.
void oc_enc_tokenize_dc_frag_list(oc_enc_ctx *_enc,int _pli,
const ptrdiff_t *_coded_fragis,ptrdiff_t _ncoded_fragis,
int _prev_ndct_tokens1,int _prev_eob_run1){
const ogg_int16_t *frag_dc;
ptrdiff_t fragii;
unsigned char *dct_tokens0;
unsigned char *dct_tokens1;
ogg_uint16_t *extra_bits0;
ogg_uint16_t *extra_bits1;
ptrdiff_t ti0;
ptrdiff_t ti1r;
ptrdiff_t ti1w;
int eob_run0;
int eob_run1;
int neobs1;
int token;
int eb;
int token1=token1;
int eb1=eb1;
/*Return immediately if there are no coded fragments; otherwise we'd flush
any trailing EOB run into the AC 1 list and never read it back out.*/
if(_ncoded_fragis<=0)return;
frag_dc=_enc->frag_dc;
dct_tokens0=_enc->dct_tokens[_pli][0];
dct_tokens1=_enc->dct_tokens[_pli][1];
extra_bits0=_enc->extra_bits[_pli][0];
extra_bits1=_enc->extra_bits[_pli][1];
ti0=_enc->ndct_tokens[_pli][0];
ti1w=ti1r=_prev_ndct_tokens1;
eob_run0=_enc->eob_run[_pli][0];
/*Flush any trailing EOB run for the 1st AC coefficient.
This is needed to allow us to track tokens to the end of the list.*/
eob_run1=_enc->eob_run[_pli][1];
if(eob_run1>0)oc_enc_eob_log(_enc,_pli,1,eob_run1);
/*If there was an active EOB run at the start of the 1st AC stack, read it
in and decode it.*/
if(_prev_eob_run1>0){
token1=dct_tokens1[ti1r];
eb1=extra_bits1[ti1r];
ti1r++;
eob_run1=oc_decode_eob_token(token1,eb1);
code exaple - variable token1 - it's first use of token1 in file and token1 never meets in other files, it's not global, not static anywhere...
Update with /Zw flag:error C4700: uninitialized local variable 'token1' used
without flag: all works fine with this lib
Update 2
it's theora 1.1.1 lib
Resume
on advice of the guys in comments, i replace every int x = x; with int x = 0 and everything works fine =) everyone thanx for answers
If you literally have int x = x;, there isn't much use of it. This piece attempts to initialize x with itself, that is, with the value of an uninitialized variable.
This may suppress some compiler warnings/errors related to uninitialized or unused variables. But some compilers can catch these dubious cases as well.
This probably also results in undefined behavior from the C standard's view point.
EDIT: Random Number Bug in Debian Linux is an article (with further links) about use and abuse of uninitialized variables and the price one may pay one day.
It prevents the compiler from emitting a warning that the variable is unused.

understanding call a pointer to a function

I am trying to understand what is a pointer to a function in c.
I am wanting some detailed process of calling a pointer to function, thus, i could understand pointer to function better.
Could somebody explain why does my code below not crash and have some wired output?
To narrow down, I am seeking something like javap which could explain how does jdk compile
my code and jvm run my code
what is the relationship of a void return and number 14,15 or 16.
(the void function return)
is there any security problem to my second param or is it same as non-init val ?
test.c
#include <stdio.h>
#include <stdlib.h>
static void f(int x, int y){
printf("x = %d \n", x );
printf("y = %d \n", y );
}
typedef int (*FUNC)(int);
int main(void){
long int addr = (long int)f;
printf("%d \n", (int)((FUNC)addr)(1) );
return 0;
}
output on mac os compiled with i686-apple-darwin11-llvm-gcc-4.2
x = 1
y = 1479046720
16
The answer is undefined behavior. You're using two incompatible function pointer types and use one to call the other. (Not to mention storing the pointer in an integer, etc., etc.) Thus, your program invokes undefined behavior, and as such, anything can happen. And the values you get are most probably just random crap from the messed up stack and/or CPU registers.
You are causing undefined behavior all over the place:
You're storing the function pointer in a integer, which isn't guaranteed to work
You're casting said integer to a different type of function pointer (fewer parameters) with a different return type
You're calling the function with fewer parameters than it expects
You take a return value from a function returning void
Trying to make sense of this is just unreasonable, but as a guess since you're using x86:
x is populated correctly in the function with the 1 you passed
y isn't so it gets a random value, likely some leftover on the stack
there's no return value and you get whatever was left in the AX register
Could somebody explain why does my code below not crash and have some
wired output
Doing the wrong thing isn't guaranteed to crash your program - there are no guarantees.
The value 16 you get back in the last output is PROBABLY the number of characters written by printf - as that's what printf returns, and in this case, nothing else happens after that in the function. But like others have said, you're asking what happens, and nobody can really say - it may not work at all, crash and burn, or give you some "random" values as return and printout - it's not defined anywhere, and if you compile the code with a different compiler, different compiler settings or on a different type of hardware, the results will change.
Each time you run the code, it will most likely give you the same result, but make some changes to the code, and unpredictable results will occur.
To answer the question,
Could somebody explain why does my code below not crash
not all broken code actually crashes. Possibly the parameters (and the return values) of f are passed in registers instead of being pushed onto the stack, and therefore the mismatch between expected values and actual values does not translate into a stack misalignment. If you tried with more arguments, enough to require stack work, you would probably get that crash, or some possibly dangerous behaviour (a similar technique is used in some security exploits, after all).
Then to clarify usage of function pointers, I have taken the liberty of rewriting the code with a couple of comments.
#include <stdio.h>
#include <stdlib.h>
/* We want to be able to print a return value, so we make
f return something - a long, so as to tell it from int
- in order to be able to get something back.
*/
static long f(int x, int y){
printf("x = %d \n", x );
printf("y = %d \n", y );
return x + y;
}
/* We want the signature of a function returning long, and taking
two int's, since this is what f() is.
*/
typedef long (*FUNCPTR)(int, int);
typedef long (FUNC)(int, int);
int main(void)
{
/* We want a pointer to f - it works either way */
FUNCPTR addr = f;
FUNC *addr2 = f;
/* addr points to a function taking two ints, so we must pass it
two ints, and format return as long decimal */
printf("%ld\n", addr(5, 7));
/* addr2 is the same */
printf("%ld\n", addr2(5, 7));
return 0;
}
Expected output:
$ gcc -W -Wall -o test test.c
$ ./test
x = 5
y = 7
12
x = 5
y = 7
12

Resources