I would like to perform a bitwise OR operation on two memory locations pointed by pointers and store it an char array.
I am struck on performing OR operation on two memory locations and later assign them to char array.
void perform_or_operations ( struct storage *a, struct storage *b )
{
char array[0x1000]; // size of array is bigger than struct storage
// Perform OR operation
array = a | b ???
}
Any suggestions ?
It appears that you want to operate on the representations of the two structures. You really ought to use unsigned char instead of char for that, but it's quite possible either way. A pointer to any object type may be converted to a pointer to a character type, and the resulting pointer may be used to access the representation of the pointed-to object. However, you absolutely need to dereference such pointers -- your code attempts to operate on the pointers themselves.
Moreover, there is no whole-array assignment in C. If I understand correctly what you want to do then you'll need to perform the bitwise or on each byte of the representation independently.
Finally, you may find it to your advantage to zero out the array, so that those bytes that don't correspond the the representation of a struct storage have consistent values.
Example:
void perform_or_operations ( struct storage *a, struct storage *b ) {
unsigned char array[0x1000] = { 0 };
unsigned char *a_bytes = (unsigned char *) a;
unsigned char *b_bytes = (unsigned char *) b;
for (size_t i = 0; i < sizeof(*a); i++) {
array[i] = a_bytes[i] | b_bytes[i];
}
}
Substitute char for unsigned char (everywhere) if you really need to work with that type.
Assuming you want an OR of the bytes that make up the structs that a and b point to, you would do the following:
char *ap = (char *)a;
char *bp = (char *)b;
size_t i;
for (i=0; i<sizeof(struct storage); i++) {
array[i] = ap[i] | bp[i];
}
The first two lines create character pointers to each struct that can be used to access the bytes of each. Then you OR the corresponding bytes;
This is what you want.
You want to cast a and b to (char*), and using temporary variables ap, bp saves cluttering the code with casts. then you dereference (*) the ap and bp pointers (or use/interpret them as array).
void perform_or_operations ( struct storage *a, struct storage *b )
{
char array[0x1000]; // size of array is bigger than struct storage
size_t size = sizeof(struct storage);
if( size > 0x1000 ) size = 0x1000; //guardrail
unsigned char *ap, *bp;
ap = (unsigned char*)a;
bp = (unsigned char*)b;
for( size_t ndx=0; ndx<size; ndx++ ) {
//perform OR operation
array[ndx] = *ap++ | *bp++;
//or this way - which do you prefer?
array[ndx] = ap[ndx] | bp[ndx];
}
}
Related
I'm trying to get struct's address.
I want to get address in an int *, and I want to change address by adding numbers to the int *. I tried several ways, but I can't solve it.
struct num_d {
unsigned char data;
unsigned char pad1;
unsigned char pad2;
unsigned char pad3;
};
struct num_d **m = malloc(sizeof(struct num_d *) * row);
for (int i = 0; i < row; i++)
{
m[i] = malloc(sizeof(struct num_d) * col);
}
How can I get m[0][0]'s address in an int *?
first things first lets typedef your struct, so we can type less and be more clear:
typedef struct num_d num_d;
void pointer
A pointer to void is a "generic" pointer type. A void * can be converted to any other pointer type without an explicit cast. we cannot de-reference a void * or do pointer arithmetic with it; you must convert it to a complete data type pointer first (like int* e.g.) then do the de-refrence or the pointer arithmetic.
Now, malloc() return a void* which points to the allocated heap buffer (if malloc successed in allocation other wise null is the return value).
you code become:
num_d** m = malloc(sizeof(num_d*) * row); /*m is an array of void* pointers (not initialized)*/
for (int i = 0; i < row; i++)
{
m[i] = malloc(sizeof(num_d) * col); /*in each element in m you have a void* that points to struct num_d on the heap*/
}
the sizeof(void*) is the same as sizeof any pointer (except function pointers in some machines/os).
putting it all together
How can I get m[0][0]'s address in an int *?
This is a wrong question! because m is an array of void* to "num_d structs" (holding the num_d heap address).
if you want the start address of the i-th num_d struct in the array m, then, just return the void* in the index i in this array m[i]. and if you want to cast it just cast it (no need actually) just assign it:
int* ptr = m[i];
Take in mind that compilers will warn you, regarding the assignment above (but this assignment is supported and legal) :
warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
or (no need again):
int* ptr = (int*)m[i];
I don't know why you need such behavior, it makes more sense to cast to num_d*
if you want the address of the first data member in the struct num_d, then you must cast to the appropriate data type to get the expected data:
unsigned char data = ((num_d*)m[i])->data;
unsigned char* p_data = &((num_d*)m[i])->data;
You don't need to have the address in an int* in order to be adding to it. The way that [] works, is that it adds to the pointer and dereferences.
You can just add to *(m[0] + 1) to get the second element.
How about:
int *ptr = (int *) m[0];
I am new to C. I need to allocate memory and store pointers in it. These pointers are of type char. So what is the type of the pointer to that memory? char? or long because addresses are just numbers?
Assuming I understand what you’re asking for, it sounds like this is what you want:
#define N 10 // or however many elements you want
...
char **arr = malloc( sizeof *arr * N ); // sizeof *arr == sizeof (char *)
Each arr[i] will have type char *.
If you want an array of char, then it would be
char *arr = malloc( sizeof *arr * N );
and each arr[i] will have type char.
So, general rule, if you want to allocate an array of type T, use
T *arr = malloc( sizeof *arr * N );
The type is char**, pointer to pointer to char, aka double pointer to char.
Note that you wouldn't need to manually allocate space for the pointers if you don't want to.
Take the code:
#define POINTER_N 10
//...
char *ptr[POINTER_N]; //array of 10 pointers to char
This already reserves space for these 10 pointers, their size is the size of a pointer to char, this size deppends on your system, for a 64 bit system the pointers are 8 bytes, for a 32 bit one it's 4 bytes, this is generic, there can be differences in these values depending on the implementation.
Already having the pointer you only will then need to allocate space for the strings themselves, so for 20 char strings initialized to \0 you would do:
#include <stdlib.h>
#define STRING_SIZE 21
//...
for(size_t i = 0; i < POINTER_N; i++){
ptr[i] = calloc(STRING_SIZE, sizeof *ptr[0]); //21 char long string
This would suffice, note that I'm reserving one extra character for the null terminator.
If you really want to allocate the space for these pointers yourself you would declare a double pointer, and allocate space for the numbers of pointers to char you need:
char **ptr = calloc(POINTER_N, sizeof *ptr); // 10 pointers to pointers to char
And for the strings:
for(size_t i = 0; i < POINTER_N; i++){
ptr[i] = calloc(STRING_SIZE, sizeof **ptr);
pointers have a type of the pointer to the referenced object. It does not matter how the memory was allocated.
examples
void *ptr = malloc(10); // pointer to void
int c;
void *ptr = &c; //pointer to void
int *ptr = malloc(sizeof(*ptr); // pointer to integer
int *ptr = &c; // pointer to integer
char *cp = malloc(100); // pointer to char
strcpy(cp, "Hello");
void foo(double *x) // x is a pointer to double.
{
/* .... */
}
double **p; //pointer to pointer to double
/* etc etc */
I had a bit of a confusion. Below is a very simple example which works:
#include <stdlib.h>
typedef struct
{
unsigned char one: 1;
unsigned char two:1;
unsigned char three: 1;
unsigned char four: 1;
} nibble_bits;
typedef union
{
unsigned char all : 4;
nibble_bits bits;
} nibble;
void initArr(nibble ** arrLoc, unsigned int size)
{
nibble * start = arrLoc[0];
int i =0;
for (i=0; i<size; i++)
{
start[i].all = 0;
}
}
int main()
{
nibble * fourNibbles = (nibble *) malloc(4 * sizeof(nibble));
initArr(&fourNibbles,4);
}
This compiles fine with no warnings. However, when I change the first line in main:
nibble * fourNibbles = (nibble *) malloc(4 * sizeof(nibble));
to:
nibble fourNibbles[4];
I get the following:
warning: main.c: In function ‘main’:
main.c:150: warning: passing argument 1 of ‘initArr’ from incompatible pointer type
Upon running, I get a "Bus error 10".
Seems to me like the lines are doing the same thing, except that the malloc is allocating space for the array on the heap and the array declaration is on the stack. But (I thought) either way "fourNibbles" is of type "pointer to nibble", and hence the address of "fourNibbles" would be pointer to pointer to nibble (nibble **).
What am I missing here?
These are not even remotely the same. This
nibble * fourNibbles = (nibble *) malloc(4 * sizeof(nibble));
declares a pointer fourNibbles, while this
nibble fourNibbles[4];
declares an array. Arrays and pointers are two completely different things, which (at object level) have nothing in common. Trying to use them interchangeably in object contexts (like & operator) will only lead to disaster. There lots of information on this topic here on SO (search for "array pointer difference") as well as in this [de-facto standard] C FAQ: http://c-faq.com/aryptr/index.html
There is another thing that draws attention in your code though. Your function
void initArr(nibble ** arrLoc, unsigned int size)
is specifically tailored to the first variant, since it requires a pointer to a pointer as its first argument. It will not work if you attempt to force a pointer to an array to the first argument (which you already had a chance to observe firsthand).
However, the real question here is why your initArr function is written in such a bizarre way. This sequence
void initArr(nibble ** arrLoc, unsigned int size)
{
...
nibble * start = arrLoc[0];
...
start[i].all = 0;
looks rather unusual. Why are you passing a pointer to a pointer instead of an ordinary single-level pointer? E.g. you could simply do
void initArr(nibble *start, unsigned size)
{
unsigned i;
for (i = 0; i < size; ++i)
start[i].all = 0;
}
This version would be called as
initArr(fourNibbles,4); /* note: no `&` operator */
and it would be compatible with both malloc-ed arrays and explicitly declared arrays.
P.S. In C language a better idiom for malloc is
nibble * fourNibbles = malloc(4 * sizeof *fourNibbles);
Note that in this variant type name nibble is mentioned only once.
You are missing that the address of an array has a different type from the pointer that the plain array name becomes when used in an expression.
That is:
int *a1 = ...;
int a2[] = { ... };
some_func(&a1);
some_func(&a2);
cannot be correct unless some_func() expects a void *. The first call passes an int ** — a pointer to pointer to int; the second call passes an int (*)[] — a pointer to array of int. Drop the & from the array.
However, in your code, the problems are more complex. Because the function expects a nibble **, you have problems. What you should be doing is passing a nibble *:
void initArr(nibble *arrLoc, unsigned int size)
{
for (unsigned int i = 0; i < size; i++)
start[i].all = 0;
}
int main(void)
{
nibble *fourNibbles_1 = (nibble *) malloc(4 * sizeof(nibble));
nibble fourNibbles_2[4];
initArr(fourNibbles_1, 4);
initArr(fourNubbles_2, 4);
initArr(&fourNubbles_2[0], 4);
}
Your actual code is doing some really rather weird stuff. How much damage it is doing may depend on how big a pointer is compared to a nibble.
I've lost count, long ago, of the number of times I've done something like this in C:
struct foo f;
struct foo* pf = &f;
char* pc = (char*) pf;
transmit(pc, sizeof(f));
Or perhaps:
char* buffer[1024];
receive(buffer, 1024);
float values[256];
for(int ii = 0; ii < 256; ii++) {
float* pf = (float*)(buffer + ii*4);
values[ii] = *pf;
}
Or maybe:
uint32_t ipAddress = ...;
uint8_t* p = (uint8_t*)&ipAddress;
uint8_t octets[4] = {p[0], p[1], p[2], p[3]};
printf("%d.%d.%d.%d\n", octets[0], octets[1], octets[2], octets[3]);
I've only just discovered that reinterpreting a piece of memory like this by casting to another pointer type invokes undefined behaviour. And yet all of the the above examples are meant to do are absolutely necessary. What's the right way of doing them?
Casting to char * (or unsigned char * or typedefs thereof) is a special case, and does not cause undefined behaviour.
From the C spec, 6.3.2.3 Pointers, paragraph 7:
When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.
Your first & third examples are covered by this case. The second example is a bit hinky, but will probably work on most systems. What you really should be doing is either reading directly into values:
float values[256];
receive(values, sizeof values); // assuming receive() takes a "void *" parameter
Or something like this (to avoid alignment problems):
char buffer[1024];
receive(buffer, sizeof buffer);
float values[256];
for(int i = 0; i < 256; i++)
{
char *pf = (char *)&values[i];
memcpy(pf, buffer + i * sizeof(float), sizeof(float));
}
(Note I changed buffer to be a char array - I assume that was a typo in your question).
Ignoring padding/alignment issues and given the following struct, what is best way to get and set the value of member_b without using the member name.
struct mystruct {
int member_a;
int member_b;
}
struct mystruct *s = malloc(sizeof(struct mystruct));
Put another way; How would you express the following in terms of pointers/offsets:
s->member_b = 3;
printf("%i",s->member_b);
My guess is to
calculate the offset by finding the sizeof the member_a (int)
cast the struct to a single word pointer type (char?)
create an int pointer and set the address (to *charpointer + offset?)
use my int pointer to set the memory contents
but I get a bit confused about casting to a char type or if something like memset is more apropriate or if generally i'm aproching this totally wrong.
Cheers for any help
The approach you've outlined is roughly correct, although you should use offsetof instead of attempting to figure out the offset on your own. I'm not sure why you mention memset -- it sets the contents of a block to a specified value, which seems quite unrelated to the question at hand.
Here's some code to demonstrate how it works:
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
typedef struct x {
int member_a;
int member_b;
} x;
int main() {
x *s = malloc(sizeof(x));
char *base;
size_t offset;
int *b;
// initialize both members to known values
s->member_a = 1;
s->member_b = 2;
// get base address
base = (char *)s;
// and the offset to member_b
offset = offsetof(x, member_b);
// Compute address of member_b
b = (int *)(base+offset);
// write to member_b via our pointer
*b = 10;
// print out via name, to show it was changed to new value.
printf("%d\n", s->member_b);
return 0;
}
The full technique:
Get the offset using offsetof:
b_offset = offsetof(struct mystruct, member_b);
Get the address of your structure as a char * pointer.
char *sc = (char *)s;
Add the add the offset to the structure address, cast the value to a pointer to the appropriate type and dereference:
*(int *)(sc + b_offset)
Ignoring padding and alignment, as you said...
If the elements you're pointing to are entirely of a single type, as in your example, you can just cast the structure to the desired type and treat it as an array:
printf("%i", ((int *)(&s))[1]);
It's possible calculate the offset based on the struct and NULL as reference pointer
e.g " &(((type *)0)->field)"
Example:
struct my_struct {
int x;
int y;
int *m;
int *h;
};
int main()
{
printf("offset %d\n", (int) &((((struct my_struct*)0)->h)));
return 0;
}
In this particular example, you can address it by *((int *) ((char *) s + sizeof(int))). I'm not sure why you want that, so I'm assuming didactic purposes, therefore the explanation follows.
The bit of code translates as: take the memory starting at address s and treat it as memory pointing to char. To that address, add sizeof(int) char-chunks - you will get a new address. Take the value that the address thus created and treat it as an int.
Note that writing *(s + sizeof(int)) would give the address at s plus sizeof(int) sizeof(mystruct) chunks
Edit: as per Andrey's comment, using offsetof:
*((int *) ((byte *) s + offsetof(struct mystruct, member_b)))
Edit 2: I replaced all bytes with chars as sizeof(char) is guaranteed to be 1.
It sounds from your comments that what you're really doing is packing and unpacking a bunch of disparate data types into a single block of memory. While you can get away with doing that with direct pointer casts, as most of the other answers have suggested:
void set_int(void *block, size_t offset, int val)
{
char *p = block;
*(int *)(p + offset) = val;
}
int get_int(void *block, size_t offset)
{
char *p = block;
return *(int *)(p + offset);
}
The problem is that this is non-portable. There's no general way to ensure that the types are stored within your block with the correct alignment, and some architectures simply cannot do loads or stores to unaligned addresses. In the special case where the layout of your block is defined by a declared structure, it will be OK, because the struct layout will include the necessary padding to ensure the right alignment. However since you can't access the members by name, it sounds like this isn't actually what you're doing.
To do this portably, you need to use memcpy:
void set_int(void *block, size_t offset, int val)
{
char *p = block;
memcpy(p + offset, &val, sizeof val);
}
int get_int(void *block, size_t offset)
{
char *p = block;
int val;
memcpy(&val, p + offset, sizeof val);
return val;
}
(similar for the other types).