For my educational purposes I was wondering if there is an alternative way with memcpy() to the following code for the function address casting to an array of chars?
#include <stdio.h>
#include <string.h>
typedef void (*_vfp)(void);
#define FPSZ sizeof(_vfp)
union rcast {
_vfp fp;
char fp_c[FPSZ];
} rc;
void a(void){
printf("a()\n");
}
int main(int argc, char **argv)
{
int i=0;
memset(&rc,0,FPSZ);
rc.fp=a;
for (i=0;i<FPSZ;++i)
printf("%hhx ",rc.fp_c[FPSZ-i-1]);
puts("");
printf("%p\n",a);
return 0;
}
Thanks.
Minimally modifying your code:
#include <stdio.h>
#include <string.h>
typedef void (*_vfp)(void);
#define FPSZ sizeof(_vfp)
void a(void){
printf("a()\n");
}
int main(int argc, char **argv)
{
int i=0;
_vfp fp = a;
char fp_c[FPSZ];
memcpy(fp_c, &fp, FPSZ);
for (i=0;i<FPSZ;++i)
printf("%hhx ",fp_c[FPSZ-i-1]);
puts("");
printf("%p\n",a);
return 0;
}
EDIT: In response to comment, here's a version without a proxy and without memcpy
#include <stdio.h>
#include <stdint.h>
#include <limits.h>
#include <string.h>
typedef void (*_vfp)(void);
#define FPSZ sizeof(_vfp)
void a(void){
printf("a()\n");
}
int main(int argc, char **argv)
{
int i=0;
char fp_c[FPSZ];
for (i=0;i<FPSZ;++i)
fp_c[i] = (char) (((uintptr_t) &a) >> CHAR_BIT * i);
for (i=0;i<FPSZ;++i)
printf("%hhx ",fp_c[FPSZ-i-1]);
puts("");
printf("%p\n",a);
return 0;
}
For my educational purposes I was wondering if there is an alternative way with memcpy() to the following code for the function address casting to an array of chars?
Note well: though arrays and pointers are closely associated, they are very different things. Among many other differences, you can use pointer types in cast operators, and pointers as cast operands, but you cannot use array types or arrays in those contexts.
You seem to say that what you want is a char array containing the bytes of the function pointer's value (as opposed to the bytes of whatever the pointer points to). You can get that, or something like it, several ways. The simplest way is to create a char * to the pointer's value. Again, that's not an array, but it can be used in many of the same ways that an array could be used:
typedef void (*_vfp)(void);
int main(int argc, char **argv)
{
int i;
_vfp fp = a;
char *cp = &fp;
for (i = 0; i < sizeof(fp); ++i) {
printf("%hhx ", cp[i]);
}
printf("\n%p\n", (void *) a);
return 0;
}
Do note, however, that the above code exhibits undefined behavior. The %p field descriptor tells printf() that the corresponding argument is an object pointer. C draws a distinction between object pointers and function pointers, and does not define any behavior for converting between values of those two type families. I include a cast explicitly expressing such a conversion (which may enable the compiler to notice and complain); your code results in such a conversion being performed implicitly.
If you want a separate array object containing the bytes of the pointer's value (as opposed to the pointed-to function's), then you can get it in a similar way:
int main(int argc, char **argv)
{
_vfp fp = a;
char array[sizeof(fp)];
memcpy(array, &fp, sizeof(array));
/* ... */
}
That one uses memcpy(), exactly as you asked.
In any event, there is no need for a union. In fact, although your union-based approach might happen to work with your C implementation, reading from a different union member than was most recently written to formally exhibits undefined behavior.
What you are doing is formally Undefined Behaviour. C language says that an union can contain any of different variables, but you shall only access the variable that was set in the union : The size of a union is sufficient to contain the largest of its members. The value of at
most one of the members can be stored in a union object at any time. (ref : C Language Specification Draft - 6.7.2.1 Structure and union specifiers - 16)
So it is neither best nor worse than doing pointer casting via void :
intptr_t ip = (intptr_t) &a;
char *fp_c = (void *) &intptr_t;
or with memcpy :
char fp_c[FPSZ];
intptr_t ip = (intptr_t) &a;
memcpy(fp_c, &ip, sizeof(intptr_t));
All will give you same result in :
for (i=0; i<FPSZ; i++) {
printf("%hhx ",fp_c[FPSZ-i-1]);
}
fputs("\n");
Related
Does C have anything similar to C++ where one can place structs in an unsigned char buffer as is done in C++ as shown in the standard sec. 6.7.2
template<typename ...T>
struct AlignedUnion {
alignas(T...) unsigned char data[max(sizeof(T)...)];
};
int f() {
AlignedUnion<int, char> au;
int *p = new (au.data) int; // OK, au.data provides storage
char *c = new (au.data) char(); // OK, ends lifetime of *p
char *d = new (au.data + 1) char();
return *c + *d; // OK
}
In C I can certainly memcpy a struct of things(or int as shown above) into an unsigned char buffer, but then using a pointer to this struct one runs into strict aliasing violations; the buffer has different declared type.
So suppose one would want to replicate the second line in f the C++ above in C. One would do something like this
#include<string.h>
#include<stdio.h>
struct Buffer {
unsigned char data[sizeof(int)];
};
int main()
{
struct Buffer b;
int n = 5;
int* p = memcpy(&b.data,&n,sizeof(int));
printf("%d",*p); // aliasing violation here as unsigned char is accessed as int
return 0;
}
Unions are often suggested i.e. union Buffer {int i;unsigned char b[sizeof(int)]}; but this is not quite as nice if the aim of the buffer is to act as storage (i.e. placing different sized types in there, by advancing a pointer into the buffer to the free part + potenially some more for proper alignment).
Have you tried using a union?
#include <string.h>
#include <stdio.h>
union Buffer {
int int_;
double double_;
long double long_double_;
unsigned char data[1];
};
int main() {
union Buffer b;
int n = 5;
int *p = memcpy(&b.data, &n, sizeof(int));
printf("%d", *p); // aliasing violation here as unsigned char is accessed as int
return 0;
}
The Buffer aligns data member according the type with the greatest alignment requirement.
Yes, because of strict aliasing rule it is just not possible. As it is not possible to write a standard compliant malloc().
Your buffer is not aligned - alignas(int) from stdalign.h needs to be added.
If you want to protect against compiler optimizations, either:
just cast the pointer and access it and compile with -fno-strict-aliasing, or use volatile
or move the accessor to the buffer to another file that is compiled without LTO so that compiler just is not able to optimize it.
// mybuffer.c
#include <stdalign.h>
alignas(int) unsigned char buffer[sizeof(int)];
void *getbuffer() { return buffer; }
// main.c
#include <string.h>
#include <stdio.h>
#include "mybuffer.h"
int main() {
void *data = getbuffer();
// int *p = new (au.data) int; // OK, au.data provides storage
int *p = data;
// char *c = new (au.data) char(); // OK, ends lifetime of *p
char *c = data;
*c = 0;
// char *d = new (au.data + 1) char();
char *d = (char*)data + 1;
*d = 0;
return *c + *d;
}
The way the definition of Effective Type in 6.5p6 is written, it's unclear what it's supposed to mean in all corner cases--likely because there was never a consensus among Committee Members as to how all corner cases should be handled. Defect reports often add more confusion than clarity, since they use terms like the "active member" of a union when neither the Standard nor the defect reports specify what actions would set or change it.
If one wants to use an object of static or automatic duration as though it were a buffer without a declared type, a safe way of doing that should be to do something like the following:
void volatile *volatile dummy_vp;
void test(void)
{
union {
char dat[1000];
unsigned long force_alignment;
} buffer;
void *volatile launder = buffer.dat;
dummy_vp = &launder;
void *storage_blob = launder;
...
}
Unless an implementation goes out of its way to test whether the read of
launder happened to yield an address matching buffer.dat, it would have no way of knowing whether the object at that address had a declared type. Nothing in the Standard would forbid an implementation from behaving nonsensically if the address happened to match that of buffer.dat, but situations where performance improvements would justify the cost of the check aren't likely to be common enough for compilers to attempt such "optimization".
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_BUFFER_SIZE 100
typedef struct config_struct config_t ;
struct config_struct{
char name[20];
char ip[20];
int port;
char log[100];
};
int main(int argc, char *argv[]) {
config_t config;
read_config_file(argv[1], &config);
return 0;
}
int read_int_from_config_line(char* config_line) {
int val = atoi(config_line);
return val;
}
void read_str_from_config_line(char* config_line, char* val) {
strncpy(val,config_line, MAX_BUFFER_SIZE);
}
void read_config_file(char* config_filename, config_t *config) {
FILE *fp;
char *value, buffer[MAX_BUFFER_SIZE];
fp = fopen("./settings.conf", "r");
while (fgets(buffer, MAX_BUFFER_SIZE, fp) != NULL) {
if(!strcmp(buffer,"NAME")) {
read_str_from_config_line(value, &(config->name));
}
if(!strcmp(buffer,"PORT")) {
&(config->port) = read_int_from_config_line(value);
}
}
}
I try to compile this code and it gives me a incompatible pointer type at read_str_from_config_line(value , &(config->name)); and lvalue required as left operand of assignment &(config->port) = read_int_from_config_line(value);
I am trying to return the stuct back to the main program but I'm having problem with the struct pointers.
Any solution for it to be solve?
PS: The code is a mess as I trying to shorten it. Any help will be good as I am still a beginner to C programming.
Thanks
The & operator means "take the address of the object to the right".
This:
&(config->port)
means "take the address of the port member of the structure pointed to by config.
You don't want to take the address, you just want to assign to the member. That's just:
config->port = ...
This is the same as (*config).port, but nobody writes it like that since the arrow operator is so convenient.
read_str_from_config_line(value, &(config->name));
confg->name is declared as a char array, which naturally decays to a pointer to the first element (of type "pointer-to-char") if you omit the &:
read_str_from_config_line(value, config->name);
Taking its address explicitly instead results in a pointer of type pointer-to-array-of-20-chars, which is not the same type as pointer-to-char - which is why you are getting an error. This is a common source of confusion in C; in general, you should not take the address of an array (although it does have legitimate use cases).
In this line:
&(config->port) = read_int_from_config_line(value);
You are taking the address of the port member of the structure pointed at by config, which is a non-lvalue pointer. It looks like you are actually trying to assign to the member, so the line should read:
config->port = read_int_from_config_line(value);
I'm a beginning programmer who is confused with passing a two dimensional array to a function. I think it may just be a simple syntax problem. I've looked for an answer, but nothing I've found seems to help, or is too far above my level for me to understand.
I identify the array and the function in the main function as, and after initializing it, attempt to call it:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int const ROWS = 8;
int const COLS = 8;
int main(int argc, char** argv) {
char board[ROWS][COLS];
bool canReach(char board[][], int i, int j);
//initialize array
//values of i and j given in a for loop
canReach(board, i, j);
return (EXIT_SUCCESS);
}
While writing the function outside the main function, I defined it exactly the same as I did in the main function.
bool canReach(char board[][], int i, int j){
//Functions purpose
}
When I attempt to build the program, I'm given this error twice and the program does not build:
error: array has incomplete element type 'char[][]'
bool canReach(char board[][], int i, int j)
^
Please note that I'm trying to pass the entire array to the function, and not just a single value. What can I do to fix this problem? I would appreciate it if it didn't have to use pointers, as I find them quite confusing. Also, I've tried to leave out things that I thought weren't important, but I may have missed something I needed, or kept in things I didn't. Thank you for your time in helping out this starting programmer!
You can just pass arrays as function arguments with definition of their size.
bool canReach(char board[ROWS][COLS], int i, int j);
When the size is unknown, pointers are the way.
bool canReach(char* board, int i, int j);
You should know, that arrays != pointers but pointers can storage the address of an array.
Here is a demonstrative program
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
bool canReach( int n, int m, char board[][m] )
{
for ( int i = 0; i < n; i++ )
{
for ( int j = 0; j < m; j++ )
{
board[i][j] = 0;
}
}
return printf( "Hello SaarthakSaxena" );
}
int main( void )
{
const int ROWS = 8;
const int COLS = 8;
char board[ROWS][COLS];
canReach( ROWS, COLS, board );
return EXIT_SUCCESS;
}
Its output is
Hello SaarthakSaxena
Defining a function inside another function (here: main) is not allowed in C. That is an extension of some compilers (e.g. gcc), but should not be used.
You have to specify the dimension of the array. C arrays do not have implicit size information as in HLL.
It also is not a good idea to use const variables for array dimensions in C. Instead
#define ROWS 8
#define COLS 8
Assuming i and j are the indexes of an element in the array, you can use the signature:
bool canReach(size_t rows, size_t cols, char board[rows][cols],
size_t i, size_t j);
This allows to pass arrays of (run-time) variable size to the function. If the dimensions are guaranteed fixed at run-time:
bool canReach(char board[ROWS][COLS], size_t i, size_t j);
But only if using the macros above. It does not work with the const variables.
Both versions tell the compiler which dimension the array has, so it can calculate the address of each element. The first dimension might be omitted, but there is nothing gained and it would imhibit optional bounds checking (C11 option). Note the 1D-case char ca[] is just a special version of this general requirement you can always omit the left(/outer)most dimension.
Note I changed the types to the (unsigned) size_t as that is the appropriate type for array-indexing and will generate a conversion warning if properly enabled (strongly recommended). However, you can use int, but have to ensure no value becomes negative.
Hint: If you intend to store non-character integers in the array or do arithmetic on the elements, you should specify the signed-ness of the char types. char as such can be either unsigned or signed, depending on implementation. So use unsigned char or signed char, depending what you want.
Below I have to examples of code that do the same thing and give the same output. In the first, I use pointer to pointer argument passing to eliminate the use of ans as a global. In the second, I madeans a global which eliminated the additional uses of * when dealing with pointer to pointer:
Example 1:
// pointer to pointer
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
unsigned char serial[] = {
0x1,0x2,0x3,0x4
};
void checkSerial(unsigned char* buf, unsigned char ** ans)
{
int i;
unsigned char *part;
part = 0;
i=2;
part = &buf[i];
*ans = (unsigned char*)malloc(2);
memset(*ans,0,2);
memcpy(*ans,part,2);
printf("0x%x\n",**ans);
++(*ans);
printf("0x%x\n",**ans);
}
int main(void)
{
unsigned char *ans, *buf;
while(1)
{
buf = malloc(4);
memset(buf,0,4);
memcpy(buf, serial, sizeof(serial));
checkSerial(buf, &ans);
--ans;
printf("the value is 0x%x\n", *ans);
free(buf);
free(ans);
sleep(3);
}
return 0;
}
Example 2:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
unsigned char serial[] = {
0x1,0x2,0x3,0x4
};
unsigned char ans[2];
void checkSerial(unsigned char* buf)
{
int i;
unsigned char *part;
part = 0;
i=2;
part = &buf[i];
int j;
for(j=0;j<2;j++)
{
ans[j] = part[j];
}
printf("0x%x\n",*ans);
++(*ans);
printf("0x%x\n",*ans);
}
int main(void)
{
unsigned char *buf;
while(1)
{
buf = malloc(4);
memset(buf,0,4);
memcpy(buf, serial, sizeof(serial));
checkSerial(buf);
printf("the value is 0x%x\n", *ans);
free(buf);
sleep(3);
}
return 0;
}
Which technique is preferred in C?
Avoid global variables when it is not necessary. Going with first example is preferable.
Global variables are easily accessible by every functions, they can be read or modified by any part of the program, making it difficult to remember or reason about every possible use.
Keep variables as close to the scope they are being used in as possible. This prevents unexpected values for your variables and potential naming issues.
I personally don't like defining global variable where there is ways to avoid it.
But some guys say that, the concept of pointer is very much confusing. I don't feel that though..
My advice, if you get confuse with pointers try to avoid it with defining global variable. Otherwise, use pointers... :)
TL;DR: Solutions 1 and 2 are both bad.
The way you wrote the example makes malloc useless since you know the size of ans and buf at compile-time, if those are really known at compile-time then , just don't use malloc at all, declare variables on the stack. In C, generally avoid dynamic memory allocation as much as possible and prefer to create buffers which can hold the maximum size a buffer can have in your application. That avoids this kind of problems in the first place. The way you wrote the example makes malloc useless since you know the size of ans and buf at compile-time. The only place where dynamic memory allocation can be useful is for buffers whose sizes are unknown at compile-time, but you can still avoid it (see below). If buf is an incoming message, and ans the answer to this message, the size of ans can be unknown at compile-time, at least if you use variable-length messages.
Your version 2 is not working and can not work! First you declared ans to be an array of size 1 and iterate over it until index 2(now you edited that). Second to declare the array ans as global you would need to know its size at compile-time, and then of course if you knew its size at compile-time you would just declare the array ans in the function checkSerial. Moreover, when you declare a variable which is used by several functions in C don't forget to declare it static, otherwise it can be accessed from all files in your project.
A solution avoiding dynamic allocation, notice you avoid the disadvantages of your 2 solutions: the pointer to pointer and the global variable, and moreover your program can not leak since you don't use dynamic allocation:
enum {MSG_MAX_SIZE = 256 };
typedef struct message {
uint8_t payload[MSG_MAX_SIZE];
size_t msg_size;
} message_t;
void checkSerial(const message_t *buf, message_t *ans)
{
//parse buf and determine size of answer
...
...
//fill answer payload
ans->msg_size = buf[42];
}
int main(void)
{
while (1) {
message_t buf;
getMsg(&buf);
message_t ans;
checkSerial(&buf, &ans);
}
}
I happen to have several functions which access different arguments of the program through the argv[] array. Right now, those functions are nested inside the main() function because of a language extension the compiler provides to allow such structures.
I would like to get rid of the nested functions so that interoperability is possible without depending on a language extension.
First of all I thought of an array pointer which I would point to argv[] once the program starts, this variable would be outside of the main() function and declared before the functions so that it could be used by them.
So I declared such a pointer as follows:
char *(*name)[];
Which should be a pointer to an array of pointers to characters. However, when I try to point it to argv[] I get a warning on an assignment from an incompatible pointer type:
name = &argv;
What could be the problem? Do you think of another way to access the argv[] array from outside the main() function?
char ** name;
...
name = argv;
will do the trick :)
you see char *(*name) [] is a pointer to array of pointers to char. Whereas your function argument argv has type pointer to pointer to char, and therefore &argv has type pointer to pointer to pointer to char. Why? Because when you declare a function to take an array it is the same for the compiler as a function taking a pointer. That is,
void f(char* a[]);
void f(char** a);
void f(char* a[4]);
are absolutely identical equivalent declarations. Not that an array is a pointer, but as a function argument it is
HTH
This should work,
char **global_argv;
int f(){
printf("%s\n", global_argv[0]);
}
int main(int argc, char *argv[]){
global_argv = argv;
f();
}
#include <stdio.h>
int foo(int pArgc, char **pArgv);
int foo(int pArgc, char **pArgv) {
int argIdx;
/* do stuff with pArgv[] elements, e.g. */
for (argIdx = 0; argIdx < pArgc; argIdx++)
fprintf(stderr, "%s\n", pArgv[argIdx]);
return 0;
}
int main(int argc, char **argv) {
foo(argc, argv);
}