Holding variable in struct - c

I have a HIGHLY performance critical section in my code where i need to minimize cpu load as much as i can. If i have a struct that has one instance, is there ANY difference in performance between defining variables in code by iteself like this:
int something;
int randomVariable;
or defining them in struct?
struct Test
{
int something;
int randomVariable;
}
because i want to use struct to make code look better

In my opinion the best way to know this , first write two different programs in C , with struct and without struct and then make them assembly file with using
gcc -S file.c
Since i dont know your code , i directly assigned values to them :
int main() {
int something;
int randomVariable;
something = 3;
randomVariable = 3;
return 0;}
and
main() {
struct Test
{
int something;
int randomVariable;
}test;
test.something = 3;
test.randomVariable = 3;
return 0;}
and i get assembly files on my Ubuntu-64bit , intel i5 machine
I saw that assembly files are nearly same
.file "test1.c"
.text
.globl main
.type main, #function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $3, -8(%rbp) **Second one(with struct) has value -16 instead -8**
movl $3, -4(%rbp) **Second one has value -12 instead of -4**
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4"
.section .note.GNU-stack,"",#progbits
So according to that results I can say that two implementation has not any significant difference about CPU load. Only difference between them second one is using very very little more memory than first one.

First, to be fair, because i want to use struct to make code look better is purely a style thing. What looks better to one person may not look better to another.
I am a fan of struct when there is a choice, for several reasons.
Speed/size efficiency:
Compare a struct over over two discrete int variables when data needed to be passed as a function argument.
Using:
int a;
int b;
Or
typedef struct {
int a;
int b;
}VAR;
VAR var;
The same data could be passed as separate pointers via function arguments (assuming 32 bit addressing):
int func1(int *a, int *b);//two 32 bit addresses passed
Or:
int func2(VAR *v);//one 32 bit address passed
The efficiency (of this type) goes up directly as number of variable goes up.
(efficiency gain if there were 100 ints?)
In the first example, you are passing two int *, while in the second, only one. Its a small difference, but it is a difference. The magnitude of the advantage is also dependent on addressing used. 32bit or 64bit.
Code maintenance and readability:
function prototypes, when used as application programming interface (API) should be stable. Using struct as arguments or as a return type support this interface stability.
For example: Given a requirement to calculate the changing velocity in Cartesian coordinates of x, y & z, of an object moving in a straight line with respect to time, you might design a function that would be called repeatedly with current values of velocityxyz and accelerationxyz and timems. The number of arguments required clearly suggest use of a struct. Struct is also suggested as the return type:
typedef struct {
double x;
double y;
double z;
}VEL; //velocity
typedef struct {
double x;
double y;
double z;
}ACC; //acceleration
typedef struct {
VEL vel;
ACC acc;
time_t ms;
}KIN; //kinematics
KIN * GetVelocity(KIN *newV);
If a new requirement for knowing Positionxyz was added to the project, all that would have to be added is a new member of the KIN struct:
typedef struct {
double x;
double y;
double z;
}POS; //position
...
typedef struct {
POS pos;
VEL vel;
ACC acc;
time_t ms;
}KIN; //kinematics
KIN * GetVelocity(KIN *newV);//prototype will continue to work
//without changing interface (argument list)
KIN * GetPosition(KIN *newV);//new prototype for position also supported

Related

How does typedefing influence compile/assembly?

