I am wondering why the following two functions return different results:
The result of GetPtr is always NULL, whereas GetPtr2 returns a pointer to the parameter, the intended behavior.
#include <stdio.h>
unsigned char ** GetPtr(unsigned char *ptr)
{
return &ptr;
}
unsigned char ** GetPtr2(unsigned char *ptr)
{
unsigned char **ptr2 = &ptr;
return ptr2;
}
int main()
{
unsigned char *test = (unsigned char *) malloc(10 * sizeof(unsigned char));
printf("%p \n", GetPtr(test));
printf("%p \n", GetPtr2(test));
free(test);
return 0;
}
Thanks in advance for any help!
unsigned char ** GetPtr(unsigned char *ptr)
{
return &ptr;
} // <-- scope of ptr ends here
You are using the address of an out-of-scope variable. As the Monty Python skit had it, It's an ex-parrot.
This function returns the address of a local variable. When that address is received by the caller, the variable whose address it is will no longer be in scope.
Related
The compareStrings is going to compare two strings. The code below works fine when the void pointer is cast to char pointer.
int compareStrings(void *value1, void *value2) {
const char *str1, *str2;
str1 = (char *)value1;
str2 = (char *)value2;
return strcmp(str1, str2);
}
However, when I cast the type to pointer to pointer to a char, the code dumps segmentation fault error which I think, reasonably, it should not.
int compareStrings(void *value1, void *value2) {
const char **str1, **str2;
str1 = (char **)value1;
str2 = (char **)value2;
return strcmp(*str1, *str2);
}
Can anyone explain the problem with the second function?
UPDATE:
The complete code is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compare(void *value1, void *value2);
int binarySearch(void **array, int size, void *value,
int(*compareFunc)(void *, void *));
int compareStrings(void *value1, void *value2);
int binarySearch(void **array, int size, void *value,
int(*compareFunc)(void *, void *)) {
int low, mid, high, compareResult;
low = 0;
high = size;
while (low < high) {
mid = low + ((high - low) / 2);
compareResult = (*compareFunc)(array[mid], value);
if (compareResult < 0) {
low = mid + 1;
} else {
high = mid;
}
}
return low;
}
int compareStrings(void *value1, void *value2) {
const char *str1, *str2;
str1 = (char *)value1;
str2 = (char *)value2;
return strcmp(str1, str2);
}
int main() {
int nElements, maxStringLen, index;
char **stringArray;
char *sToFind;
nElements = 10;
maxStringLen = 100;
sToFind = NULL;
stringArray = malloc(sizeof(char *) * nElements);
for (int i = 0; i < nElements; i++) {
stringArray[i] = malloc(sizeof(char) * maxStringLen);
sprintf(stringArray[i], "sample%d", i+1);
}
sToFind = "sample3";
index = binarySearch((void **)stringArray, nElements, sToFind, compareStrings);
if (index >= nElements) {
printf ("ERROR: value %s not found at index %d\n", sToFind, index);
}else{
printf("item found at index %d!\n", index);
}
for(int i = 0; i < nElements; i++) {
free(stringArray[i]);
}
free(stringArray);
return 0;
}
when I cast the type to pointer to pointer to a char, the code dumps
segmentation fault error which I think, reasonably, it should not.
When you cast the pointer to pointer that operation does not affect the casted pointer. It still points to same memory.
This is demonstrated by printout 3.
1. Original string addresses:
Address of str1= 0x55bc799fea65
Address of str2= 0x55bc799fea6a
3. The addresses after casting `(char **)` do not change:
Address of (char **)value1= 0x55bc799fea65
Address of (char **)value2= 0x55bc799fea6a
Casting is not & or * operation!
When you do dereferencing by * that operation dereferences the value of the original pointer.
The result is not what you want:
4.
Address of *(char **)value1= 0x343332 00 34 33 32 31
Address of *(char **)value2= 0x31 00 35 34 33 32
These are not the addresses as you expected but the values of the strings.
Those values are not the valid addresses!
When you try to use them as the string addresses you will get segmentation fault in the strcmp function.
Take a look at the demo program:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void print_addresses(char *nr, char *d1, void *a1, char *d2, void *a2)
{
printf("%s.\nAddress of %s= %p\nAddress of %s= %p\n\n",nr, d1, a1, d2, a2);
}
int compareStrings1 (void *value1, void *value2)
{
char *str1, *str2;
str1 = (char *) value1;
str2 = (char *) value2;
//2.
print_addresses("2", "str1", str1, "str2", str2);
return strcmp(str1, str2);
}
int compareStrings2(void *value1, void *value2) {
char **str1, **str2;
char **s1, **s2;
str1 = (char **)value1; // warning: assignment from incompatible pointer type
str2 = (char **)value2; // warning: assignment from incompatible pointer type
//3. Addresses after casting `(char **)` do not change:
print_addresses( "3", " (char **)value1", str1, " (char **)value2", str2); // str1,str2 are still pointing to the original strings!
//---------------------------------------------------------------------------------------------
print_addresses( "4", "*(char **)value1", *str1, "*(char **)value2", *str2); // '*' this dereferences the address to the value of the first character
printf("(*str1)= %c\n", *str1); //'*' this dereferences the address to the value of the first character
printf("(*str2)= %c\n\n", *str2); //'*' this dereferences the address to the value of the first character
// Now:
s1 = (char **) &value1; // '&'' gives us pointer to pointer
s2 = (char **) &value2; // '&'' gives us pointer to pointer
//5.
print_addresses( "5", " (char **) & value1" , s1, " (char **) & value2", s2); // pointer to pointer address
//6.
print_addresses( "6", "*(char **) & value1", *s1, "*(char **) & value2", *s2); // dereferencing pointer to pointer
return strcmp(*s1, *s2); // OK!
}
int main()
{
char *str1 = "1234";
char *str2 = "2345"; // 5 bytes
//1. Original string addresses:
print_addresses("1", "str1", str1, "str2", str2);
int res1 = compareStrings1(str1, str2);
int res2 = compareStrings2(str1, str2);
return 0;
}
Output:
1.
Address of str1= 0x55bc799fea65
Address of str2= 0x55bc799fea6a
2.
Address of str1= 0x55bc799fea65
Address of str2= 0x55bc799fea6a
3.
Address of (char **)value1= 0x55bc799fea65
Address of (char **)value2= 0x55bc799fea6a
4.
Address of *(char **)value1= 0x3433320034333231
Address of *(char **)value2= 0x310035343332
(*str1)= 1
(*str2)= 2
5.
Address of (char **) & value1= 0x7ffd061f56b8
Address of (char **) & value2= 0x7ffd061f56b0
6.
Address of *(char **) & value1= 0x55bc799fea65
Address of *(char **) & value2= 0x55bc799fea6a
I hope it helps.
The problem is that your are casting a pointer and not transforming it into a pointer to a pointer.
The cast (char **) just change the type of the following expression, it do not transform it. So the original and the resulting pointer are still the same pointer (they point the same place in memory), just the type is different. So both points to a string. But with your cast you lie to the compiler: you are telling him that you know what you are doing, and that the pointer point to a pointer to a string.
So you get a segmentation fault: the pointer point to a text and not to a pointer to a text: you are deferencing a string and oops.
You should have written:
str1 = (char **)&value1;
Note: your const char * is probably wrong. You are saying that the string is constant (and only the first one), not that the variable is constant (which should be written char * const).
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 want to pass a char pointer to a function and have it set the value and pass it back. Here is my attempt but the printf prints garbage, where am I going wrong?
int a() {
char *p;
b(p);
printf("%s", p);
return 0;
}
int b(char * ptr) {
ptr = "test string";
return 0;
}
Pass a reference to the pointer.
int b(char **ptr)
{
*ptr = "Print statement";
//your code
}
//call
b(&p);
If you want to set the value of the pointer and pass it back, then b() needs to return a pointer:
int a(void) {
char *p = NULL;
p = b(p);
printf("%s", p);
return 0;
}
char * b(char * ptr) {
ptr = "test string";
return ptr;
}
Here p is initialized to NULL to avoid undefined behavior from passing an uninitialized value to a function. You could also initialize p to another string literal. Inside b, ptr is a copy of the pointer p that was passed to b. When you reassign the value stored in ptr to the address of the string literal "test string", the original pointer p is unchanged. By passing ptr back to the calling function, and reassigning p to the return value of b, the calling function can use the updated value.
As #M.M points out in the comments, this is somewhat redundant. The function b() could instead declare a pointer of its own, initialized to a string literal:
int a(void) {
char *p = b();
printf("%s", p);
return 0;
}
char * b(void) {
char *ptr = "test string";
return ptr;
}
Ii've a big Problem. I write a static Library, what I would like to use in a Software. My Problem is: if you give a pointer from a function out of the library back to the main program the pointer have not the value from the pointer in the Library. Is there an issue, if you give pointer from an Libay.a back to the main.c
Main.c:
#include <stdio.h>
int main(int argc, const char * argv[]) {
char *ptr;
Prallow_its(ptr, 122);
printf("%s", ptr);
return 0;
}
Prallow.c from Prallow.a
[...]
char *Prallow_its(char *ptr, int i){
static char buffer[255];
sprintf(buffer, "%u", i);
ptr = buffer;
return ptr;
}
[...]
It's fine to return the pointer to your static buffer from the library. It lives in the same address space as the rest of your program. Of course, it's not thread-safe but that's a separate issue.
The real problem is the way you are calling it:
char *ptr; // <-- ptr uninitialised
Prallow_its(ptr, 122); // <-- return value ignored
printf("%c", ptr); // <-- ptr still uninitialised
You should instead do this:
ptr = Prallow_its( ptr, 122 );
Alternatively, you could allow ptr to be modified by Prallow_its. In that case, it must be defined like this:
char *Prallow_its( char **ptr, int i )
{
static char buffer[255];
sprintf(buffer, "%u", i);
*ptr = buffer;
return *ptr;
}
And called like this:
Prallow_its( &ptr, 122 );
C passes by value, so the line ptr = buffer in the library function does not change the value of ptr in main.
Also, the library function doesn't do anything with the pointer that's passed in, so there's no reason to pass the pointer. The code in Main.c should be
int main(int argc, const char * argv[])
{
char *ptr = Prallow_its(122);
printf("%s", ptr);
return 0;
}
and the code in Prallow.c should be
char *Prallow_its(int i)
{
static char buffer[255];
sprintf(buffer, "%u", i);
return buffer;
}
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);