Related
I'm a "new" C programmer, but an old assembly programmer, and have been searching for an answer for a few days.
I'm trying to parse multiple fields in a message with the C struct construct, (It's a LORA radio with an embedded RTU modbus packet).
I have This example code that shows my question:
#include <stdio.h>
#include <stdint.h>
struct MessageTable{
uint8_t msg_id;
uint8_t from;
uint8_t to;
unsigned flags1 : 1;
unsigned retransmitted : 1;
unsigned hops : 4;
union {
unsigned long millisecs;
unsigned char bytes[sizeof(unsigned long)];
} ms;
};
struct MessageTable message, *mp;
struct MessageTable message_table[8] = {0};
char buf[256];
void main(void) {
int i;
for (i=0; i<255; i++)
buf[i] = i;
mp = (struct MessageTable) &buf;
printf("To: %u, From: %u", mp->to, mp->from);
}
When I try to compile I get:
question.c: In function ‘main’:
question.c:27:18: error: conversion to non-scalar type requested
27 | mp = (struct MessageTable) &buf;
| ^~~~~~~~~~~~
What I'm attempting to do is, overlay the struct in the buffer space at some arbitrary position for named access to the different fields instead of using hard coded offsets (I.E. to=buf[2]; and retransmitted = buf[3]&02x;
What is the clean, readable, appropriate way to do this?
NOTE: there will be multiple structs at different buf positions (LORA routing, Modbus Send, Modbus Rx, Modbus err, etc...)
and, this is straight C, not C++.
I don't care if the buffer "runs off" the end of the struct, the code constructs take care of that.
First to address your error message on this line:
mp = (struct MessageTable) &buf;
Here you're attempting to convert &buf, which has type char (*)[256] i.e. a pointer to an array, to a struct MessageTable which is not a pointer type. Arrays in most contexts decay to a pointer to the first element, so you don't need to take its address, and you need to cast it to a pointer type:
mp = (struct MessageTable *)buf;
The other issue however is:
The struct might not be exactly the size you expect
The order of bitfieds may not be what you expect
If the buffer is not properly aligned for the fields in the struct you could generate a fault.
You have two problems in:
mp = (struct MessageTable) &buf;
The first is buf is already a pointer due to array/pointer conversion. C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3)
The second problem is you are casting to struct MessageTable instead of a Pointer to struct MessageTable. You can correct both with:
mp = (struct MessageTable*) buf;
Also, unless you are programming in a freestanding environment (without the benefit of any OS), in a standards conforming implementation, the allowable declarations for main for are int main (void) and int main (int argc, char *argv[]) (which you will see written with the equivalent char **argv). See: C11 Standard - §5.1.2.2.1 Program startup(p1). See also: What should main() return in C and C++? In a freestanding environment, the name and type of the function called at program startup are implementation-defined. See: C11 Standard - 5.1.2.1 Freestanding environment
Putting it altogether you would have:
#include <stdio.h>
#include <stdint.h>
struct MessageTable{
uint8_t msg_id;
uint8_t from;
uint8_t to;
unsigned flags1 : 1;
unsigned retransmitted : 1;
unsigned hops : 4;
union {
unsigned long millisecs;
unsigned char bytes[sizeof(unsigned long)];
} ms;
};
struct MessageTable message, *mp;
struct MessageTable message_table[8] = {0};
char buf[256];
int main(void) {
int i;
for (i=0; i<255; i++)
buf[i] = i;
mp = (struct MessageTable*) buf;
printf("To: %u, From: %u", mp->to, mp->from);
}
Example Use/Output
$ ./bin/struct_buf_overlay
To: 2, From: 1
C struct fields are, by default, not guaranteed to be immediately adjacent to one other, and furthermore bitfields can be reordered. Implementations are permitted to reorder bitfields and implement padding in order to efficiently meet system memory alignment requirements. If you need to guarantee that struct fields are positioned in memory immediately adjacent to one another (without padding) and in the order you specified, you need to look up how to tell your compiler to create a packed struct. This is not standard C (but it's necessary to ensure that what you're trying to accomplish will work--it might, but is not guaranteed, to work otherwise), and each compiler has its own way of doing it.
A part of the C program that I am writing includes initialization of an input table using sc_memset() function. The table is defined by a typedef struct as shown below.
typedef struct {
UINT32 switchnum;
UINT32 feedback[8];
UINT32 switch_output[8];
} SWITCH_CHECK_IN;
SWITCH_CHECK_IN switch_input_table;
All the table elements, that is switchnum, feedback and switch_output should be initialized to zero.The sc_memset function prototype to be used for initialization is :
extern void sc_memset (volatile unsigned char *dest, unsigned long n, unsigned char data);
I have written the initialization code and because of the type differences in SWITCH_CHECK_IN & volatile unsigned char, I have tried to do some casting as below (I have tried several cast statements) but everytime I get a 'passing arg 1 of sc_memeset from incompatible pointer type' error.
while( *(volatile unsigned char *) &switch_input_table) {
{
sc_memset( &switch_input_table, sizeof(switch_input_table), 0 );
}
I'm new to C so I am not quite sure if my general approach is correct. Kindly,
1. Where am I going wrong? Could you please show me the correct way.
2. What other methods can be used?
Thanks in advance.
You need to cast the pointer to struct into a pointer to unsigned char, just like you do in the while condition:
sc_memset( (unsigned char*)&switch_input_table, ...
You shouldn't need volatile in the cast - the function implicitly adds volatile type qualifier to the passed parameter. Why it has volatile, I have no idea - it's fishy code unless the function expects a hardware register etc as input.
I'm trying to make a function that will accept a float variable and convert it into a byte array. I found a snippet of code that works, but would like to reuse it in a function if possible.
I'm also working with the Arduino environment, but I understand that it accepts most C language.
Currently works:
float_variable = 1.11;
byte bytes_array[4];
*((float *)bytes_array) = float_variable;
What can I change here to make this function work?
float float_test = 1.11;
byte bytes[4];
// Calling the function
float2Bytes(&bytes,float_test);
// Function
void float2Bytes(byte* bytes_temp[4],float float_variable){
*(float*)bytes_temp = float_variable;
}
I'm not so familiar with pointers and such, but I read that (float) is using casting or something?
Any help would be greatly appreciated!
Cheers
*EDIT: SOLVED
Here's my final function that works in Arduino for anyone who finds this. There are more efficient solutions in the answers below, however I think this is okay to understand.
Function: converts input float variable to byte array
void float2Bytes(float val,byte* bytes_array){
// Create union of shared memory space
union {
float float_variable;
byte temp_array[4];
} u;
// Overite bytes of union with float variable
u.float_variable = val;
// Assign bytes to input array
memcpy(bytes_array, u.temp_array, 4);
}
Calling the function
float float_example = 1.11;
byte bytes[4];
float2Bytes(float_example,&bytes[0]);
Thanks for everyone's help, I've learnt so much about pointers and referencing in the past 20 minutes, Cheers Stack Overflow!
Easiest is to make a union:
#include <stdio.h>
int main(void) {
int ii;
union {
float a;
unsigned char bytes[4];
} thing;
thing.a = 1.234;
for (ii=0; ii<4; ii++)
printf ("byte %d is %02x\n", ii, thing.bytes[ii]);
return 0;
}
Output:
byte 0 is b6
byte 1 is f3
byte 2 is 9d
byte 3 is 3f
Note - there is no guarantee about the byte order… it depends on your machine architecture.
To get your function to work, do this:
void float2Bytes(byte bytes_temp[4],float float_variable){
union {
float a;
unsigned char bytes[4];
} thing;
thing.a = float_variable;
memcpy(bytes_temp, thing.bytes, 4);
}
Or to really hack it:
void float2Bytes(byte bytes_temp[4],float float_variable){
memcpy(bytes_temp, (unsigned char*) (&float_variable), 4);
}
Note - in either case I make sure to copy the data to the location given as the input parameter. This is crucial, as local variables will not exist after you return (although you could declare them static, but let's not teach you bad habits. What if the function gets called again…)
Here's a way to do what you want that won't break if you're on a system with a different endianness from the one you're on now:
byte* floatToByteArray(float f) {
byte* ret = malloc(4 * sizeof(byte));
unsigned int asInt = *((int*)&f);
int i;
for (i = 0; i < 4; i++) {
ret[i] = (asInt >> 8 * i) & 0xFF;
}
return ret;
}
You can see it in action here: http://ideone.com/umY1bB
The issue with the above answers is that they rely on the underlying representation of floats: C makes no guarantee that the most significant byte will be "first" in memory. The standard allows the underlying system to implement floats however it feels like -- so if you test your code on a system with a particular kind of endianness (byte order for numeric types in memory), it will stop working depending on the kind of processor you're running it on.
That's a really nasty, hard-to-fix bug and you should avoid it if at all possible.
I would recommend trying a "union".
Look at this post:
http://forum.arduino.cc/index.php?topic=158911.0
typedef union I2C_Packet_t{
sensorData_t sensor;
byte I2CPacket[sizeof(sensorData_t)];
};
In your case, something like:
union {
float float_variable;
char bytes_array[4];
} my_union;
my_union.float_variable = 1.11;
Yet another way, without unions:
(Assuming byte = unsigned char)
void floatToByte(byte* bytes, float f){
int length = sizeof(float);
for(int i = 0; i < length; i++){
bytes[i] = ((byte*)&f)[i];
}
}
this seems to work also
#include <stddef.h>
#include <stdint.h>
#include <string.h>
float fval = 1.11;
size_t siz;
siz = sizeof(float);
uint8_t ures[siz];
memcpy (&ures, &fval, siz);
then
float utof;
memcpy (&utof, &ures, siz);
also for double
double dval = 1.11;
siz = sizeof(double);
uint8_t ures[siz];
memcpy (&ures, &dval, siz);
then
double utod;
memcpy (&utod, &ures, siz);
Although the other answers show how to accomplish this using a union, you can use this to implement the function you want like this:
byte[] float2Bytes(float val)
{
my_union *u = malloc(sizeof(my_union));
u->float_variable = val;
return u->bytes_array;
}
or
void float2Bytes(byte* bytes_array, float val)
{
my_union u;
u.float_variable = val;
memcpy(bytes_array, u.bytes_array, 4);
}
**conversion without memory reference** \
#define FLOAT_U32(x) ((const union {float f; uint32_t u;}) {.f = (x)}.u) // float->u32
#define U32_FLOAT(x) ((const union {float f; uint32_t u;}) {.u = (x)}.f) // u32->float
**usage example:**
float_t sensorVal = U32_FLOAT(eeprom_read_dword(&sensor));
First of all, some embedded systems 101:
Anyone telling you to use malloc/new on Arduino have no clue what they are talking about. I wrote a fairly detailed explanation regarding why here: Why should I not use dynamic memory allocation in embedded systems?
You should avoid float on 8 bit microcontrollers since it leads to incredibly inefficient code. They do not have a FPU, so the compiler will be forced to load a very resource-heavy software floating point library to make your code work. General advise here.
Regarding pointer conversions:
C allows all manner of wild and crazy pointer casts. However, there are lots of situations where it can lead to undefined behavior if you cast a character byte array's address into a float* and then de-reference it.
If the address of the byte array is not aligned, it will lead to undefined behavior on systems that require aligned access. (AVR doesn't care about alignment though.)
If the byte array does not contain a valid binary representation of a float number, it could become a trap representation. Similarly you must keep endianess in mind. AVR is an 8-bitter but it's regarded as little endian since it uses little endian format for 16 bit addresses.
It leads to undefined behavior because it goes against the C language "effective type" system, also known as a "strict pointer aliasing violation". What is the strict aliasing rule?
Going the other way around is fine though - taking the address of a float variable and converting it to a character pointer, then de-reference that character pointer to access individual bytes. Multiple special rules in C allows this for serialization purposes and hardware-related programming.
Viable solutions:
memcpy always works fine and then you won't have to care about alignment and strict aliasing. You still have to care about creating a valid floating point representation though.
union "type punning" as demonstrated in other answers. Note that such type punning will assume a certain endianess.
Bit shifting individual bytes and concatenating with | or masking with & as needed. The advantage of this is that it's endianess-independent in some scenarios.
float f=3.14;
char *c=(char *)&f;
float g=0;
char *d=(char *)&g;
for(int i=0;i<4;i++) d[i]=c[i];
/* Now g=3.14 */
Cast your float as char, and assign the address to the char pointer.
Now, c[0] through c[3] contain your float.
http://justinparrtech.com/JustinParr-Tech/c-access-other-data-types-as-byte-array/
I have a c program with multiple headers and source files. On running, the program gives segmentation fault. On using "up" and "print variable" commands, i figured that the function "busntoint()" is not working properly.
I have following functions for converting a string of length n from binary to decimal:
unsigned int busntoint(int n, busn bus)
{
unsigned int value = 0;
int i;
for (i=0; i < n; i++) {
if (bus[i] == '1') value += (unsigned int)pow(2,(n-1-i));
}
return value;
}
unsigned int bus2toint(bus2 bus)
{
return busntoint(2, bus);
}
unsigned int bus32toint(bus32 bus)
{
return busntoint(32, bus);
}
I then wrote another program to check the working of these functions. It works just fine and gives the correct and expected output. I dunno why it is not working properly in the "bigger" program.
If it's useful, following is the definition of variables:
typedef char bus2[3];
typedef char bus3[4];
typedef char bus5[6];
typedef char bus6[7];
typedef char bus8[9];
typedef char bus16[17];
typedef char bus32[33];
The usage of the function in the "bigger" program is as follows:
int LoadMemory(char * binfilename, bus8 memory[4096])
{
//some code
int addr = bus32toint(line);
setbit8(memory[addr], &line[33]);
//some code
}
p addr in gdb gives garbage value, leading to segmentation fault in memory[addr].
Your first problem probably lies in your abuse of pow to compute powers of two and the possible overflow that your computation may encounter.
The correct way of computing integer powers of two is the shift operator, here that would be
2u << (n-1-i)
the suffix u is to ensure that this has the correct type (unsigned). But then you also have to ensure that the value by which you are shifting is not too large, you must guarantee that the corresponding power will still fit into an unsigned. You didn't tell us on what architecture your are, not all have unsigned with 32 bit.
Then your LoadMemory function also looks bogus. As far as I can see there can no guarantee be given that addr (for which you didn't show the type) is smaller than 4096.
Use unsigned int addr = bus32toint(line);
I have a data type, say X, and I want to know its size without declaring a variable or pointer of that type and of course without using sizeof operator.
Is this possible? I thought of using standard header files which contain size and range of data types but that doesn't work with user defined data type.
To my mind, this fits into the category of "how do I add two ints without using ++, += or + ?". It's a waste of time. You can try and avoid the monsters of undefined behaviour by doing something like this.
size_t size = (size_t)(1 + ((X*)0));
Note that I don't declare a variable of type or pointer to X.
Look, sizeof is the language facility for this. The only one, so it is the only portable way to achieve this.
For some special cases you could generate un-portable code that used some other heuristic to understand the size of particular objects[*] (probably by making them keep track of their own size), but you'd have to do all the bookkeeping yourself.
[*] Objects in a very general sense rather than the OOP sense.
Well, I am an amateur..but I tried out this problem and I got the right answer without using sizeof. Hope this helps..
I am trying to find the size of an integer.
int *a,*s, v=10;
a=&v;
s=a;
a++;
int intsize=(int)a-(int)s;
printf("%d",intsize);
The correct answer to this interview question is "Why would I want to do that, when sizeof() does that for me, and is the only portable method of doing so?"
The possibility of padding prevent all hopes without the knowledge of the rules used for introducing it. And those are implementation dependent.
You could puzzle it out by reading the ABI for your particular processor, which explains how structures are laid out in memory. It's potentially different for each processor. But unless you're writing a compiler it's surprising you don't want to just use sizeof, which is the One Right Way to solve this problem.
if X is datatype:
#define SIZEOF(X) (unsigned int)( (X *)0+1 )
if X is a variable:
#define SIZEOF(X) (unsigned int)( (char *)(&X+1)-(char *)(&X) )
Try this:
int a;
printf("%u\n", (int)(&a+1)-(int)(&a));
Look into the compiler sources. You will get :
the size of standard data types.
the rules for padding of structs
and from this, the expected size of anything.
If you could at least allocate space for the variable, and fill some sentinel value into it, you could change it bit by bit, and see if the value changes, but this still would not tell you any information about padding.
Try This:
#include<stdio.h>
int main(){
int *ptr = 0;
ptr++;
printf("Size of int: %d",ptr);
return 0;
Available since C89 solution that in user code:
Does not declare a variable of type X.
Does not declare a pointer to type X.
Without using sizeof operator.
Easy enough to do using standard code as hinted by #steve jessop
offsetof(type, member-designator)
which expands to an integer constant expression that has type size_t, the value of which is the offset in bytes, to the structure member ..., from the beginning of its structure ... C11 §7.19 3
#include <stddef.h>
#include <stdio.h>
typedef struct {
X member;
unsigned char uc;
} sud03r_type;
int main() {
printf("Size X: %zu\n", offsetof(sud03r_type, uc));
return 0;
}
Note: This code uses "%zu" which requires C99 onward.
This is the code:
The trick is to make a pointer object, save its address, increment the pointer and then subtract the new address from the previous one.
Key point is when a pointer is incremented, it actually moves by the size equal to the object it is pointing, so here the size of the class (of which the object it is pointing to).
#include<iostream>
using namespace std;
class abc
{
int a[5];
float c;
};
main()
{
abc* obj1;
long int s1;
s1=(int)obj1;
obj1++;
long int s2=(int)obj1;
printf("%d",s2-s1);
}
Regards
A lot of these answers are assuming you know what your structure will look like. I believe this interview question is intended to ask you to think outside the box. I was looking for the answer but didn't find any solutions I liked here. I will make a better assumption saying
struct foo {
int a;
banana b;
char c;
...
};
By creating foo[2], I will now have 2 consecutive foo objects in memory. So...
foo[2] buffer = new foo[2];
foo a = buffer[0];
foo b = buffer[1];
return (&b-&a);
Assuming did my pointer arithmetic correctly, this should be the ticket - and its portable! Unfortunately things like padding, compiler settings, etc.. would all play a part too
Thoughts?
put this to your code
then check the linker output ( map file)
unsigned int uint_nabil;
unsigned long ulong_nabil;
you will get something like this ;
uint_nabil 700089a8 00000004
ulong_nabil 700089ac 00000004
4 is the size !!
One simple way of doing this would be using arrays.
Now, we know for the fact that in arrays elements of the same datatype are stored in a contiguous block of memory. So, by exploiting this fact I came up with following:
#include <iostream>
using namespace std;
int main()
{
int arr[2];
int* ptr = &arr[0];
int* ptr1 = &arr[1];
cout <<(size_t)ptr1-(size_t)ptr;
}
Hope this helps.
Try this,
#define sizeof_type( type ) ((size_t)((type*)1000 + 1 )-(size_t)((type*)1000))
For the following user-defined datatype,
struct x
{
char c;
int i;
};
sizeof_type(x) = 8
(size_t)((x*)1000 + 1 ) = 1008
(size_t)((x*)1000) = 1000
This takes into account that a C++ byte is not always 8 binary bits, and that only unsigned types have well defined overflow behaviour.
#include <iostream>
int main () {
unsigned int i = 1;
unsigned int int_bits = 0;
while (i!=0) {
i <<= 1;
++int_bits;
}
unsigned char uc = 1;
unsigned int char_bits = 0;
while (uc!=0) {
uc <<= 1;
++char_bits;
}
std::cout << "Type int has " << int_bits << "bits.\n";
std::cout << "This would be " << int_bits/8 << " IT bytes and "
<< int_bits/char_bits << " C++ bytes on your platform.\n";
std::cout << "Anyways, not all bits might be usable by you. Hah.\n";
}
Surely, you could also just #include <limit> or <climits>.
main()
{
clrscr();
int n;
float x,*a,*b;//line 1
a=&x;
b=(a+1);
printf("size of x is %d",
n=(char*)(b)-(char*)a);
}
By this code script the size of any data can be calculated without sizeof operator.Just change the float in line 1 with the type whose size you want to calculate
#include <stdio.h>
struct {
int a;
char c;
};
void main() {
struct node*temp;
printf("%d",(char*)(temp+1)-(char*)temp);
}
# include<stdio.h>
struct node
{
int a;
char c;
};
void main()
{
struct node*ptr;
ptr=(struct node*)0;
printf("%d",++ptr);
}
#include <bits/stdc++.h>
using namespace std;
int main()
{
// take any datatype hear
char *a = 0; // output: 1
int *b = 0; // output: 4
long *c = 0; // output: 8
a++;
b++;
c++;
printf("%d",a);
printf("%d",b);
printf("%d",c);
return 0;
}