I have a char * who points to the structure. Here is my structure:
struct prot
{
int size;
unsigned short codeAction;
void *data;
};
I recovered size and codeAction, but now I want to recover data.
And when I cast my last 8 bytes I have nothing in it.
The following code is just a test, it's a bad code:
char lol[4];
for (int i = 0; i < 4; i++)
lol[i] = test[i];
int size = *(int*)lol;
char loli[2];
int index = 0;
for (int i = 4; i < 6; i++)
{
loli[index] = test[i];
index++;
}
int code = *(short*)loli;
char lolo[8];
index = 0;
for (int i = 6; i < size; ++i)
{
lolo[index] = test[i];
index++;
}
void *newData = (char *)lolo; // how can I cast it?
How I can display the content of newData?
Your problem is that when casting lolo you actually cast a pointer to the char array you defined. So the result of the cast would be a char pointer to the first cell of the array.
Why don't you just use this as a struct and access the fields regularly?
Anyway, you want to use lolo as a 64 bit type pointer and the access what's in it.
void* newData = *((uint64_t*)lolo)
Besides, don't loop until size in the last for loop, loop only 8 times, until lolo is full. The number of bytes in newData itself (not what it points to) is constant, and is 4 bytes on 32bit machines, 8 bytes on 64bit ones.
Last thing - index++, not o++. o isn't defined, as much as I can see.
Related
#define MAX_NUM_STACKS_ALLOWED 10
#define MAX_PLATES_PER_STACK 5
#define NEW_STACKS_CREATION_INC 2
typedef struct stackOfPlates {
int currentStackIndex;
int currentStackTop[MAX_NUM_STACKS_ALLOWED];
int currentMaxStacks;
int **stackOfPlatesArray;
} stackOfPlates_t;
stackOfPlates_t *stackOfPlates_Init(void) {
stackOfPlates_t *stackOfPlates = (stackOfPlates_t *)malloc(sizeof(stackOfPlates));
stackOfPlates->stackOfPlatesArray = (int **)malloc(NEW_STACKS_CREATION_INC * sizeof(int *));
stackOfPlates->currentStackIndex = 0;
stackOfPlates->currentMaxStacks = NEW_STACKS_CREATION_INC;
int i;
for (i = 0; i < stackOfPlates->currentMaxStacks; i++) {
stackOfPlates->stackOfPlatesArray[i] = (int *)malloc(MAX_PLATES_PER_STACK * sizeof(int));
printf("%d\n", stackOfPlates->currentMaxStacks);
}
for (i = 0; i < MAX_NUM_STACKS_ALLOWED; i++) {
stackOfPlates->currentStackTop[i] = -1;
}
return stackOfPlates;
}
void main()
{
stackOfPlates_t *stackOfPlatesA;
stackOfPlatesA = stackOfPlates_Init();
}
The output of the above code is:
2 (expected),
0 (not expected, not sure how this field gets modified)
I'm trying to malloc the 2D array (stackOfPlates->stackOfPlatesArray). After allocating memory for the NEW_STACKS_CREATION_INC number of stacks, I allocate memory for MAX_PLATES_PER_STACK for every stack. During this operation, I find that my stackOfPlates->currentMaxStacks gets modified to 0.
Could someone please explain why?
In your code
malloc(sizeof(stackOfPlates));
should be
malloc(sizeof(*stackOfPlates));
As you want to allocate memory for the structure type not the pointer to structure type.
That said, see this: Do I cast the result of malloc?
I was wondering if you could help me overcome a hurdle I've run into with my C syntax. I have written the function:
binary_and_trim(char *password, unsigned *key1, unsigned *key2)
that has achieved the goal of converting a provided string into binary and trimmed off the leading zero. I have assigned my key1 and key2 pointers to the correct indexes. But then, when I return to the main function the values are all lost.
I believe that the problem is that when I pass the *key1/*key2 pointers to the function it only receives a copy of them. But, as I am new to C, I don't know how to fix it?
I created a for loop to help me test/debug.
#include <stdio.h>
#include <string.h>
void binary_and_trim(char *password, unsigned *key1, unsigned *key2);
unsigned int get_n_bits(unsigned *bits, int width, int index);
int main(int argc, const char * argv[]) {
unsigned *key1 = NULL;
unsigned *key2 = NULL;
binary_and_trim("password", key1, key2);
//This test fails with a EXC_BAD_ACCESS error
for(int i = 0 ; i < 28; i++){
printf("key1[%d] %u key2[%d] %d\n", i, key1[i], i, (key2 + i));
}
}
void binary_and_trim(char *password, unsigned *key1, unsigned *key2){
char c;
int count = 0;
unsigned tmp;
unsigned long len = strlen(password);
unsigned trimmedbinary[len * 7];
for(int i = 0; i < len; i++){
c = *(password + i);
for( int j = 6; j >= 0; j--) {
tmp = 0;
if(c >> j & 1){
tmp = 1;
}
*(trimmedbinary + count) = tmp;
count++;
}
}
key1 = trimmedbinary;
key2 = &trimmedbinary[28];
//This test works correctly!!!
for(int i = 0 ; i < 28; i++){
printf("key1[%d] %d key2[%d] %d\n", i, *(key1 + i), i, *(key2 + i));
}
}
I believe that the problem is that when I pass the *key1/*key2 pointers to the function it only receives a copy of them.
Yes, exactly. Pointers are just integers and integers get copied. You solve this with a pointer to a pointer, a "double pointer".
However, there is another problem. trimmedbinary is using stack/automatic memory. "Automatic" meaning it will be freed once the function exits. Once the function returns key1 and key2 will point at freed memory. trimmedbinary must be declared in heap/dynamic memory with malloc.
void binary_and_trim(char *password, unsigned int **key1, unsigned int **key2){
unsigned int *trimmedbinary = malloc(len * 7 * sizeof(unsigned int));
...
*key1 = trimmedbinary;
*key2 = &trimmedbinary[28];
for(int i = 0 ; i < 28; i++) {
printf("key1[%d] %u, key2[%d] %u\n", i, (*key1)[i], i, (*key2)[i]);
}
return;
}
And call it as binary_and_trim("password", &key1, &key2);
Update: I answered the question about how to alter the pointer value, but I have not noticed the memory issue in the code. Please refer to this answer instead.
Pointers are variables themselves. You may already know that with a pointer, you can change the value stored in the variable the pointer points to. Therefore, you need to use a pointer to a pointer to change the value (the memory address) stored in the pointer.
Change your function signature to:
void binary_and_trim(char *password, unsigned **key1, unsigned **key2)
Call with:
binary_and_trim("password", &key1, &key2);
and replace key1 and key2 to *key1 and *key2 in the function definition.
Your problem is that the variable you use to fill with your keys data trimmedbinary is allocated only for the scope of the function binary_and_trim. That said, when you print inside the function
void binary_and_trim(char *password, unsigned **key1, unsigned **key2){
...
unsigned trimmedbinary[len * 7]; // <--
...
*key1 = trimmedbinary; // <--
*key2 = &trimmedbinary[28]; // <--
//This test works correctly!!!
for(int i = 0 ; i < 28; i++){
printf("key1[%d] %d key2[%d] %d\n", i, *(key1 + i), i, *(key2 + i));
}
}
it just works because the data your key1 pointer is trying to access is still there.
However, when you return from your function back to main, key1 and key2 still point back to the buffer you initialized inside binary_and_trim, which is no longer valid because is out of scope.
I suggest you create a buffer in main and pass it as a parameter,
int main(int argc, const char * argv[]) {
const char* password = "password";
unsigned long len = strlen(password);
unsigned buffer[len * 7]; // <-- Add buffer here
unsigned *key1 = NULL;
unsigned *key2 = NULL;
binary_and_trim(password, &key1, &key2, &buffer, len * 7);
//This test succeeds
for(int i = 0 ; i < 28; i++){
printf("key1[%d] %u key2[%d] %d\n", i, key1[i], i, (key2 + i));
}
}
void binary_and_trim(char *password, unsigned **key1, unsigned **key2, unsigned** buffer, size_t buff_size){
char c;
int count = 0;
unsigned tmp;
...
//Use *buffer instead of trimmedbinary
//Check if buff_size matches len(password) * 7
or alternatively, make the buffer heap allocated (dont forget to free() later).
I believe that the problem is that when I pass the *key1/*key2
pointers to the function it only receives a copy of them.
Already altered in code as well.
Wow! Thank you EVERYONE! I finally got it up and running (after 4 hours of beating my head against the wall). I can't begin to say how clutch you all are.
I'm realizing I have tons to learn about the granular memory access of C (I'm used to Java). I can't wait to be an actual WIZARD like you all!
I am trying to store data to the char buffer pointed by the pointer credit_data.
I am incrementing the pointer every time i copy the data. After final increment, i am decrementing the pointer by having a counter on the number of bytes read and then use that to decrement the pointer and get the correct address. But when i try to print the final string stored in the buffer, i am getting NULL. I am new to pointers and pointer arithmetic. Please guide me.
#define DP_RMD_PERSON_TITLE_MAX_LEN (64)
#define DP_RMD_FAMILY_TITLE_MAX_LEN (64)
int CaluclateSizeOfCreditList()
{
short dataset_idx = 0,str_len =0, num_datasets = 8; //variable
str_len = sizeof(short);
for (dataset_idx = 0; dataset_idx < num_datasets; dataset_idx++) {
str_len += sizeof(short) + DP_RMD_PERSON_TITLE_MAX_LEN + DP_RMD_PERSON_TITLE_MAX_LEN;
}
return str_len;
}
void main ()
{
unsigned char* credit_data = NULL;
//unsigned char* dp_credit_data;
short num_credits = 8 , classification = 2, dataset_idx = 0, i = 0, len = 0;
char *person_title = "robert"; char *person_given_name = "Wuhl";
len = CaluclateSizeOfCreditList();
credit_data = (unsigned char *)malloc(len);
if(!credit_data) return;
memset(credit_data, 0x00, len);
//dp_credit_data = credit_data;
printf("\n credit_data pointing to address location %p",credit_data);
*credit_data = num_credits;
credit_data += sizeof(short);
i += sizeof(short);
for (dataset_idx = 0; dataset_idx < num_credits; dataset_idx++)
{
*credit_data = (unsigned char)classification;
credit_data += sizeof(short);
i += sizeof(short);
len = strlen(person_title);
len++;
memcpy(credit_data,person_title,len);
credit_data += DP_RMD_PERSON_TITLE_MAX_LEN;
i += DP_RMD_PERSON_TITLE_MAX_LEN;
len = strlen(person_given_name);
len++;
memcpy(credit_data,person_given_name,len);
if(dataset_idx < 7)
{
credit_data += DP_RMD_PERSON_TITLE_MAX_LEN;
i += DP_RMD_PERSON_TITLE_MAX_LEN;
}
}
*credit_data = '\0';
printf("\n credit_data pointing to address location after increment %p",credit_data);
credit_data = credit_data - i;
//credit_data = dp_credit_data;
printf("\ncredit_data is [%s]\n",credit_data);
//Free the allocated memory
}
Problem statement is, i have a structure whose member variable is an array of another structure.
typedef struct _DP_RMD_CREDIT_
{
DP_RMD_CREDIT_TYPE classification; //ENUM
UBYTE *person_title;
UBYTE *person_given_name;
UBYTE *person_family_name;
UBYTE *organisation;
} DP_RMD_CREDIT;
typedef struct _DP_RMD_CREDIT_LIST_
{
USHORT num_credits;
DP_RMD_CREDIT credit[DP_RMD_MAX_CREDITS];
} DP_RMD_CREDIT_LIST;
I want to store all the values of those member variables in a buffer and update to sqlite db as BLOB. Please assist me.
Your code makes completely no sense (sorry to be so blunt).
Function CaluclateSizeOfCreditList() will always return 1042, so why have that function.
*credit_data = num_credits;
credit_data += sizeof(short);
The above places an int in *credit_data, then increments with size of short. Makes no sense.
*credit_data = (unsigned char *)classification;
credit_data += sizeof(int);
The above makes classification a pointer to char then copies that thing to credit_data. Here you think the compiler will convert the value of classification into a string of digits. Nono. Then you increment credit_data with the size of an int. You have two thoughts: classification is made into a string of digits (how many??); the original was an int so, increment with that size. Bad thinking.
*credit_data = '\0';
if(NULL != credit_data)
This terminates credit_data with a null character, as if it was a string (but it is filled with binary data), then you test if credit_data actually has memory (allocated from malloc). Quite the other way around, I'd say.
And now you wonder why printf doesn't show anything...
I suggest you read a book on C.
Is it possible to increment/advance a char array like I can a char pointer?
For example I can do this for a char pointer:
while (*cPtr)
printf("c=%c\n", *(cPtr++));
But I am not able to do this:
// char cArray[] = "abcde";
while (*cArray)
printf("c=%c\n", *(cArray++)); // Compile error: 19 26 [Error] lvalue required as increment operand
The purpose is to be able to iterate over a char array when I dont know the length of the array. My thinking is that I just want to advance till I find a null character I guess unless theres an easier way?
char a[] = "abcde";
int index = -1;
while (a[++index])
printf("c=%c\n", a[index]);
Is it possible to increment/advance a char array like I can a char pointer?
Unlike pointers, arrays are not lvalues and you can't modify it. That's a major difference between arrays and pointers.
Do something like that:
char cArray[] = "abc def";
char *p = &cArray[0];
while (*p)
printf("c=%c\n", *(p++));
You can do:
for(int i = 0; i < 5; i++) // if you know the length
printf("c=%c\n", a[i]);
or get the size with sizeof() and replace i < 5 with i < size:
int size = (sizeof(a) / sizeof(*a))
I have used this with success under keil uVision:
char buffer[512];
uint8_t var[512]; // uint8_t = integer 8bit
for(int i = 0; i < 128; i = i + 4)
sprintf(&buffer[i],"%03d,", var[y]); //this will put 4 bytes in buffer
Better way to do this:
char buffer[128];
uint8_t int_buffer[24]; // gets updated in an interrupt - some sensors values
uint8_t i = 0;
uint8_t PrintSize = 0;
while(/*myFile is smaller than 1Mb..*/)
{
PrintSize = 0;
i = 0;
while(i < 23)
{
PrintSize += sprintf(buffer + PrintSize,"%01d,",int_buffer[i]);
i++;
}
PrintSize += sprintf(buffer + PrintSize,"%01d\n", int_buffer[23]);
//write buffer to a file in my app
}
File content is like this:
41,1,210,243,120,0,210,202,170,0,14,28,0,0,0,1,85,0,5,45,0,0,0,1
40,1,215,255,119,0,215,255,170,0,14,37,0,0,0,1,85,0,5,46,0,0,0,1
I am trying to allocate a block of memory, and store a list of structures without using multiple mallocs for each... this is just a generic example, I don't have the original code I was working with earlier, but this is the general idea, but my problem was that I was getting heap corruption when other parts of my code executed after the InitPoints() function call. I don't know what part of my code is illegal, but I suspect it is in the for loop of the InitPoints() function. I am trying to use this as table, then I can create additional tables of defined size if I ran out of memory and link them together... so kind of like a dynamic expanding array if that makes any sense.
typedef struct Tb{
POINT points;
POINT *next;
} TABLE;
typedef struct Pt{
int x;
int y;
}POINT;
POINT *mypoints;
int main() {
int size = 10;
int i = 0;
mypoints = InitPoints(size);
for(i=0; i < size; i++)
{
printf("mypoint [%d] = (%d,%d)\n",i, mypoints->x, mypoints->y);
mypoints = mypoints + sizeof(POINT);
}
// some other code...
// i.e. createThread(....)
return 0;
}
POINT* InitPoints(int size)
{
POINT *tmp;
POINT *orig;
int a = 10;
int b = 1000;
orig = (POINT*) malloc (sizeof(POINT) * size);
if(orig == NULL)
return NULL;
tmp = orig;
for (i = 0; i < size; i++)
{
tmp->x = a++;
tmp->y = b++;
tmp = tmp + sizeof(POINT);
}
return orig;
}
This is wrong:
mypoints = mypoints + sizeof(POINT);
You should review pointer arithmetic in C. Just use:
mypoints += 1; /* or something similar */
(There is a similar problem in your InitPoints function)
Here's one referemce:
http://www.eskimo.com/~scs/cclass/notes/sx10b.html
The problem is in this line:
tmp = tmp + sizeof(POINT);
It should be
++tmp;
The latter says to increment the pointer by one element; since it points to the structure, it increments by the size of the structure. The original code instead increments by n elements where n is the number of bytes in the structure. For example, if int is 32-bits, it will advanced by 8 elements.
This is why I would do it
for (i = 0; i < size; i++)
{
orig[i].x = a++;
orig[i].y = b++;
}
In C, adding an integer to a POINT* pointer advances the pointer not by that number of bytes, but by that number of POINT structures.
You have two places in your code where you add sizeof(POINT) to your pointer. Instead you should just add 1.