What does this do exactly? [*(char*)p1] - c

I am not used to pointers because I started learning Pascal in high school and now I am upgrading myself to C. My request would be to explain me what should I think when I see something like this [*(char*)p1]. Don't be shy writing me quite a few lines :)
Thank you.
P.S. p1 is a const void *. To be more accurate.

Assuming that [*(char*)p1] is an array designator, (char*) is used to cast p1 to make p1 char * type. Then * is used to dereference it to use value at the address (p1 points to) as index to some array.

void *p1;// pointer to void or generic pointer; might be used when you want to be flexible about the data type
(char*)p1; //typecast to a char pointer; you address the memory locatuion pointed to by P1 as char
*(char*)p1; //the value at the location pointed to by p1.
Hope this helps.

[*(char*)p1] is somewhat incomplete, there needs to be a variable name in front of it for the array subscription to make sense, such as for example foo[*(char*)p1].
In that case, it means:
convert p1 to pointer-to-char
dereference this pointer (giving a char value)
use this value as index to look up in an array
Note that using a char as index will make most compilers unhappy and cause it to emit a warning. That is because most often when a char is used as an index, it happens by error, not by intent, and also because it is implementation-defined whether char is signed or unsigned (so it is inherently non-portable, and you may end up indexing out of bounds by accident, if you assume the wrong one).

(char*)p1 is a typecast. This means, for this statement, we're treating p1 as a pointer to a character.
*(char*)p1 dereferences p1, interpreting it as a char type due to the typecast (char*). A pointer points to a memory location, and dereferencing that pointer returns the value at the location in memory p1 points to.
[*(char*)p1] ... Array access? is this a snippet from something larger?
This void* to someOtherType* conversion is common in C code, because malloc, used to allocate memory dynamically, returns void*.

Related

Why are pointer type casts necessary?

I cannot understand why are pointer type casts necessary, as long as pointers point to an address and their type is important only when it comes to pointer arithmetic.
That is to say, if I encounter the next code snippet:
int a = 5; then both
char*b = (char*)&a; and int*c = (int*)&a
point to the very same memory location.
Indeed, when executing char*b = (char*)&a part of the memory contents may be lost, but this is due to the type of b is char* which can store only sizeof(char) bytes of memory, and this could be done implicitly.
The pointer type is important when you dereference it, since it indicates how many bytes should be read or stored.
It's also important when you perform pointer arithmetic, since this is done in units of the size that the pointer points to.
The type of the pointer is most important when you dereference the pointer.
The excerpt
char *b = (int*)&a;
is wrong because int * cannot be assigned to char *. You meant char *b = (char *)&a;. The C standard says you need an explicit cast because the types are not compatible. This is the "yeah yeah, I know what I am doing".
The excerpt
int*c = (int*)&a;
is right, but &a is already a pointer to an int, so the cast will do no conversion, therefore you can write it as int *c = &a;.
as long as pointers point to an address and their type is important only when it comes to pointer arithmetic.
No, not only for pointer arithmetic. Its also important for accessing the data pointed by the pointer, the wrong way of accessing as in your example leads to improper results.
when executing charb = (int)&a part of the memory contents may be lost, but this is due to the type of b is char* which can store only sizeof(char) bytes of memory,
First of all, that is wrong to do (unless we really need to extract 1-byte out of 4-bytes)
Second, the application of pointer cast is mostly used w.r.t void*(void pointers) when passing data for a function which can handle many different type, best example is qsort

free a cast pointer

