I have a code which looks as shown below. The code here is if the word_size = 64. In similar fashion I need to have for 32 and 16 too. I can't find a way to reuse the same encrypt function for all the sizes. Moreover, I need to declare the variables too according to the word_size, ie. to use either uint_16 or uint_32 or uint_64 depends upon word_size. Can you help me with writing a reusable code in this case?
#include<stdio.h>
#include<stdint.h>
void encrypt(uint64_t* , uint64_t*, uint64_t*);
int main(){
int block_size;
// Get the user inputs
printf("input the block size: \n");
scanf("%d", &block_size); // can be 32, 64 or 128
int word_size = block_size/2; // 16,32 or 64
// Depending on the word_size, I should declare the variables with
// corresponding width
uint64_t plain_text[2] = {0,0};
uint64_t cipher_text[2] = {0,0};
uint64_t key_text[2] = {0,0};
uint64_t * pt, *ct, *k;
encrypt(pt, ct,k);
}
/*
* Ecnryption Method
*/
void encrypt(uint64_t* pt, uint64_t* ct, uint64_t* k){
// Involves bit shifting algorithm which works only on exact sizes i.e eiter 16,32 or 64.
}
I can provide more information if needed.
There is a way to do this in C - by using struct and union
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
enum type {
U64,
U32,
U16,
U8,
};
struct container {
enum type type;
union {
uint64_t u64;
uint32_t u32;
uint16_t u16;
uint8_t u8;
} value;
};
int test(struct container container) {
switch(container.type) {
case U64:
printf("Value is :%" PRIu64 "\n", container.value);
break;
case U32:
printf("Value is :%" PRIu32 "\n", container.value);
break;
case U16:
printf("Value is :%" PRIu16 "\n", container.value);
break;
case U8:
printf("Value is :%" PRIu8 "\n", container.value);
break;
}
return 0;
}
int main(int argc, char **argv) {
struct container c1, c2;
c1.type = U64;
c1.value.u64 = 10000000000ULL;
c2.type = U8;
c2.value.u8 = 100;
test(c1);
test(c2);
return 0;
}
The output produced was:
Value is :10000000000
Value is :100
Related
I have a struct like the following:
struct Foo {
unsigned int id;
unsigned int flag_1 : 1;
unsigned int flag_2 : 1;
unsigned int flag_3 : 1;
// Some arbitrary number of further flags. Code is
// automatically generated and number will vary.
// Notably, it may be more than an int's worth.
int some_data;
float some_more_data;
// ...
};
From time to time, I need to reset all the flags to zero while preserving the rest of the struct. One way is obviously to set each flag to 0 individually, but it feels like there ought to be a way to do it in one fell swoop. Is that possible?
(Note that I am open to not using bit fields, but this is code that will sometimes run on memory-contrained systems, so the memory savings are very appealing.)
Edit:
There is a similar question here: Reset all bits in a c bitfield
However, the struct in that question is entirely bitfields. I cannot simply memset the entire struct to zero here, and the other answer involving unions is not guaranteed to work, especially if there are more than an int's worth of flags.
Just use a separate struct for the flags:
struct Foo_flags {
unsigned int flag_1 : 1;
unsigned int flag_2 : 1;
unsigned int flag_3 : 1;
// ...
};
struct Foo {
unsigned int id;
struct Foo_flags flags;
int some_data;
float some_more_data;
// ...
};
Or even a simpler nested struct:
struct Foo {
unsigned int id;
struct {
unsigned int flag_1 : 1;
unsigned int flag_2 : 1;
unsigned int flag_3 : 1;
// ...
} flags;
int some_data;
float some_more_data;
// ...
};
Then, later in your code:
struct Foo x;
// ...
x.flags.flag_1 = 1;
// ...
memset(&x.flags, 0, sizeof(x.flags));
With some minor adjustments, you can use the offsetof macro to find the beginning and end of the "flag" data within the structure, then use memset to clear the relevant memory. (Note that you cannot use offsetof directly on bitfields, hence the addition of the flag_beg member!)
Here's a working example:
#include <stdio.h>
#include <stddef.h> // defines offsetof
#include <string.h> // declares memset
struct Foo {
unsigned int id;
unsigned int flag_beg; // Could be unsigned char to save space
unsigned int flag_1 : 1;
unsigned int flag_2 : 1;
unsigned int flag_3 : 1;
unsigned int flag_end; // Could be unsigned char to save space
// Some arbitrary number of further flags. Code is
// automatically generated and number will vary.
// Notably, it may be more than an int's worth.
int some_data;
float some_more_data;
// ...
};
#define FBEG (offsetof(struct Foo, flag_beg))
#define FEND (offsetof(struct Foo, flag_end))
int main()
{
struct Foo f;
f.id = 3; f.flag_1 = 1; f.flag_2 = 0; f.flag_3 = 1;
f.some_data = 33; f.some_more_data = 16.2f;
printf("%u %u %u %u %d %f\n", f.id, f.flag_1, f.flag_2, f.flag_3, f.some_data, f.some_more_data);
memset((char*)(&f) + FBEG, 0, FEND - FBEG);
printf("%u %u %u %u %d %f\n", f.id, f.flag_1, f.flag_2, f.flag_3, f.some_data, f.some_more_data);
return 0;
}
Suppose I have the following (made up) definition:
typedef union {
struct {
unsigned int red: 3;
unsigned int grn: 3;
unsigned int blu: 2;
} bits;
uint8_t reg;
} color_t;
I know I can use this to initialize a variable that gets passed to a function, such as :
color_t white = {.red = 0x7, .grn = 0x7, .blu = 0x3};
printf("color is %x\n", white.reg);
... but in standard C, is it possible to instantiate a color_t as an immediate for passing as an argument without assigning it first to a variable?
[I discovered that yes, it's possible, so I'm answering my own question. But I cannot promise that this is portable C.]
Yes, it's possible. And the syntax more or less what you'd expect. Here's a complete example:
#include <stdio.h>
#include <stdint.h>
typedef union {
struct {
unsigned int red: 3;
unsigned int grn: 3;
unsigned int blu: 2;
} bits;
uint8_t reg;
} color_t;
int main() {
// initializing a variable
color_t white = {.bits={.red=0x7, .grn=0x7, .blu=0x3}};
printf("color1 is %x\n", white.reg);
// passing as an immediate argument
printf("color2 is %x\n", (color_t){.bits={.red=0x7, .grn=0x7, .blu=0x3}}.reg);
return 0;
}
In this code contains two structures and their naming is different. Structure member naming is same but type is different. Is there any possibility to change the structure name at run time by using macros or other functionality.
typedef struct STag_ABCRegisters
{
unsigned long aaa;
unsigned long bbb;
unsigned long ccc;
unsigned long dddd;
}RegistersABC;
typedef struct STag_CDERegisters
{
unsigned short aaa;
unsigned short bbb;
unsigned short ccc;
unsigned short dddd;
}RegistersCDE;
main()
{
int type = 1;
if(type == 1)
{
RegistersABC->ccc = 10;
}
else
{
RegistersCDE->ccc = 10;
}
/* after some process again checking the type updating structure*/
type = 2;
if(type == 1)
{
RegistersABC->aaa = 10;
}
else
{
RegistersCDE->aaa = 10;
}
}
I need the help for following process
In the above code contains complexity of if else condition.
So is there any possibilities for select the structure at run time??.
See the below Pseudo code steps for your understanding
main()
{
char type = "ABC";
Registers//type//->aaa = 10; // Type of structure name should be replaced here
}
As I stated in my comment, structures are just the way memory is organized on the machine.
If both structures were compiled by the same compiler on the same machine (architecture / OS), their memory footprint will be the same and you can simply cast their pointer to one to a pointer of the other.
This, however, is not the best way to go about "inheritance" with C.
At the moment, you can have something like this:
struct STag_ABCRegisters
{
unsigned short aaa;
unsigned long bbb;
unsigned short ccc;
unsigned short dddd;
} RegistersABC;
struct STag_CDERegisters
{
unsigned short aaa;
unsigned long bbb;
unsigned short ccc;
unsigned short dddd;
} RegistersCDE;
main()
{
(struct STag_CDERegisters*) pdata = (struct STag_CDERegisters*)&RegistersABC;
data->ccc = 10;
data->aaa = 10;
}
It works, but it isn't beautiful.
If you need two of the same, the correct way would be:
struct STag_Registers
{
unsigned short aaa;
unsigned long bbb;
unsigned short ccc;
unsigned short dddd;
};
struct STag_Registers RegistersABC, RegistersCDE;
main()
{
struct STag_Registers * data = &RegistersABC;
data->ccc = 10;
data->aaa = 10;
}
If you need struct inheritance, then the "trick" is to have the "parent" placed at the head of the struct, so that the memory footprint is aligned.
struct STag_Registers
{
unsigned short aaa;
unsigned long bbb;
unsigned short ccc;
unsigned short dddd;
};
struct STag_RegistersExtended
{
struct STag_Registers parent;
// ... more types
};
This allows a pointer to struct STag_RegistersExtended to be cast as a pointer to struct STag_Registers, so that functions that accept a pointer to struct STag_Registers can also accept a pointer to struct STag_RegistersExtended.
Good luck with C.
EDIT (answering comment)
If you're writing for an embedded system and you have reserved (fixed) memory addresses for the data, you could go with something such as:
typedef struct {
unsigned short aaa;
unsigned long bbb;
unsigned short ccc;
unsigned short dddd;
} register_s;
#define PTR2REG(p) ((register_s *)(p))
#define REG_A PTR2REG(0x1000))
#define REG_B PTR2REG(0x9000))
inline void perform_work(register_s * reg)
{
reg->ccc = 10;
// ...
reg->aaa = 10;
}
main()
{
perform_work(REG_A);
perform_work(REG_B);
if(REG_A->aaa == 10) // should be true
printf("work was performed");
}
You should note that struct have a memory alignment and packing order. The compiler will add padding to the struct you defined in the question, due to the long's memory alignment requirements. You can read more about struct packing here.
If your embedded system requires an exact bit / byte match (and is free from padding requirements), you should tell the complier not to add any padding. This is often done using #pragma pack
EDIT 2
I'm not sure where the type in your question is derived from... but if you have a global variable with the address for the struct, you could go with:
typedef struct {
unsigned short aaa;
unsigned long bbb;
unsigned short ccc;
unsigned short dddd;
} register_s;
#define PTR2REG(p) ((register_s *)(p))
#define REG_A PTR2REG(0x1000))
#define REG_B PTR2REG(0x9000))
register_s * active_register = REG_A;
inline void perform_work(void)
{
active_register->ccc = 10;
// ... active_register might change
active_register->aaa = 10;
}
main()
{
perform_work();
}
This is from a C++ perspective, you really should be more careful with those language tags if this is not what you want
Since C++ does not have reflection, it's not possible to do what you want at runtime. There are workarounds though.
For example one workaround could be to have a common base-class for the common elements (which in your simple example seems to be all). The you could have an unordered map translating strings to pointers to your structure.
Example:
struct CommonBase
{
unsigned short aaa;
unsigned long bbb;
unsigned short ccc;
unsigned short dddd;
};
struct ABC : CommonBase {};
struct DEF : CommonBase {};
int main()
{
std::unordered_map<std::string, std::unique_ptr<CommonBase>> items = {
{ "ABC", new ABC },
{ "DEF", new DEF }
};
std::cout << "Select item to modify (ABC or DEF): ";
std::string input;
std::cin >> input;
items[input]->aaa = 12;
}
For members that are not common, that are unique for each respective structure, then you need to actually check like you do now and then downcast the pointer to the correct type.
For a C solution there is none really, except to manually check like you do now.
Dynamic languages like python have buildin metadata table for reflection, so we just build one for help. Now it looks much like a script language.
_Generic need C11 std to work.
some code copied from How to save the result of typeof?
// some code copied from https://stackoverflow.com/questions/42222379/how-to-save-the-result-of-typeof
// gcc -std=c11 typeid_of_test.c
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
typedef struct STRU
{
int32_t aaa;
double bbb;
int ccc;
char dddd;
}STRU;
typedef struct Metainfo
{
int type;
char* name; //or hash
int offset;
}Metainfo;
enum {TYPE_UNKNOWN, TYPE_INT, TYPE_CHAR, TYPE_DOUBLE};
#define typeid_of(T) _Generic((T), int: TYPE_INT, long: TYPE_INT, char: TYPE_CHAR, double: TYPE_DOUBLE, default: 0)
#define META(ST_, M_) {typeid_of((__typeof__(((ST_ *)0)->M_))0), #ST_ "." #M_, offsetof(ST_, M_)}
/* { typeid, name, offset } */
Metainfo meta[]={
META(STRU, aaa),
META(STRU, bbb),
META(STRU, ccc),
META(STRU, dddd),
};
int set_by_name(char* member_name, char* value, void* p)
{
int offset=0, type=0;
for(int i=0; i<sizeof(meta)/sizeof(Metainfo); i++)
if(stricmp(member_name, meta[i].name)==0)
{
offset=meta[i].offset;
type = meta[i].type;
}
switch(type)
{
case TYPE_INT:
*(int*)((char*)p+offset) = atoi(value);
break;
case TYPE_CHAR:
*(char*)((char*)p+offset) = atoi(value);
break;
case TYPE_DOUBLE:
*(double*)((char*)p+offset) = atof(value);
break;
default:
return 0;
}
return 1;
}
int main(void)
{
for(int i=0; i<sizeof(meta)/sizeof(Metainfo); i++)
printf("type:%d, name: %s, offset: %d\n", meta[i].type, meta[i].name, meta[i].offset);
STRU b={0};
set_by_name("stru.bbb", "3.1415926", &b);
printf("stru.bbb == %f", b.bbb);
return 0;
}
I want to basically process a struct array in a method in a dynamic library, but when I pass the array and print it (in the exact same manner as in my main program) it has different values.
Consider a struct like this:
struct color {
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
}
And the code to print it looks like this:
printf("pos: %p\n", array);
for (i = 0; i < size; i++) {
printf("bgra: %08x\n", ((uint32_t *) array)[i]);
}
Now, what I'm doing in the test program is this:
printf("Table:\n");
print(table, size);
and the output looks like this (as excepted):
pos: 0x7fff5b359530
bgra: 00000000
bgra: ff0000ff
bgra: ff00ffff
But when i execute the same code in a function in the library this is what i get:
pos: 0x7fff5b359530
bgra: 00000008
bgra: 00000030
bgra: 5b3598e0
Now I'm wondering what I'm doing wrong, since i can't see a fault in my code. Also, the values must correlate somehow since, the output is always the same (Except for the address of course).
header.h
#include <stdint.h>
#ifndef __HEADER_H_
#define __HEADER_H_
struct bmpt_color_bgra {
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
};
void print(struct bmpt_color_bgra *table, uint8_t size);
uint8_t *gen(struct bmpt_color_bgra *table, uint8_t size);
#endif
library.c
#include <stdlib.h>
#include <stdio.h>
#include "header.h"
#define EXPORT __attribute__((visibility("default")))
__attribute__((constructor))
static void initializer(void) {
printf("[%s] initializer()\n", __FILE__);
}
__attribute__((destructor))
static void finalizer(void) {
printf("[%s] finalizer()\n", __FILE__);
}
EXPORT
void print(struct bmpt_color_bgra *table, uint8_t size) {
uint8_t i;
printf("pos: %p\n", table);
for (i = 0; i < size; i++) {
printf("bgra: %08x\n", ((uint32_t *) table)[i]);
}
}
EXPORT
uint8_t *gen(struct bmpt_color_bgra *table, uint8_t size) {
printf("table in func:\n");
print(table, size);
}
test.c
#include <stdio.h>
#include <stdlib.h>
#include "header.h"
int main(int argc, char **argv) {
struct bmpt_color_bgra arr[3];
struct bmpt_color_bgra c;
c.b = 0x0;
c.g = 0x0;
c.r = 0x0;
c.a = 0x0;
arr[0] = c;
c.b = 0xff;
c.a = 0xff;
arr[1] = c;
c.r = 0xff;
arr[2] = c;
//the first result (the correct one)
print(arr, 3);
//the second result
gen(arr, 3);
}
This probably comes down to memory alignment of the members within the struct, and the size of the struct itself differing between your program and the dynamic/shared library. You don't mention which compiler you are using, but using different compiler(s) or compiler options for your program and the shared library could cause this effect.
You can preserve binary compatibility between modules by specifying exactly how the members of the struct should be aligned. E.g in GCC you can force how the struct is represented in memory by use of an attribute.
See https://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/Type-Attributes.html for GCC alignment instructions
struct bmpt_color_bgra {
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
} __attribute__ ((packed));
Also take a look at Byte Alignment for integer (or other) types in a uint8_t array for a similar question.
I am not receiving anything in buffer. Wherever I printf my buffer, it is always empty or shows garbage value. Can anyone help?
I defined header, packet and called them in my main, but buffer still shows garbage.
#include <stdint.h>
struct header {
uint16_t f1;
uint16_t f2;
uint32_t f3;
};
struct data {
uint16_t pf1;
uint64_t pf2;
};
#include <arpa/inet.h>
#include <string.h>
#include <stdint.h>
#include "packet.h"
void htonHeader(struct header h, char buffer[8]) {
uint16_t u16;
uint32_t u32;
u16 = htons(h.f1);
memcpy(buffer+0, &u16, 2);
printf("Value of buff is: %hu\n",buffer);
u16 = htons(h.f2);
memcpy(buffer+2, &u16, 2);
u32 = htonl(h.f3);
memcpy(buffer+4, &u32, 4);
}
void htonData(struct data d, char buffer[10]) {
uint16_t u16;
uint32_t u32;
u16 = htons(d.pf1);
memcpy(buffer+0, &u16, 2);
u32 = htonl(d.pf2>>32);
memcpy(buffer+2, &u32, 4);
u32 = htonl(d.pf2);
memcpy(buffer+6,&u32, 4);
}
void HeaderData(struct header h, struct data d, char buffer[18]) {
htonHeader(h, buffer+0);
htonData(d, buffer+8);
printf("buff is: %s\n",buffer);
}
#include <stdio.h>
#include "packet.c"
#include <string.h>
#include<stdlib.h>
int main(){
struct header h;
struct data d;
char buff[18];
//printf("Packet is: %s\n",buff);
printf("Generating Packets..... \n");
h.f1=1;
d.pf1=2;
h.f2=3;
d.pf2=4;
h.f3=5;
HeaderData(h,d,buff);
strcat(buff,buff+8);
printf("Packet is: %s\n",buff);
return 0;
}
The problem is that your printf()s are either syntactically wrong (printf( "%hu", ... ); expects an unsigned short as parameter, but you pass a pointer) or you try to print buff by using "%s" but the content is binary, not text. What you could do instead was doing some kind of hexdump, like:
int i;
for( i=0; i<sizeof( buff ); i++ ) {
printf( "%x ", buff[i] & 0xff );
}
puts( "" ); // terminate the line
Please note, that using sizeof works im main() only, in the other function you've got to determine the buffer size differently.
Besides: because of the binary content of buff, you can't use strcat(). Even if you have made sure that there is a '\0' behind the last value you have copied (I haven't checked if you have), depending on the integer values you copy, there may be another '\0' value before that one and strcat() would overwrite everything form that point on.