Since there are two ways of writing enums, structs, unions or types where one uses typedef, or alternatively doesn't, I was wondering what would be the benefits and disadvantages of each approach.
E.g. 1: typedef enum { ENUM_A, ENUM_B } ENUM_OBJECT;
E.g. 2: typedef unsigned char uint8
Personally I like encapsulation provided by the second variant, but when I write code for all enums, structs and unions I would always avoid writing the first example with typedef, but I would use this approach:
E.g. 1: enum ENUM_TAG { ENUM_A, ENUM_B };
enum ENUM_TAG some_variable;
Yes, I know that it can take a bit more horizontal space, but to me it better details idea of what is the type than something like this:
typedef int matrix_buffer_t[2][5];
matrix_buffer_t some_variable;
Can someone outline facts (not personal opinions, since these are discussible) about differences between usage of typedef and no typedef? How does this influence compiled code, program memory size, etc?
I've tried looking at the assembly diff when I compile the following code with no typedef:
struct TestStruct
{
int field;
};
int main(void)
{
struct TestStruct test;
printf ("%d\n", test.field);
return 1;
}
vs code with typedef:
typedef struct
{
int field;
} TestStruct;
int main(void)
{
TestStruct test;
printf ("%d\n", test.field);
return 1;
}
Assembly is definitely not the same. I'm giving a side to side comparison:
___________________________________________________________________________________________________________
.LC0: .LC0:
.string "%d\n" .string "%d\n"
main: main:
pushq %rbp push rbp
movq %rsp, %rbp mov rbp, rsp
subq $16, %rsp sub rsp, 16
movl -4(%rbp), %eax mov eax, DWORD PTR [rbp-4]
movl %eax, %esi mov esi, eax
movl $.LC0, %edi mov edi, OFFSET FLAT:.LC0
movl $0, %eax mov eax, 0
call printf call printf
movl $1, %eax mov eax, 1
leave leave
ret ret
It was compiled using godbolt and gcc compiler. For sure I can see the difference I am just wondering when it is better to use which approach depending on benefits/flaws.
Note: I've tried compiling to a .map file which gives addresses of each variable, size, types, etc. and when typedef is used, .map file becomes more compex.
Typedef is the only feature that makes C language grammar a context-sensitive grammar.
Its effect is to change the environment of the parser, to convert some symbols into special symbols.
Without typedef a parser for the C language would not need an environmental structure to keep track of the definitions of type symbols.
Note that in ISO/IEC 9899:1999 5.1.1.2 Translation phases, typedef acts into the 7th step (the syntax analyser step):
White-space characters separating tokens are no longer significant. Each
preprocessing token is converted into a token. The resulting tokens are
syntactically and semantically analyzed and translated as a translation unit.
Can someone outline facts (not personal opinions, since these are discussible) about differences between usage of typedef and no typedef?
This is the very same, mostly subjective discussion as whether you should typedef struct or not. Most people use typedef, except the Linux world which tends to type out struct tag and there is no obvious right or wrong.
(Although the attempt to provide a rationale for using the latter style in the unprofessional document Linux kernel coding style is laughable, entirely subjective and similar to the arguments for using "Hungarian notation".)
Regarding enum, you typically use the typedef just to not having to type out the enum tag every time you use it. Anonymous enum without a name are typically just use when dealing with a local, encapsulated type.
There are a few non-subjective reasons why typing out keyword + tag is bad:
Two preprocessor tokens instead of one can be problematic to use when passing types to function-like macros, using them in X-macros and similar. Example:
#define SUPPORTED_TYPES(X) \
X(int) \
X(float) \
X(struct foo) \
enum
{
#define ENUM_CONSTANT(type) type ## _val,
SUPPORTED_TYPES(ENUM_CONSTANT)
};
This code is attempting to create a number of constants corresponding to a list of supported types. It will create int_val, float_val and then fail upon struct foo_val because there are two preprocessor tokens in that type and spaces can't be used in identifiers. On the other hand, the same problem exists when using unsigned int.
Not typing out the tag is consistent with C++ coding style. C++ doesn't have tags in the same manner as C, but the name of the type is the type - with no need to type out the keyword explicitly.
Regarding typedef unsigned char uint8 specifically, this is very bad practice but not because of the typedef but because you are inventing your own "local garage standard" instead of using standard C stdint.h types.
I've tried looking at the assembly diff when I compile the following code with no typedef
You are doing something wrong, like not using the same optimizer settings or forgetting #include <stdio.h> in C90 mode. There's identical machine code, see for yourself: https://godbolt.org/z/zd5q7Pc77

How to specify default global variable alignment for gcc?

How do I get rid of alignment (.align 4 below) for all global variables by default with GCC, without having to specify __attribute__((aligned(1))) for each variable?
I know that what I ask for is a bad idea to apply universally, becuase on some architectures an alignment of 1 wouldn't work, because e.g. the CPU is not able to dereference an unaligned pointer. Bit in my case I'm writing an i386 bootloader, and unaligned pointers are fine (but slower) there.
Source code (a.c):
__attribute__((aligned(1))) int answer0 = 41;
int answer = 42;
Compiled with: gcc -m32 -Os -S a.c
Assembly output (a.s):
.file "a.c"
.globl answer
.data
.align 4
.type answer, #object
.size answer, 4
answer:
.long 42
.globl answer0
.type answer0, #object
.size answer0, 4
answer0:
.long 41
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4"
.section .note.GNU-stack,"",#progbits
The flag gcc -fpack-struct=1 changes the alignment of all struct members and structs to 1. For example, with that flag
struct x { char a; int b; };
struct y { int v : sizeof(char) + sizeof(int) == sizeof(struct x); };
struct z { int b; };
struct x x = { 1, 1 };
int i = 42;
struct z z = { 2 };
compiles to no alignment for variables x' andz', but it still has an .align 4 for the variable i (of type int). I need a solution which also makes int i = 42; unaligned, without having to specify something extra for each such variable.
IMO packing variables to save the space using the packed struct is the easiest and safest way.
example:
#include <stdio.h>
#include <stdint.h>
#define _packed __attribute__((packed))
_packed struct
{
uint8_t x1;
_packed int x2;
_packed uint8_t x3[2];
_packed int x4;
}byte_int;
int main(void) {
printf("%p %p %p %p\n", &byte_int.x1, &byte_int.x2, &byte_int.x3, &byte_int.x4);
printf("%u %u %u %u\n", (unsigned int)&byte_int.x1, (unsigned int)&byte_int.x2, (unsigned int)&byte_int.x3, (unsigned int)&byte_int.x4); // I know it is an UB just to show the op in dec - easier to spot the odd and the even addresses
return 0;
}
https://ideone.com/bY1soH
Most probably gcc doesn't have such a flag which can change the default alignment of global variables.
gcc -fpack-struct=1 can be a workaround, but only for global variables which happen to be of struct type.
Also post-processing the .s output of gcc and removing (some of) the .align lines could work as a workaround.

