I am working on a Uni assignment here, and I've run into a problem. I am attempting to store a string input at a point inside a struct using a for-loop. Later on I intend to use the pointer to the place where the data was stored to fetch the string. Now the problem is, as I move on inside my for-loop, the address of the point changes as well. This code:
printf("B: %p\n", txt->point);
for(i = 0; i < input_sz; i++)
{
txt->point[i] = input[i];
}
printf("A: %p\n", txt->point);
gives the output:
B: 0x7fc111803200
A: 0x7fc111803265
where B is before-value and A is after-copying value.
Any help debugging this would be very appreciated!
EDIT: Here's some more code:
The struct:
struct text_storage {
char* start;
char* point;
char* end;
} typedef text_t;
Initialization function:
text_t* text_init(void *memory, size_t size)
{
text_t* to_return;
if(size < sizeof(text_t))
{
return NULL;
}
to_return = (text_t*) memory;
to_return->start = to_return;
to_return->end = to_return->start + size;
to_return->point = to_return->start;
printf("Start: %p, point: %p, end: %p, end-start: %d\n", to_return->start, to_return->point, to_return->end, (to_return->end - to_return->start));
return to_return;
}
The text-store method in which the error occurs:
int text_store_entry(text_t *txt, const char *input, size_t input_sz)
{
int to_return;
char* begin = txt->point;
int i;
if(input_sz > (txt->end - txt->point))
{
return -1;
}
printf("Start: %p, point: %p, end: %p, end-start: %d\n", txt->start, txt->point, txt->end, (txt->end - txt->start));
printf("B: %p\n", txt->point);
for(i = 0; i < input_sz; i++)
{
txt->point[i] = input[i];
}
printf("A: %p\n", txt->point);
}
Main-function (testing purposes only):
int main(int argc, char* argv[])
{
void* memory = malloc(10000);
char* a = "hei pa deg din trekkbasun";
text_t* txt;
int memoverwritten;
txt = text_init(memory, 10000);
memoverwritten = text_store_entry(txt, a, (size_t)26);
printf("got through\n");
return 0;
}
The problem most probably is due to the initialization of structures of type struct text_storage. Such structures contain three pointers to text. Each pointer should be initialized, possibly with a malloc. Your text_init function does not do that properly.
In fact, the place where the start pointer is stored overlaps with the first bytes of the memory that you want to use.
I'm guessing that you need a structure like this:
typedef struct text_storage {
char* start;
char* point;
char* end;
char* data;
} text_t;
initialized with a function like this:
text_t text_init(void *memory, size_t size)
{
text_t to_return;
to_return.data = (char *) memory;
to_return.start = to_return.data;
to_return.end = to_return.start + size;
to_return.point = to_return.start;
return to_return;
}
Print txt->point in the loop and see the point at which it changes. I'm guessing it changes when assigning to txt->point[0]. I'm not fully familiar with printf, so I'm not sure what it's printing out for you, but the name of an array references the first location. If printf is printing out a pointer, txt->point[i] is always a char pointer, and printf may be dereferencing txt->point, which will get it the first entry, and then showing the address there, which you do assign when you change the point to input[i].
Related
I am trying to compile and run in my desk an answers in one of the problems of leetcode, this 1 only for practice and learning proposes, but when i trying to run in a specific line of code there are the issue, with double pointers.
int **vale=(int**)malloc(n*sizeof(int*));
//*vale=(int*)malloc(m*sizeof(int*));
vale = spiralMatrix(m, n, Lista, ptr, vale);}
the problem is when the code reach the line of *returnColumnSizes the code crash.
i know that a double pointer is like a matrix, and for use then we nned to allocate the memory, so is for that i am allocating the double pointer first. So now i can send it to the function but it doesn't work. what is that i doing wrong?
int** spiralMatrix(int m, int n, struct ListNode* head, int* returnSize, int** returnColumnSizes){
*returnSize = m;
*returnColumnSizes = (int*)malloc(m*sizeof(int)); ---> this crash
int **res = (int**)malloc(m*sizeof(int*));
thanks!
To avoid the XY Problem, I won't try to answer your LeetCode question. Instead, we will discuss your topic's central question, "How can I Correctly Pass this double pointer to a function in C".
Double pointer means simply an address that point to another pointer. For example, let's say we have a simple pointer, char* foo = "Hello", if we pass foo to a function, we are giving the address of "Hello", But what if we want to pass foo itself, here the concept of the double-pointer becomes handy, char** bar = &foo, now, if we pass bar, we are passing the address of foo and not "Hello" this time.
Full Example:
#include <stdio.h>
void change_by_pointer(char* s) {
s = "One";
}
void change_by_double_pointer(char** s) {
*s = "Double";
}
int main() {
char* foo = "Hello";
printf("foo = %s\n", foo);
// Change by pointer
change_by_pointer(foo);
printf("foo = %s\n", foo);
// Change by double pointer
char** bar = &foo;
change_by_double_pointer(bar); // Or change_by_double_pointer(&foo);
printf("foo = %s\n", foo);
return 0;
}
Output:
foo = Hello
foo = Hello
foo = Double
Finally, I'm not sure what you are trying to do with spiralMatrix() but based on the params datatypes, this is how you deal with it.
#include <stdio.h>
// Please ignore the behavior of this function.
// This is just an example of how you deal with double-pointers.
int** spiralMatrix(int m, int n, struct ListNode* head, int* returnSize, int** returnColumnSizes){
*returnSize = m;
*returnColumnSizes = malloc(m * sizeof(int));
**returnColumnSizes = 3;
int **res = returnColumnSizes;
return res;
}
int main() {
int returnSize = 1;
int* returnColumnSizes = NULL;
printf("returnSize = %d\n", returnSize);
printf("Calling spiralMatrix()...\n");
int** Res = spiralMatrix(2, 0, NULL, &returnSize, &returnColumnSizes);
printf("returnSize = %d\n", returnSize);
printf("returnColumnSizes = %d\n", *returnColumnSizes);
printf("Res = %d\n", **Res);
return 0;
}
Output:
returnSize = 1
Calling spiralMatrix()...
returnSize = 2
returnColumnSizes = 3
Res = 3
My coding assignments came with it's header file, meaning we need to use the same data types, and not vary anything.
There is a lot of pointers, (mainly a lot of void *). Meaning things are confusing, more than difficult.
we have to do a separate function, just to increment the value referenced by a pointer. But given the nature of program, I don't want to constantly make new pointers.
The code is as follows:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void* intal_create(const char* );
void* intal_increment(void* );
void *intal_create(const char* str)
{
int a;
a=atoi(str);
return &a;
}
void *intal_increment(void *intal)
{
int *a= (int *)intal;//new pointer;
++*a;
//value referenced has been incremented;
*(int *)intal=*a;
return intal;
}
int main()
{
int * x;// void * return a pointer, need a pointert to int to pick it up
char *dummy;
gets(dummy);
x=(int *)intal_create(dummy);
printf("integer return is %d\n",*(int *)x);
printf("address stored is %p\n",(int *)x);
x=(int *)intal_increment(x);
printf("integer return is %d\n",*(int *)x);
printf("address stored is %p\n",(int *)x);
}
I wanted x to be the parameter called, and also for it to store the return value. The printf address is merely for my understanding.
The segmentation faults never end, and from my understanding, I'm just returning a pointer and asking a pointer to stop the return pointer
By incorporating all the comments. Mainly allocating memory to dummy before passing it gets() function and allocating memory in heap for the return pointer of intal_create.These two fixes solve the issue. Have a look at the following code for reference.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void* intal_create(const char* );
void* intal_increment(void* );
void *intal_create(const char* str)
{
int *a = (int *)malloc(sizeof(int));
*a = atoi(str);
return a;
}
void *intal_increment(void *intal)
{
//Here i am not allocating
int *a = (int *)intal;//new pointer;
(*a)++;
return intal;
}
int main()
{
int * x;// void * return a pointer, need a pointert to int to pick it up
char dummy[20] = {0};
fgets(dummy,5,stdin);
x = (int *)intal_create(dummy);
printf("integer return is %d\n",*x);
printf("address stored is %p\n",(void*)x);
x=(int *)intal_increment(x);
printf("integer return is %d\n",*x);
printf("address stored is %p\n",(void *)x);
//Make sure you deallocate the memory allocated in the intal_create function.
free(x);
}
There is some code piece right here below:
main ()
{
char in[8];
char out[255];
iconv_t cd;
cd = iconv_open("gb18030", "utf-8");
...
char *p_in = in;
char *p_out = out;
size_t inlen = strlen(in);
size_t outlen = sizeof(out);
if (iconv(cd, &p_in, &inlen, &p_out, &outlen) < 0)
{
...
return -1
}
...
return 0;
}
I can't totally understand the 2nd and 3rd parameters of the call to iconv. Why should that be ** pointer not the * pointer as the input? Can anyone explain the cases in C when the ** pointer should be used?
Pointer to pointer is used where the passed pointer is need to be modified in the called function and that modification need to be seen in the caller function. This is required because in C arguments are passed by value. So, when an argument is passed to a function then it simply copied to the function's parameter and created a local copy having block scope. Any change to that variable will not be seen in the argument that has been passed.
void foo(in x){
x = 10;
}
int main(void){
int x = 5;
foo(x)
printf("%d\n", x); // x will be 5
}
Same happens with pointers
void bar(char *p){
p = "foobar";
}
int main(void){
char *p = NULL;
bar(p);
if(p)
printf("p is pointing to %s\n", p);
else
printf("p is NULL\n"); // This will
}
Using a pointer to pointer will do the desired job (pointing p to the string "foobar"
void bar(char **p){
*p = "foobar";
}
int main(void){
char *p = NULL;
bar(&p);
if(p)
printf("p is pointing to %s\n", p);
else
printf("p is NULL\n"); // This will
}
Another use is when an array of string is need to passed to a function. Like
int main(int argc, char **argv)
or
void print_fruits(char **fruits, size_t len){
for(int i = 0; i < len; i++)
printf("%s\n", fruits[i]);
}
int main(void){
char *fruits[5] = {"Apple", "Banana", "Cherry", "Kiwi", "Orange"};
print_fruits(fruits, sizeof(fruits)/sizeof(fruits[0]));
}
Note that in function call print_fruits, fruits in the argument list will decay to pointer to its first element and the expression fruits will become of type char ** after the conversion.
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);
#include <stdio.h>
#include <stdlib.h>
struct Point {
double x;
};
void test(struct Point **a, int len)
{
int i;
printf("a = %p\n", a);
for (i = 0; i < len; ++i)
printf("%f\n", a[i]->x);
}
int main()
{
int i;
int len = 4;
struct Point *P;
P = malloc(len*sizeof(struct Point));
for (i = 0; i < len; ++i) {
P[i].x = i;
printf("%f\n", P[i].x);
}
printf("&P = %p\n", &P);
test(&P, len);
return 0;
}
I am trying to pass an array of structs to a function (I want to pass a pointer to the array, not make a copy). When I try to use the array inside the function, I get an access violation. What is the correct way to do this? What am I doing wrong? a == &P, so it should work, right?
Why's you want a struct Point **? You can rewrite the same as
void test(struct Point *a, int len)
{
//some stuff
printf("%f\n", a[i].x);
}
and call it like
test(P, len);
This way, IMHO, the requirement
I want to pass a pointer to the array
is also met#.
(#) NOTE: To be strict, here we pass the pointer to the first element of the array, however, the behaviour compares equal. Thanks to Mr. #alk for the comment.
Passing &p to function test means that you are passing a pointer to the first element of an array of one element of type struct Point *. Therefore, only a[0] is valid (and hence a[0]->x) and all other a[i] are out of bound access. This will invoke undefined behavior.
Change a[i]->x to a[0][i].x or (*a)[i].x in test function.
Using pointer to pointer in this case is not worthy. This would be of worth using if passed pointer is to be modified in the function and that modification is expected to seen in the caller.
The array should be passed using the parameter struct Point *a. When you increment a the pointer will move by sizeof(struct Point).
void test(const struct Point *a, int len)
{
...
}
Other answers offer you better alternatives.But I'll put this here to help anyone (myself) understand why it is wrong.
I want to pass a pointer to the array,
Taking your requirement literally you do it like this:
void test(size_t len, struct Point (*a)[len])
{
size_t i;
printf("a = %p\n", (void *) a);
for (i = 0; i < len; ++i)
printf("%f\n", (*a)[i].x);
}
And call it like this:
size_t len = 4;
struct Point * p = malloc(len * sizeof *p);
for (i = 0; i < len; ++i) {
p[i].x = i;
printf("%f\n", p[i].x);
}
printf("p = %p\n", (void *) p);
printf("&p = %p\n", (void *) &p);
test(len, &p);
You could also implement the same functionality (looping over the array's elements) by going the way proposed by Sourav Ghosh's answer. You then would pass a pointer to the array's 1st element then, but a pointer to the array itself.