I want to know if it is ok to free() a pointer cast to another type.
For instance if I do this:
char *p = malloc (sizeof (int));
int *q = (int *)p;
free (q);
I get no warning on gcc (-Wall).
On linux, the man pages on free says it is illegal to call free on a pointer that was not returned by malloc(), calloc() or realloc(). But what happens if the pointer was cast to another type in between?
I ask this because I read that the C standard does not require different pointer types (e.g. int* and char*) to have the same size, and I fail to understand how this is possible since they both need to be convertible to a void* in order to call the malloc/free functions.
Is the above code legal?
It's probably safe, but it's not absolutely guaranteed to be safe.
On most modern systems, all pointers (at least all object pointers) have the same representation, and converting from one pointer type to another just reinterprets the bits that make up the representation. But the C standard doesn't guarantee this.
char *p = malloc (sizeof (int));
This gives you a char* pointer to sizeof (int) bytes of data (assuming malloc() succeeds.)
int *q = (int *)p;
This converts the char* pointer to an int* pointer. Since int is bigger than char, an int* pointer could require less information to indicate what it points to. For example, on a word-oriented machine, an int* might point just point to a word, while a char* has to contain a word pointer and an offset that indicates which byte within the word it points to. (I've actually worked on a system, the Cray T90, that worked like this.) So a conversion from char* to int* can actually lose information.
free (q);
Since free() takes an argument of type void*, the argument q is implicitly converted from int* to void*. There is no guarantee in the language standard that converting a char* pointer to int*, and then converting the result to void*, gives you the same result as converting a char* directly to a void*.
On the other hand, since malloc() always returns a pointer that's correctly aligned to point to any type, even on a system where int* and char* have different representations, it's unlikely to cause problems in this particular case.
So your code is practically certain to work correctly on any system you're likely to be using, and very very likely to work correctly even on exotic systems you've probably never seen.
Still, I advise writing code that you can easily demonstrate is correct, by saving the original pointer value (of type char*) and passing it to free(). If it takes several paragraphs of text to demonstrate that your code is almost certainly safe, simplifying your assumptions is likely to save you effort in the long run. If something else goes wrong in your program (trust me, something will), it's good to have one less possible source of error to worry about.
A bigger potential problem with your code is that you don't check whether malloc() succeeded. You don't do anything that would fail if it doesn't (both the conversion and the free() call are ok with null pointers), but if you refer to the memory you allocated you could be in trouble.
UPDATE:
You asked whether your code is legal; you didn't ask whether it's the best way to do what you're doing.
malloc() returns a void* result, which can be implicitly converted to any pointer-to-object type by an assignment. free() takes a void* argument; any pointer-to-object type argument that you pass to it will be implicitly converted to void*. This round-trip conversion (void* to something_else* to void*) is safe. Unless you're doing some kind of type-punning (interpreting the same chunk of data as two different types), there's no need for any casts.
Rather than:
char *p = malloc (sizeof (int));
int *q = (int *)p;
free (q);
you can just write:
int *p = malloc(sizeof *p);
...
free(p);
Note the use of sizeof *p in the argument to malloc(). This gives you the size of whatever p points to without having to refer to its type explicitly. It avoids the problem of accidentally using the wrong type:
double *oops = malloc(sizeof (int));
which the compiler likely won't warn you about.
Yes, it's legal. free() takes a void pointer (void*), so the type doesn't matter. As long as the pointer passed to was returned by malloc/realloc/calloc it's valid.
Yes the pointer is not changed, the cast is merely how the compiler interprets the bunch of bits.
edit: The malloc call returns an address in memory ie a 32(or 64) bit number.
The cast only tells the compiler how to interpret the value stored at that address, is it a float, integer, string etc, and when you do arithmatic on the address how big a unit should it step in.
The code is legal, however it is not necessary. Since pointers only point to the address where data is stored, there is no need to allocate space, or subsequently free it.

C Language: When you dereference a "pointer to a pointer to int", what is supposed to be returned?

Let's say you have:
void *a = //some address;
*((int **)(char*)a) = 5
I'm not really clear on what the second line is supposed to be doing... I know that 'a' is casted to a pointer to a char, and then eventually casted to a pointer to a pointer to an int, but it was unclear what dereferencing a pointer to a pointer to an int actually does...
This would be very helpful. Thanks
it is storing the value 5 in "some address", but more precisely, it is storing the value 5 widened to the machine address size in those many bytes starting at "some address".
e. g. if it is a 64-bit machine, it is storing the value 0x0000000000000005 at the 8 bytes starting at "some address"
i don't see why it is doing it in such a complicated way, but who are we to judge the intentions of a programmer hard at work at the end of a long day.
If you dereference a pointer to a pointer to an int you'll get a pointer to an int. Dereferencing means you'll get the object it was pointing at which is in this case a pointer to an int.
Here's an interesting article that explains how to interpret more complex declarations
It's a nonsense, obfuscated way of writing:
void* a = (void*)5;
As we can tell, original code doesn't make any sense. Here is what it does:
Assign an address to a.
Typecast a from void pointer to char pointer.
Wildly typecast the char pointer to a pointer-to-pointer to int.
Take the contents of the pointer-to-pointer, ie the address where an int should be stored.
This address will be stored where a currently stores its address, overwriting it with the address 5.
EDIT: Btw, note that implicit integer to pointer casts are not allowed in C (C99 6.5.4 §3). There must be a cast like in the code above.

memcpy fails but assignment doesn't on character pointers

Actually, memcpy works just fine when I use pointers to characters, but stops working when I use pointers to pointers to characters.
Can somebody please help me understand why memcpy fails here, or better yet, how I could have figured it out myself. I am finding it very difficult to understand the problems arising in my c/c++ code.
char *pc = "abcd";
char **ppc = &pc;
char **ppc2 = &pc;
setStaticAndDynamicPointers(ppc, ppc2);
char c;
c = (*ppc)[1];
assert(c == 'b'); // assertion doesn't fail.
memcpy(&c,&(*ppc[1]),1);
if(c!='b')
puts("memcpy didn't work."); // this gets printed out.
c = (*ppc2)[3];
assert(c=='d'); // assertion doesn't fail.
memcpy(&c, &(*ppc2[3]), 1);
if(c != 'd')
puts("memcpy didn't work again.");
memcpy(&c, pc, 1);
assert(c == 'a'); // assertion doesn't fail, even though used memcpy
void setStaticAndDynamicPointers(char **charIn, char **charIn2)
{
// sets the first arg to a pointer to static memory.
// sets the second arg to a pointer to dynamic memory.
char stat[5];
memcpy(stat, "abcd", 5);
*charIn = stat;
char *dyn = new char[5];
memcpy(dyn, "abcd", 5);
*charIn2 = dyn;
}
your comment implies that char stat[5] should be static, but it isn't. As a result charIn points to a block that is allocated on the stack, and when you return from the function, it is out of scope. Did you mean static char stat[5]?
char stat[5];
is a stack variable which goes out of scope, it's not // sets the first arg to a pointer to static memory.. You need to malloc/new some memory that gets the abcd put into it. Like you do for charIn2
Just like what Preet said, I don't think the problem is with memcpy. In your function "setStaticAndDynamicPointers", you are setting a pointer to an automatic variable created on the stack of that function call. By the time the function exits, the memory pointed to by "stat" variable will no longer exist. As a result, the first argument **charIn will point to something that's non-existent. Perhaps you can read in greater detail about stack frame (or activation record) here: link text
You have effectively created a dangling pointer to a stack variable in that code. If you want to test copying values into a stack var, make sure it's created in the caller function, not within the called function.
In addition to the definition of 'stat', the main problem in my eyes is that *ppc[3] is not the same as (*ppc)[3]. What you want is the latter (the fourth character from the string pointed to by ppc), but in your memcpy()s you use the former, the first character of the fourth string in the "string array" ppc (obviously ppc is not an array of char*, but you force the compiler to treat it as such).
When debugging such problems, I usually find it helpful to print the memory addresses and contents involved.
Note that the parenthesis in the expressions in your assignment statements are in different locations from the parenthesis in the memcpy expressions. So its not too suprising that they do different things.
When dealing with pointers, you have to keep the following two points firmly in the front of your mind:
#1 The pointer itself is separate from the data it points to. The pointer is just a number. The number tells us where, in memory, we can find the beginning of some other chunk of data. A pointer can be used to access the data it points to, but we can also manipulate the value of the pointer itself. When we increase (or decrease) the value of the pointer itself, we are moving the "destination" of the pointer forward (or backward) from the spot it originally pointed to. This brings us to the second point...
#2 Every pointer variable has a type that indicates what kind of data is being pointed to. A char * points to a char; a int * points to an int; and so on. A pointer can even point to another pointer (char **). The type is important, because when the compiler applies arithmetic operations to a pointer value, it automatically accounts for the size of the data type being pointed to. This allows us to deal with arrays using simple pointer arithmetic:
int *ip = {1,2,3,4};
assert( *ip == 1 ); // true
ip += 2; // adds 4-bytes to the original value of ip
// (2*sizeof(int)) => (2*2) => (4 bytes)
assert(*ip == 3); // true
This works because the array is just a list of identical elements (in this case ints), laid out sequentially in a single contiguous block of memory. The pointer starts out pointing to the first element in the array. Pointer arithmetic then allows us to advance the pointer through the array, element-by-element. This works for pointers of any type (except arithmetic is not allowed on void *).
In fact, this is exactly how the compiler translates the use of the array indexer operator []. It is literally shorthand for a pointer addition with a dereference operator.
assert( ip[2] == *(ip+2) ); // true
So, How is all this related to your question?
Here's your setup...
char *pc = "abcd";
char **ppc = &pc;
char **ppc2 = &pc;
for now, I've simplified by removing the call to setStaticAndDynamicPointers. (There's a problem in that function too—so please see #Nim's answer, and my comment there, for additional details about the function).
char c;
c = (*ppc)[1];
assert(c == 'b'); // assertion doesn't fail.
This works, because (*ppc) says "give me whatever ppc points to". That's the equivalent of, ppc[0]. It's all perfectly valid.
memcpy(&c,&(*ppc[1]),1);
if(c!='b')
puts("memcpy didn't work."); // this gets printed out.
The problematic part —as others have pointed out— is &(*ppc[1]), which taken literally means "give me a pointer to whatever ppc[1] points to."
First of all, let's simplify... operator precedence says that: &(*ppc[1]) is the same as &*ppc[1]. Then & and * are inverses and cancel each other out. So &(*ppc[1]) simplifies to ppc[1].
Now, given the above discussion, we're now equipped to understand why this doesn't work: In short, we're treating ppc as though it points to an array of pointers, when in fact it only points to a single pointer.
When the compiler encounters ppc[1], it applies the pointer arithmetic described above, and comes up with a pointer to the memory that immediately follows the variable pc -- whatever that memory may contain. (The behavior here is always undefined).
So the problem isn't with memcopy() at all. Your call to memcpy(&c,&(*ppc[1]),1) is dutifully copying 1-byte (as requested) from the memory that's pointed to by the bogus pointer ppc[1], and writing it into the character variable c.
As others have pointed out, you can fix this by moving your parenthesis around:
memcpy(&c,&((*ppc)[1]),1)
I hope the explanation was helpful. Good luck!
Although the previous answers raise valid points, I think the other thing you need to look at is your operator precedence rules when you memcpy:
memcpy(&c, &(*ppc2[3]), 1);
What happens here? It might not be what you're intending. The array notation takes higher precedence than the dereference operator, so you first attempt perform pointer arithmetic equivalent to ppc2++. You then dereference that value and pass the address into memcpy. This is not the same as (*ppc2)[1]. The result on my machine is an access violation error (XP/VS2005), but in general this is undefined behaviour. However, if you dereference the same way you did previously:
memcpy(&c, &((*ppc2)[3]), 1);
Then that access violation goes away and I get proper results.

What is the meaning of "wild pointer" in C?

Can anybody tell me, the meaning of wild pointer in C, how to obtain it and is this available in C++?
The standard does not define or use the term "wild". I'd be careful "correcting" other people's opinions about what it means, and I'd especially avoid quoting random non-normative internet junk to support my position.
To me, it would mean a pointer that neither refers to a legitimate object, nor is NULL. Possible sources of these types of pointer values might include uninitialized pointer objects, objects that have ceased to exist, computed pointer values, improperly aligned pointer values, accidental corruption of the pointer itself, or what it pointed to, etc.
int main(void)
{
int *p; // uninitialized and non-static; value undefined
{
int i1;
p = &i1; // valid
} // i1 no longer exists; p now invalid
p = (int*)0xABCDEF01; // very likely not the address of a real object
{
int i2;
p = (int*)(((char*)&i2) + 1); // p very likely to not be aligned for int access
}
{
char *oops = (char*)&p;
oops[0] = 'f'; oops[1] = 35; // p was clobbered
}
}
and so on, and so forth. There are all kinds of ways to get an invalid pointer value in C. My favourite has got to be the guy who tried to "save" his objects by writing their addresses to a file. Strangely, when he read back those pointer values during a different run of the program, they didn't point to his objects any more. Fancy, that.
But that's just what wild means to me. Since it's not a normative term, it means whatever the person who spoke or wrote it meant it to mean. Ask him or her.
A wild pointer in C is a pointer that has not been initialised prior to its first use.
From Wikipedia:
Wild pointers are created by omitting
necessary initialization prior to
first use. Thus, strictly speaking,
every pointer in programming languages
which do not enforce initialization
begins as a wild pointer.
This most often occurs due to jumping
over the initialization, not by
omitting it. Most compilers are able
to warn about this.
eg
int f(int i)
{
char* dp; //dp is a wild pointer
...
}
It is not s standard term. It is normally used to refer to the pointers pointing to invalid memory location.
int *p;
*p = 0; //P is a wild pointer
Or
int *p = NULL;
{
int a;
p = &a; // as soon as 'a' goes out of scope,'p' is pointing to invalid location
}
*p = 0;
To get a wild (aka dangling) pointer you:
Create an object
Create a pointer to that object
Delete the object
Forget to set the pointer to null
The pointer is now classed as "wild" as it's pointing to an arbitrary piece of memory and using it in this state could cause problems with your program.
A pointer which is not initialized with any address is called as a wild pointer. It may contain any garbage address, so dereferencing a wild pointer is dangerous
A wild pointer is any pointer that is used (particularly as an L_value {ie (*pointer) = x } ) while having a value that is either not correct or no longer correct. It could also be used to describe the using of memory that is not defined as a pointer as a pointer (possibly by having followed a wild pointer or by using outdated structure definitions).
There's no official definition. It's just words that we use when referring to certain pointer errors or the results of those errors.
Wiki
It's a pointer to either uninitialized object or an object with a bad state. using this pointer will cause trouble. the wiki is a good source of explanation.
Wild pointer is a pointer that doesn’t point to either a valid object (of the indicated type, if applicable), or to a distinguished null value, if applicable.
Read more about Wild Pointer here
Wild pointer is a pointer which declaration is present but it has not been defined yet.Means we have declare a pointer -
data_type *ptr; //but not define which address it is containing
*ptr=100//wild pointer does not point to any valid address.so we will get ERROR
printf("ptr:%d",ptr);//we will get:0(in gcc compiler)
a ponter which not have locating any data type varable that varable is call the wild pointer
Uninitialized pointer is called Wild Pointer.
Suppose if you try
int *p; //pointing to any random or unknown location.
*p= 16; /Some unknown memory location is being corrupted.This should never be done./
This can create a great threat to your program. B'Coz because they point to some arbitrary memory location and changing the content of that location may cause a program to crash or behave badly.

Resources