incompatible return type from struct function - C

When I attempt to run this code as it is, I receive the compiler message "error: incompatible types in return". I marked the location of the error in my code. If I take the line out, then the compiler is happy.
The problem is I want to return a value representing invalid input to the function (which in this case is calling f2(2).) I only want a struct returned with data if the function is called without using 2 as a parameter.
I feel the only two ways to go is to either:
make the function return a struct pointer instead of a dead-on struct but then my caller function will look funny as I have to change y.b to y->b and the operation may be slower due to the extra step of fetching data in memory.
Allocate extra memory, zero-byte fill it, and set the return value to the struct in that location in memory. (example: return x[nnn]; instead of return x[0];). This approach will use more memory and some processing to zero-byte fill it.
Ultimately, I'm looking for a solution that will be fastest and cleanest (in terms of code) in the long run. If I have to be stuck with using -> to address members of elements then I guess that's the way to go.
Does anyone have a solution that uses the least cpu power?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
long a;
char b;
}ab;
static char dat[500];
ab f2(int set){
ab* x=(ab*)dat;
if (set==2){return NULL;}
if (set==1){
x->a=1;
x->b='1';
x++;
x->a=2;
x->b='2';
x=(ab*)dat;
}
return x[0];
}
int main(){
ab y;
y=f2(1);
printf("%c",y.b);
y.b='D';
y=f2(0);
printf("%c",y.b);
return 0;
}
If you care about speed, it is implementation specific.
Notice that the Linux x86-64 ABI defines that a struct of two (exactly) scalar members (that is, integers, doubles, or pointers, -which all fit in a single machine register- but not struct etc... which are aggregate data) is returned thru two registers (without going thru the stack), and that is quite fast.
BTW
if (set==2){return NULL;} //wrong
is obviously wrong. You could code:
if (set==2) return (aa){0,0};
Also,
ab* x=(ab*)dat; // suspicious
looks suspicious to me (since you return x[0]; later). You are not guaranteed that dat is suitably aligned (e.g. to 8 or 16 bytes), and on some platforms (notably x86-64) if dat is misaligned you are at least losing performance (actually, it is undefined behavior).
BTW, I would suggest to always return with instructions like return (aa){l,c}; (where l is an expression convertible to long and c is an expression convertible to char); this is probably the easiest to read, and will be optimized to load the two return registers.
Of course if you care about performance, for benchmarking purposes, you should enable optimizations (and warnings), e.g. compile with gcc -Wall -Wextra -O2 -march=native if using GCC; on my system (Linux/x86-64 with GCC 5.2) the small function
ab give_both(long x, char y)
{ return (ab){x,y}; }
is compiled (with gcc -O2 -march=native -fverbose-asm -S) into:
.globl give_both
.type give_both, #function
give_both:
.LFB0:
.file 1 "ab.c"
.loc 1 7 0
.cfi_startproc
.LVL0:
.loc 1 7 0
xorl %edx, %edx # D.2139
movq %rdi, %rax # x, x
movb %sil, %dl # y, D.2139
ret
.cfi_endproc
you see that all the code is using registers, and no memory is used at all..
I would use the return value as an error code, and the caller passes in a pointer to his struct such as:
int f2(int set, ab *outAb); // returns -1 if invalid input and 0 otherwise

Heap corruption with function pointer on Solaris 64-bits

