How to assign string into char* pointer? - c

#include <stdio.h>
struct Analysis {
int lnlen;
int arr[2];
char* name;
};
int main()
{
struct Analysis ana_space[2];
char *ptr = (void*) &ana_space;
ana_space[0].lnlen = 0;
ana_space[0].arr[0] = 1;
ana_space[0].arr[1] = 2;
ana_space[0].name = "Peter";
printf("\n%d\n", *ptr); // print 0;
*ptr = 10; // how to use memcpy here;
printf("\n%d\n", *ptr); // print 10;
ptr = ptr + sizeof(int); // advance pointer by int;
printf("\n%d\n", *ptr); // print 1;
ptr = ptr + 2*sizeof(int); // advance pointer by 2 ints;
printf("\n%s\n", *ptr); // print "Peter"; --------------not work
//*ptr = "Jim"; // how to assign new name "Jim" into that memory;
return 0;
}
Output:
0
10
1
(null)
I want to use char * as pointer to go through memory address to get some data and also store value into memory.
For int and int array, it works fine, but not for the string.
How to print the string and store new string value into memory?

Your approach is not portable. It will be better to use offsetof to make sure that you can reliably point to the addresses of the members of a struct.
int main()
{
struct Analysis ana_space[2];
char *ptr = (void*) &ana_space;
size_t offset1 = offsetof(struct Analysis, arr);
size_t offset2 = offsetof(struct Analysis, name);
ana_space[0].lnlen = 0;
ana_space[0].arr[0] = 1;
ana_space[0].arr[1] = 2;
ana_space[0].name = "Peter";
// advance pointer to point to arr.
ptr = ptr + offset1;
// advance pointer to point to name
ptr = ptr + (offset2-offset1);
// Cast the pointer appropriately before dereferencing.
printf("\n%s\n", *(char**)ptr);
// how to assign new name "Jim" into that memory;
*(char**)ptr = "Jim";
printf("\n%s\n", *(char**)ptr);
return 0;
}
Your use of:
printf("\n%d\n", *ptr); // print 0;
*ptr = 10; // how to use memcpy here;
printf("\n%d\n", *ptr); // print 10;
and the expected output is flawed. It works only with little endian systems. I suggest using:
printf("\n%d\n", *(int*)ptr);
*(int*)ptr = 10;
printf("\n%d\n", *(int*)ptr);

The code you presented could cause undefined behavior due to padding and representations of types, which are implementation-defined.
After you increment the pointer ptr here:
ptr = ptr + 2*sizeof(int);
the pointer ptr points to the member name of the struct Analysis. If you dereference the pointer ptr, you get the type char and thus a single byte. This byte does not represent a pointer to the string.
The pointer ptr will have to be cast to the type pointer to a pointer to char, and then dereferenced so the correct and full value of the member name will be obtained.
That resulting value is a pointer to the string "Peter".

ANSI C has a macro called offsetof() found in stddef.h that gives a more sure way of calculating the pointer offset of a member within a struct. Here, we can get the the address of the name member in ana_space[0] directly.
ptr = (char*) &ana_space + offsetof(struct Analysis, name);
This takes out any guess work on padding.
This pointer then has to be properly cast to print the contents of name:
printf("%s\n", *(char**) ptr);

Related

Pointers in structure with dynamic memory allocation

