Own offsetof implementation produces warning - c

I wrote a small piece of code to understand how the offsetof macro works in the background. Here is the code:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
/* Getting the offset of a variable inside a struct */
typedef struct {
int a;
char b[23];
float c;
} MyStructType;
unsigned offset = (unsigned)(&((MyStructType * )NULL)->c);
printf("offset = %u\n", offset);
return 0;
}
However, if I run it I get a warning message:
WARNING: cast from pointer to integer of different size [-Wpointer-to-int-cast]
However, if I look at the original offsetof macro in c, the code looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
int main(void)
{
/* Getting the offset of a variable inside a struct */
typedef struct {
int a;
char b[23];
float c;
} MyStructType;
unsigned offset = offsetof(MyStructType, c);
printf("offset = %u\n", offset);
return 0;
}
So why do I get the warning as I cast to unsigned ? It appears to be the type for the offsetof macro. This is puzzling me.

As mch commented, unsigned is not the right type; it's 32-bit on pretty much all real-world systems. The offsetof macro is supposed to produce a result of type size_t, which is what you "should" be casting to here. I think you're confused by the code you found storing the result into an object of type unsigned; that's okay as long as they're sure the value is small, but it doesn't mean the type of the expression offsetof(MyStructType, c); was unsigned. C allows you to silently assign a larger integer type into a smaller one.
However, no matter what you do, this is not a valid implementation of offsetof and has undefined behavior (via applying -> to an invalid pointer). The way you get a working offsetof without UB is #include <stddef.h>.

Related

Overlay struct to arbitary buffer

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.

Why won't this C program print the unsigned int?

I wrote this function to reverse a number. I will have test cases that are up to 2^32. I need the function to return unsigned ints. My question is this: why wont this print?
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
unsigned int reverse(unsigned int a);
int main(){
printf("%u\n",reverse(987654321));
//printf("%ui\n",reverse(987654321)); //this wont work either
return 0;
}
unsigned int reverse(unsigned int a)
{
int temp=0;
while(a>0)
{
temp=10*temp+a%10;
a/=10;
}
return temp;
}
Yes I did forget about the proto-type... Bear with me I have been doing Java and Lisp lately. However, my compiler keeps giving me a warning saying I have extra characters in the format string. It also does this if I have type "long long int" and I use "%lli% in the format string, which I also tried.
You forgot to include prototype for your function before main.
unsigned int reverse(unsigned int a);
The number probably is just too big for an unsigned on your architecture.
Remember to always enable maximum warning level for your compiler. This should have told you that reverse is not known where you use it, that you are passing an int to the %u format and also that your number ist too big.

Troubling converting string to long long in C

I'm having trouble getting the atoll function to properly set a long long value in c. Here is my example:
#include <stdio.h>
int main(void) {
char s[30] = { "115" };
long long t = atoll(s);
printf("Value is: %lld\n", t);
return 0;
}
This prints:
Value is: 0
This works though:
printf("Value is: %lld\n", atoll(s));
What is going on here?
First, let's answer your question:
#include <stdio.h>
#include <stdlib.h> // THIS IS WHAT YOU ARE MISSING
int main(void) {
char s[30] = { "115" };
long long t = atoll(s);
printf("Value is: %lld\n", t);
return 0;
}
Then, let's discuss and answer 'why?':
For compatibility with very old C programs (pre-C89), using a function without having declared it first only generates a warning from GCC, not an error (As pointed out by the first comment here, also implicit function declarations are allowed in C89, therefore generating an error would not be appropriate, that is another reason to why only a warning is generated). But the return type of such a function is assumed to be int (not the type specified in stdlib.h for atoll for instance), which is why the program executes unexpectedly but does not generate an error. If you compile with -Wall you will see that:
Warning: Implicit declaration of function atoll
This fact mostly shocks people when they use atof without including stdlib.h, in which case the expected double value is not returned.
NOTE: (As an answer to one of the comments of the question) This is the reason why the results of atoll might be truncated if the correct header is not included.

New to C programming on linux, stuck at typecasting

I am pretty new to programming on Linux. I am trying to implement a message queue in one of my assignments. But I am not able to do it. The code is as follows :
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <linux/sched.h>
#include <stdlib.h>
#include <string.h>
typedef long MSISDN;
typedef struct
{
long mtype;
long mtext;
}msgbuf;
void init(int qid,int key) {
qid = msgget(key,IPC_CREAT|0666);
}
void sendMsg(long t_ype, long buf, int len, int qid) {
int length = sizeof(long) + sizeof(MSISDN);
msgbuf *p = malloc(length);
p->mtype = t_ype;
fputc('2',stderr);
void* tosend = (void*) buff;
fputc('3',stderr);
memcpy(p->mtext,tosend,length);
fputc('4',stderr);
msgsnd(qid,p,length,IPC_NOWAIT);
free(p);
}
void main()
{
int qid;
int key = 1111;
int len= sizeof(MSISDN);
long type_1=1;
long send = 12345;
init(qid,key);
fputc('1',stderr);
sendMsg(type_1,send,len,qid);
getchar();
}
The problem is memcpy is not working . I am getting a warning :
. warning: passing argument 1 of ‘memcpy’ makes pointer from integer without a cast [enabled by default]
Also when I run the code it gets a SIGSEGV signal at the memcpy. I think I am not getting the typecast correctly.
It's not the typecast, it's the argument itself. p->mtext is a long, not a pointer. You need to send the address of p->mtext as the dest argument to memcpy. You're getting the segfault because memcpy is trying to write to the memory address pointed to by p->mtext, which is clearly not in your process' address space.
That's the reason - since this is a homework assignment, I'll leave the fixing of the code up to you.
You would explicitly type cast a variable like this
double num = 1.11;
int num2 = (int)num;
num = 1.11
num2 = 1

size of a datatype without using sizeof

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;
}

Resources