I have the following C code on Solaris 5.10 64-bits compiled with CC 5.10 with flags -m64 -KPIC -x04
header.h
typedef struct functions
{
double (* pfComputeGeneric) (myStruct *, myStruct *, double, double *, int);
} functions;
...
double myCompute(myStruct *, myStruct *, double, double *, int);
source.c
double myCompute(myStruct * px1, myStruct *px2, double d1, double *pd1, int i1)
{
// Do stuff with px1
}
...
myStruct *pxStruct = alloc(...);
functions *pxFunctions = alloc(...);
pxFunctions->pfComputeGeneric = myCompute;
...
double dResult += pxFunctions->pfComputeGeneric(pxStruct, pxStruct, 0.0, NULL, 0);
The code in source.c runs fine (nothing weird) until I enter enter into myCompute through function pointer pfCompute, where px1 gets corrupted. I don't know why.
Replacing the call through pfCompute by a direct call to myCompute solves the issue.
Removing the -x04 option also solves the issue.
I had a look at the answer of this question but I'm sure I'm not messing with pointer sizes.
I think it is indeed an issue of -x04. When I look at the assemby call, I see:
...
0x0000000000987eb2: myCaller+0x081a: movq 0xfffffffffffffe28(%rbp),%rcx
0x0000000000987eb9: myCaller+0x0821: movq $0x0000000000000006,%rax
0x0000000000987ec0: myCaller+0x0828: movq 0xfffffffffffffe08(%rbp),%rdi
0x0000000000987ec7: myCaller+0x082f: call *0x0000000000000018(%rdi)
0x0000000000987eca: myCaller+0x0832: addq $0x0000000000000010,%rsp
So the compiler uses %rdi (!) to get the real adress of myCompute from pxFunctions. And in 64-bits, %rdi is used to store the first argument of a function, hence the alteration.

Does struct with a single member have the same performance as a member type?

Does struct with a single member have the same performance as a member type (memory usage and speed)?
Example:
This code is a struct with a single member:
struct my_int
{
int value;
};
is the performance of my_int same as int ?
Agree with #harper overall, but watch out for the following:
A classic difference is seen with a "unstructured" array and an array in a structure.
char s1[1000];
// vs
typedef struct {
char s2[1000];
} s_T;
s_T s3;
When calling functions ...
void f1(char s[1000]);
void f2(s_T s);
void f3(s_T *s);
// Significant performance difference is not expected.
// In both, only an address is passed.
f1(s1);
f1(s3.s2);
// Significant performance difference is expected.
// In the second case, a copy of the entire structure is passed.
// This style of parameter passing is usually frowned upon.
f1(s1);
f2(s3);
// Significant performance difference is not expected.
// In both, only an address is passed.
f1(s1);
f3(&s3);
In some cases, the ABI may have specific rules for returning structures and passing them to functions. For example, given
struct S { int m; };
struct S f(int a, struct S b);
int g(int a, S b);
calling f or g may, for example, pass a in a register, and pass b on the stack. Similarly, calling g may use a register for the return value, whereas calling f may require the caller to set up a location where f will store its result.
The performance differences of this should normally be negligible, but one case where it could make a significant difference is when this difference enables or disables tail recursion.
Suppose g is implemented as int g(int a, struct S b) { return g(a, b).m; }. Now, on an implementation where f's result is returned the same way as g's, this may compile to (actual output from clang)
.file "test.c"
.text
.globl g
.align 16, 0x90
.type g,#function
g: # #g
.cfi_startproc
# BB#0:
jmp f # TAILCALL
.Ltmp0:
.size g, .Ltmp0-g
.cfi_endproc
.section ".note.GNU-stack","",#progbits
However, on other implementations, such a tail call is not possible, so if you want to achieve the same results for a deeply recursive function, you really need to give f and g the same return type or you risk a stack overflow. (I'm aware that tail calls are not mandated.)
This doesn't mean int is faster than S, nor does it mean that S is faster than int, though. The memory use would be similar regardless of whether int or S is used, so long as the same one is consistently used.
If the compiler has any penalty on using structs instead of single variables is strictly compiler and compiler options dependent.
But there are no reasons why the compiler should make any differences when your struct contains only one member. There should be additional code necessary to access the member nor to derefence any pointer to such an struct. If you don't have this oversimplified structure with one member deferencing might cost one addtional CPU instruction depending on the used CPU.
A minimal example w/ GCC 10.2.0 -O3 gives exactly the same output i.e. no overhead introduced by struct:
diff -u0 <(
gcc -S -o /dev/stdout -x c -std=gnu17 -O3 -Wall -Wextra - <<EOF
// Out of the box
void OOTB(int *n){
*n+=999;
}
EOF
) <(
gcc -S -o /dev/stdout -x c -std=gnu17 -O3 -Wall -Wextra - <<EOF
// One member struct
typedef struct { int inq_n; } inq;
void OMST(inq *n){
n->inq_n+=999;
}
EOF
)
--- /dev/fd/63 [...]
+++ /dev/fd/62 [...]
## -4,3 +4,3 ##
- .globl OOTB
- .type OOTB, #function
-OOTB:
+ .globl OMST
+ .type OMST, #function
+OMST:
## -13 +13 ##
- .size OOTB, .-OOTB
+ .size OMST, .-OMST
Not sure about more realistic/complex situations.

Resources