I am attempting to create a structure (2nd) in a structure (1st) with dynamic memory allocation. For the sequence of steps below (case 1), where I call malloc for a pointer to the 2nd structure before calling realloc for the 1st structure, I see garbage when printing the value of the member (str[0].a1) in the first structure. If I place the same realloc code before malloc (case 2), there are no issues.
#include<stdio.h>
#include<stdlib.h>
typedef struct string2_t {
int a2;
} string2;
typedef struct string1_t {
int a1;
string2 * b;
} string1;
string1 * str = NULL;
int size = 0;
string1 test(int val){
// case 2
//str = (string1 *) realloc(str, size*sizeof(string1));
string1 S;
S.a1 = val;
size += 1;
S.b = (string2 *) malloc(2*sizeof(string2));
S.b[0].a2 = 11;
S.b[1].a2 = 12;
// case1
str = (string1 *) realloc(str, size*sizeof(string1));
return S;
}
int main() {
size += 1;
str = (string1 *) malloc(size*sizeof(string1));
str[0] = test(10);
printf("value of a:%d\n",str[0].a1);
str[1] = test(20);
printf("value of a:%d\n",str[0].a1);
return(0);
}
I can see that memory location changes for case 1, but I don't quite understand why doesn't pointer point to the right contents (str[0].a1 shows junk). I haven't returned the address of 1st structure before realloc, so I feel it should have worked. Could someone explain why it's pointing to garbage?
As has been stated by several in the comments, lines like this cause undefined behavior:
str[0] = test(10);
The test() function reallocates str, and this is not sequenced with retrieving the address of str[0] as the location to store the result. It's very likely to be compiled as if it had been written
string1 *temp = str;
temp[0] = test(10);
temp caches the old address of str from before the realloc(), and this is invalid after the function returns.
Change your code to:
string1 temp = test(10);
str[0] = temp;
Better design would be to reorganize the code so that all maintenance of the str array is done in one place. test() should be a black box that just allocates the string1 object, while main() allocates and reallocates str when assigning to it.

C pass void pointer array to function

I want to pass a void pointer array to a function which fills it with the result it works fine with integer but I have troubles returning char*
int function(void *arr[]);
int main(void) {
void *arr[3];
function(arr);
printf("%d\n", *(int *)&arr[0]);
printf("%d\n", *(int *)&arr[1]);
printf("%s\n", (char *)&arr[2]);
}
int function(void *arr[]){
arr[0] = (void*)(int)4;
arr[1] = (void*)(int)6;
char* test = "abc";
arr[2] = (void*)test;
return 0;
}
for the String I don't get the right value
arr has type void(*)[3].
arr[0] has type void*. The fact that it stores a suitably converted value of 4 is irrelevant.
&arr[0] has type void**.
(int *)&arr[0] has type int*, but it points to an object of type void* instead of pointing to an object of type int. This is not what pointers normally do. You can have such a pointer, but the only thing you can legally do with it is convert it back to the right type, in this case void**. You are not doing that.
*(int *)&arr[0] has type int.
Here you are accessing an object of type void* through an lvalue of type int. This is undefined behaviour. Don't do that.
If you want to convert arr[0] back to int, just do that:
printf("%d\n", (int)arr[0]);
Likewise, if you want to convert arr[2] back to char*, do just that:
printf("%s\n", (char*)arr[2]);
You may pass an array of voids, and assign that array elements to a dynamically allocated memory region that stores the pointed-to value.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int function(void *arr[]){
arr[0] = malloc(sizeof(int));
if (arr[0] == NULL) goto ERR_MALLOC_0;
*(int*)arr[0] = 4;
arr[1] = malloc(sizeof(int));
if (arr[1] == NULL) goto ERR_MALLOC_1;
*(int*)arr[1] = 6;
const char *const test = "abc";
arr[2] = malloc(strlen(test));
if (arr[2] == NULL) goto ERR_MALLOC_2;
strcpy(arr[2], test);
return 0;
// remember about error checking
free(arr[2]);
ERR_MALLOC_2:
free(arr[1]);
ERR_MALLOC_1:
free(arr[0]);
ERR_MALLOC_0:
return -1;
}
int main(void) {
void *arr[3];
int err = function(arr);
if (err == -1) abort();
// & is the address of element, not it's element
printf("%d\n", *(int*)arr[0]);
printf("%d\n", *(int*)arr[1]);
printf("%s\n", (char*)arr[2]);
// remember to free memory
for (int i = 0; i < 3; ++i) {
// funny how we do not need to know the effective type
free(arr[i]);
}
}
But such function is just plainly confusing and will result in many, many bugs and problems. Instead just actually use variables of proper type:
#include <stdlib.h>
#include <string.h>
int function(int *val1, int *val2, char **string) {
*val1 = 3;
*val2 = 6;
const char *test = "abc";
*string = malloc(strlen(test));
if (*string == NULL) return -1;
strcpy(*string, test);
return 0;
}
int main(void) {
int val1;
int val2;
char *string;
int err = function(&val1, &val2, &string);
if (err == -1) abort();
printf("%d\n", val1);
printf("%d\n", val2);
printf("%s\n", string);
free(string);
}
If you are really striving for implementing some virtual representation and operations on different data types, using plain "array of void pointers" will get you nowhere, because such array doesn't know what is the underlying type of the value that is being stored - you, as a programmer, have to know what is inside that array (ie. that arr[0] is an int and arr[2] is a char*), so as you know it you might as well just use variables of proper types from the start.
arr[0] = (void*)(int)4;
The above line cast the integer 4 as void pointer (address) and stores it in the array arr as pointer address. I guess that's not what you wanted.
In order to access data using a void pointer the way you want, first make it point to a valid memory address, which will hold the data when the function exits. You have to be careful while assigning memory address to a void pointer inside a function, all variables in that function's stack (local variables) will be popped off the from the stack when the function exits, making that memory addresses invalid. Only use static (or global) or dynamic memory while assigning the memory address to your pointer inside the function, if you want to use it outside the function.

Garbage value even after initializing members of dynamically allocated struct array

I have a dynamically allocated array of structures, 'buff'. Each element is a structure that has a few integer variables and a pointer 'buffer_ptr' which points to another dynamically allocated array of structures. The size of both arrays is given as command line input.
int buffer_size;
int user_num;
struct tuple
{
char userID[5];
char topic[16];
int weight;
};
struct buff_ctrl
{
struct tuple* buffer_ptr;
int in;
int out;
int numItems;
int done;
};
The arrays are created and initialized in main() as follows:
int main(int argc, char* argv[])
{
void *status;
pthread_t mapThd;
if(argc != 4)
{
printf("Input format: ./combiner <buffer_size> <number_of_users> <input_file>\n");
return -1;
}
buffer_size = atoi(argv[1]);
user_num = atoi(argv[2]);
struct buff_ctrl *buff = (struct buff_ctrl*)malloc(user_num * sizeof(struct buff_ctrl));
for(int i=0; i<user_num; i++)
{
struct buff_ctrl* curr_buff = (buff + (i*sizeof(struct buff_ctrl)));
struct tuple *ptr = (struct tuple*)malloc(buffer_size * sizeof(struct tuple));
curr_buff->buffer_ptr = ptr;//points to another array
curr_buff->in = 8;
curr_buff->out = 4;
curr_buff->numItems = 7;
curr_buff->done = 0;
printf("%p\n",curr_buff);
}
Then, I need to pass the 'buff' pointer as an argument when creating thread using pthread_create:
pthread_create(&mapThd, NULL, mapper, (void*)buff);
pthread_join(mapThd, &status);
free(buff);
/*end of main*/
My function pointer is as follows:
void* mapper(void *buff)
{
struct buff_ctrl* arr = (struct buff_ctrl *)buff;
struct buff_ctrl* temp_ptr;
printf("######################################################\n");
for(int k=0; k<user_num; k++)
{
/*Printing just to check values */
temp_ptr = arr + (k*sizeof(struct buff_ctrl));
printf("buffer ptr = %p\n", temp_ptr->buffer_ptr);
printf("in = %d\n", temp_ptr->in);
printf("out = %d\n", temp_ptr->out);
printf("numItems = %d\n", temp_ptr->numItems);
}
printf("######################################################\n");
pthread_exit((void*)buff);
}
But, when I print the values of 'buffer_ptr' from the created thread (only one), for ODD number of user_num, there is always ONE element of the array 'buff' which gives garbage value after pthread_create statement! When the values are checked in main itself after removing calls to pthread, it runs fine.
This line
struct buff_ctrl* curr_buff = (buff + (i*sizeof(struct buff_ctrl)));
should be
struct buff_ctrl* curr_buff = buff + i;
buff + i is pointer arithmetic and the compiler already takes the size of the
object pointed to by buff into consideration. By doing i*sizeof(struct buff_ctrl) you are assigning
a pointer that may be after the allocated memory.
As general suggestion:
Don't cast malloc. And instead of using sizeof(<type>), use sizeof *variable, this is more safe, because
it's easier to make mistakes when writing sizeof(<type>).
So:
struct buff_ctrl *buff = malloc(user_num * sizeof *buff);
...
struct tuple *ptr = malloc(buffer_size * sizeof *ptr);
And you don't need to declare a separate pointer, you can do:
for(int i=0; i<user_num; i++)
{
buff[i].buffer_ptr = malloc(buffer_size * sizeof *buff[i].buffer_ptr);
buff[i].in = 8;
buff[i].out = 4;
buff[i].numItems = 7;
buff[i].done = 0;
}
Also you should always check for the return value of malloc. If it returns
NULL, you cannot access that memory.
This is wrong:
struct buff_ctrl* curr_buff = (buff + (i*sizeof(struct buff_ctrl)));
When you do pointer arithmetic, it operates in units of the size of what the pointer points to, so you don't need to multiply by sizeof. As a result, you're effectively multiplying twice and accessing outside the array bounds.
Just treat buff as an array, rather than dealing with pointers.
for(int i=0; i<user_num; i++)
{
struct tuple *ptr = malloc(buffer_size * sizeof(struct tuple));
buff[i].buffer_ptr = ptr;//points to another array
buff[i].in = 8;
buff[i].out = 4;
buff[i].numItems = 7;
buff[i].done = 0;
}
Also, see Do I cast the result of malloc?
You have a fundamental error.
Pointer arithmetics works by adding the offset in multiples of the pointer type, so adding the offset yourself will not work as you apparently expect it to.
If it was a char * pointer then you would need to add the offset manually, increments would be multiplied by one. But in your case increments by n are multiplied by the size of the pointer base type.
There are times when doing pointer arithmetics with the addition notation makes sense, but most of the time it's much clearer to write index notation instead.

C Program: Update unsigned char pointer array with function

I have a function to update an unsigned char* and cannot find where my bug is. I'm not sure if I need to allocate memory, or if I am pointing to the wrong memory space somewhere. I tried to follow a similar structure as posted here, but have not had success with an unsigned char.
My code so far:
#include <stdio.h>
void changeArray(unsigned char **arr)
{
unsigned char ptr[3] = {100, 101, 102};
*arr = ptr;
printf("%d\n", **(arr+0)); // This prints out the correct value of 100
}
int main(int argc, const char* argv[])
{
int i = 0;
unsigned char *blah;
unsigned char ptr2[3] = {103, 104, 105};
blah = ptr2;
printf("Blah is: \n");
for (i = 0; i < 3; i++) {
printf("%d,",*(blah+i)); //This prints out 103,104,105
}
changeArray(&blah);
printf("Blah is now: \n");
for (i = 0; i < 3; i++) {
printf("%d,", *(blah +i)); //This prints out 0,0,0
}
return 0;
}
Any help in determining how to properly access the values set in the changeArray() function would be greatly appreciated.
With this *arr = ptr; you are storing a pointer to a variable with automatic storage duration. The behaviour undefined.
You can dynamically allocate and return a pointer that way:
void changeArray(unsigned char **arr)
{
unsigned char ptr[3] = {100, 101, 102};
unsigned char *p = malloc(sizeof ptr);
memcpy(p, ptr, sizeof ptr);
*arr = p;
printf("%d\n", **(arr+0)); // This prints out the correct value of 100
}
You should also do error checking if malloc failed and remember to free the allocated memory after use in main.
The problem here is, ptr is local to changeArray() function. So once the function finishes execution, there is no existance of ptr. Hence, once you assign ptr to *arr
*arr = ptr;
and changeArray() execution gets over, accessing blah in main() now will invoke undefined behaviour.
FWIW, you don't need to pass the address of blah, you don't need a pointer-to-pointer at all. blah is already a pointer, which you can pass to changeArray() to alter the contents of the memory area it points to. You can do something like
void changeArray(unsigned char *arr)
{
for (int i = 0; i < 3; i ++)
arr[i] = 100+i;
}
and call it like
changeArray(blah);

Basic help needed with pointers (double indirection)

I asked some time ago on an account I can't remember how to manipulate basic pointers and someone gave me a really good demo
for example
char *ptr = "hello" (hello = a char array)
so now *ptr is pointing at 'h'
ptr++ means moving the ptr to point at the next element, to get its value I do *ptr and that gives me e
ok so far everything works as I hope :D, but now I need to manipulate a char **ptr and was wondering how I do this in a way that mimics the effects of a 2d array?
Some basic tips would be much appreciated as I need to do an assignment that has a **ptr to imitate a 2d array and without knowing how it does this first means I can't even solve it on paper (for example, how do you dereference a **ptr, how do you get [x][y] values etc)
thanks
You can subscript a pointer the same way you can subscript an array, provided all the addresses have been set up correctly.
Assuming the following declaration:
char **ptr;
here are the types of the various expressions:
Expression Type Equivalent expressions (yield same value)
---------- ---- -----------------------------------------
ptr char ** &ptr[0]
*ptr char * ptr[0]
*(ptr+i) char * ptr[i]; &ptr[i][0]
**ptr char ptr[0][0]
*(*(ptr+i)) char ptr[i][0]; *ptr[i]
*(*(ptr+i)+j) char ptr[i][j]
thus:
ptr can be treated as though it was an array of strings (2-d array of char)
ptr[i] points to the beginning of the i'th string in the list
ptr[i][j] is the value of the j'th character of the i'th string in the list
The expressions ptr++ and ++ptr will advance ptr to point to the next string
The expressions (*ptr)++ and ++(*ptr) will advance *ptr to point to the next character
As for setting up your pointers, this arrangement assumes everything has already been allocated as static arrays or dynamically through malloc. You cannot just write
char **ptr = {"foo", "bar", "bletch"}; // using aggregate initializer on
// non-aggregate type; bad juju,
// a.k.a undefined behavior
or
char **ptr; // ptr has not been initialized to point anywhere
ptr[0] = "foo"; // dereferencing ptr via subscript invokes undefined
ptr[1] = "bar"; // behavior
ptr[2] = "bletch";
Generally, when you're using a pointer as though it was an array, you'll use malloc or something similar to allocate your buffers:
char **ptr = malloc(sizeof *ptr * N);
if (ptr)
{
ptr[0] = "foo"; // ptr[i] gets address of
ptr[1] = "bar"; // string literal
ptr[2] = "bletch";
...
}
or
char **ptr = malloc(sizeof *ptr * N);
if (ptr)
{
size_t i;
for (i = 0; i < N; i++)
{
ptr[i] = malloc(sizeof *ptr[i] * M); // strictly speaking, the sizeof
if (ptr[i]) // is not necessary here
{
//initialize ptr[i]
}
}
}
A pointer to a pointer is just that. For example:
// Declare our double-indirection pointer.
char** ptr;
// And initialize it:
char s1[] = "hello";
char s2[] = "world";
ptr = malloc(sizeof(char*) * 2);
ptr[0] = s1;
ptr[1] = s2;
// ptr now points to a pointer that points to 'h'.
char* ptr2 = *ptr;
// ptr2 points to 'h'.
char* ptr3 = *(ptr + 1);
// ptr3 points to "w".
char c = **ptr; // could be written as *(*ptr)
// c = 'h'.
char c2 = *(*(ptr + 1));
// c2 = 'w'.
char c3 = *(*(ptr) + 1);
// c3 = 'e'.
You may use them as you would a normal two-dimensional array. (Since effectively, that's what they are)
char** ptr = {"lorem", "ipsum", "dolor"};
char* s1 = ptr[0]; //Points to the beginning of "lorem"
char* s2 = ptr[1]; //Points to the beginning of "ipsum"
char c = ptr[2][4]; //Contains 'r'
This is due to the fact that:
int *a;
//...
int i = a[6];
int j = *(a + 6); //Same as previous line!
Cheers,
Amit Ron--

Resources