Related
I'm confused about these errors. The str1 is a string that is being passed but I get the a warning at the compare and and error at the if statement
int stringcmp(void* str1, void* str2) {
int a = strlen(str1);
int b = strlen(str2);
int x;
if ( a < b ) {
x = a;
} else {
x = b;
}
int c = 0;
while ( c < x ) {
if (str1[c] < str2[c]) { //errors happen here
return 0;
}
if (str1[c] > str2[c]) {
return 1;
}
c++;
}
if ( a == x ) {
return 0;
}
return 1;
}
Your function receives void* arguments, so in the line you pointed you are dereferencing pointers to void and that is why you get the warnings. I am not sure why you are receiving the value not ignore as it ought to be because that means that you are assigning the value of a function that returns void, and that is not the case of strlen (which is the only one you are calling).
And you should also receive an error in the calls to strlen when passing to it a void* parameter.
So you have to change your function's signature to
int stringcmp(const char* str1, const char* str2);
to suppress the warnings and be able to call strlen on the strings.
Dereferencing void * makes no sense, ever. In C, void means "no type"/"nothing", if you have void *p;, what is *p supposed to be?
In C, void * is used as a generic pointer type, "pointer to anything". To use p above, you must cast it to the type of the object it is pointing at (passed in some other way, unbeknownst to the compiler). E.g.:
int i;
void *p = (void *) &i;
...
int j = *(int *)p;
You know what p points to, the compiler doesn't.
The type void * is often used to pass around opaque data, or to write generic functions (like qsort, it gets an array of unspecified elements and a function that compares them).
That said, as a (misguided) extension GCC allows pointer arithmetic on void *, so that p + 1 is like ((char *)p + 1), it points at the next char position.
Your error arises from the fact that you are attempting to use the array notation str1[c] on a void-pointer. To understand why this is wrong we need to look at what the array notation in C actually means.
Let us assume that we define char* str1. Here we have said that str1 is an address to some place in memory where there is a char.
To get the data that is stored on the address which str1 is referring to we can use *str1.
This is equivalent to saying: "Go to the address that str1 is holding and give me what is stored on that address".
When we use the array notation we can use str1[0], this will be a value fetched from a place in memory where there is an element of the same type that str1 was defined as. It is the same thing as saying *str1 (go to the address that str1 is pointing to and give me the value that is stored there).
An array is just a bunch of data stored in a sequence in memory and strings are just arrays of characters of exactly 1 byte in size stored immediately after one another.
When we say str1[1] we are telling the compiler to move by the size of the type that str1 was defined to be pointing at, in this case 1 byte(char), and then get us whatever is stored at that location. In the case of strings, this should be another char.
Now when we have defined str1 as void*, how would the compiler know how how much it should move in memory to get the next element in the array? Since void has no size it is impossible.
Hopefully you now understand what you need to change in this line to get rid of your errors
int stringcmp(void* str1, void* str2)
EDIT:
What should I do to have a correct code then ?
EDIT2:
Ok, I correct the code below
Context
Fiddling with memcpy.
Linux, 64 bits.
gcc 4.8.x
Code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void d(char ** restrict a, char ** restrict b){
char r[20];
memcpy(r,*a, strlen(*a)+1);
// it is the same thing as before since *c is equivalent to &r (or put simply r).
char *restrict c = malloc(20);
memcpy(c,*a, strlen(*a)+1);
// that one bugs me. why b alone and not *b ??
// EDIT : this is incorrect
memcpy(b,*a, strlen(*a)+1);
// EDIT : this is correct
memcpy(*b,*a, strlen(*a)+1);
printf("pointer c -> hey %s\n",c);
printf("array r -> hey %s\n",r);
// EDIT : this is incorrect
printf("double pointer -> hey %s\n",b);
// EDIT : this is correct
printf("double pointer -> hey %s\n",*b);
}
int main(void)
{
char a[] = "YOU";
char * b = a;
char * c = malloc(20);
d(&b, &c);
return 0;
}
Question
I would like to undertsand why memcpy doesn't complain about me passing double pointer to it, while it needs a pointer only.
I know that with chars *b == &a == a and that an array is referenced by its first member up to '\0'. The problem really is with passing a double pointer to memcpy.
why didn't I have to do
memcpy(*b, *a, strlen(*a)+1);
since memcpy signature is
void * memcpy ( void * destination, const void * source, size_t num );
and first argument is a "Pointer to the destination array where the content is to be copied, type-casted to a pointer of type void*", according to cplusplus.com.
What is the "catch" here please ?
Thanks a lot
Well, a double pointer is a single pointer to single pointer, so it can be passed to a function that expects a void pointer.
It is of course another thing whether or not your code is correct... It's not and works only by coincidence. Note that not only you use memcpy() to write to a wrong location, but you also print the same wrong location of memory as a string in your printf(). The "coincidence" here is that both of these "wrong" locations are the same, so you falsely assumed that it works fine.
Try to really print the right thing and you'll see the mayhem:
printf("double pointer -> hey %s\n",*b);
Consider what would happen if you wanted to copy the representation of a pointer to another one, like this:
char *p;
char *q = NULL;
memcpy(&p, &q, sizeof q);
should the compiler really complain in this case? Nope.
The point is that void * is untyped. It can point to any object type. It's not a constraint that a void * can't point to a pointer-to-pointer. It absolutely can.
As to why it "works": It does not work. It only appears to be working. Because of the invalid pointer operation, the code has undefined behavior, so it can do anything. In the better case, it crashes and makes the problem apparent. In your case, the error remained silent and the program was pretending it worked.
In this answer, the author discussed how it was possible to cast pointers in C. I wanted to try this out and constructed this code:
#include <stdio.h>
int main(void) {
char *c;
*c = 10;
int i = *(int*)(c);
printf("%d", i);
return 1;
}
This compiles (with a warning) and when I execute the binary it just outputs bus error: 10. I understand that a char is a smaller size than an int. I also understand from this post that I should expect this error. But I'd really appreciate if someone could clarify on what is going on here. In addition, I'd like to know if there is a correct way to cast the pointers and dereference the int pointer to get 10 (in this example). Thanks!
EDIT: To clarify my intent, if you are worried, I'm just trying to come up with a "working" example of pointer casting. This is just to show that this is allowed and might work in C.
c is uninitialized when you dereference it. That's undefined behaviour.
Likewise, even if c were initialized, your typecast of it to int * and then a dereference would get some number of extra bytes from memory, which is also undefined behaviour.
A working (safe) example that illustrates what you're trying:
int main(void)
{
int i = 10;
int *p = &i;
char c = *(char *)p;
printf("%d\n", c);
return 0;
}
This program will print 10 on a little-endian machine and 0 on a big-endian machine.
These lines of code are problematic. You are writing through a pointer that is uninitialized.
char *c;
*c = 10;
Change to something like this:
char * c = malloc (sizeof (char));
Then, the following line is invalid logic, and the compiler should at least warn you about this:
int i = *(int*)(c);
You are reading an int (probably 4 or 8 bytes) from a pointer that only has one byte of storage (sizeof (char)). You can't read an int worth of bytes from a char memory slot.
First of all your program has undefined behaviour because pointer c was not initialized.
As for the question then you may write simply
int i = *c;
printf("%d", i);
Integral types with rankes less than the rank of type int are promoted to type int in expressions.
I understand that a char is a smaller size than an int. I also understand from this post that I should expect this error. But I'd really appreciate if someone could clarify on what is going on here
Some architectures like SPARC and some MIPS requires strict alignment. Thus if you want to read or write for example a word, it has to be aligned on 4 bytes, e.g. its address is multiple of 4 or the CPU will raise an exception. Other architectures like x86 can handle unaligned access, but with performance cost.
Let's take your code, find all places where things go boom as well as the reason why, and do the minimum to fix them:
#include <stdio.h>
int main(void) {
char *c;
*c = 10;
The preceding line is Undefined Behavior (UB), because c does not point to at least one char-object. So, insert these two lines directly before:
char x;
c = &x;
Lets move on after that fix:
int i = *(int*)(c);
Now this line is bad too.
Let's make our life complicated by assuming you didn't mean the more reasonable implicit widening conversion; int i = c;:
If the implementation defines _Alignof(int) != 1, the cast invokes UB because x is potentially mis-aligned.
If the implementation defines sizeof(int) != 1, the dereferencing invokes UB, because we refer to memory which is not there.
Let's fix both possible issues by changing the lines defining x and assigning its address to c to this:
_Alignas(in) char x[sizeof(int)];
c = x;
Now, reading the dereferenced pointer causes UB, because we treat some memory as if it stored an object of type int, which is not true unless we copied one there from a valid int variable - treating both as buffers of characters - or we last stored an int there.
So, add a store before the read:
*(int*)c = 0;
Moving on...
printf("%d", i);
return 1;
}
To recap, the changed program:
#include <stdio.h>
int main(void) {
char *c;
_Alignas(in) char x[sizeof(int)];
c = x;
*c = 10;
*(int*)c = 0;
int i = *(int*)(c);
printf("%d", i);
return 1;
}
(Used the C11 standard for my fixes.)
Is it possible to dereference a void pointer without type-casting in the C programming language?
Also, is there any way of generalizing a function which can receive a pointer and store it in a void pointer and by using that void pointer, can we make a generalized function?
for e.g.:
void abc(void *a, int b)
{
if(b==1)
printf("%d",*(int*)a); // If integer pointer is received
else if(b==2)
printf("%c",*(char*)a); // If character pointer is received
else if(b==3)
printf("%f",*(float*)a); // If float pointer is received
}
I want to make this function generic without using if-else statements - is this possible?
Also if there are good internet articles which explain the concept of a void pointer, then it would be beneficial if you could provide the URLs.
Also, is pointer arithmetic with void pointers possible?
Is it possible to dereference the void pointer without type-casting in C programming language...
No, void indicates the absence of type, it is not something you can dereference or assign to.
is there is any way of generalizing a function which can receive pointer and store it in void pointer and by using that void pointer we can make a generalized function..
You cannot just dereference it in a portable way, as it may not be properly aligned. It may be an issue on some architectures like ARM, where pointer to a data type must be aligned at boundary of the size of data type (e.g. pointer to 32-bit integer must be aligned at 4-byte boundary to be dereferenced).
For example, reading uint16_t from void*:
/* may receive wrong value if ptr is not 2-byte aligned */
uint16_t value = *(uint16_t*)ptr;
/* portable way of reading a little-endian value */
uint16_t value = *(uint8_t*)ptr
| ((*((uint8_t*)ptr+1))<<8);
Also, is pointer arithmetic with void pointers possible...
Pointer arithmetic is not possible on pointers of void due to lack of concrete value underneath the pointer and hence the size.
void* p = ...
void *p2 = p + 1; /* what exactly is the size of void?? */
In C, a void * can be converted to a pointer to an object of a different type without an explicit cast:
void abc(void *a, int b)
{
int *test = a;
/* ... */
This doesn't help with writing your function in a more generic way, though.
You can't dereference a void * with converting it to a different pointer type as dereferencing a pointer is obtaining the value of the pointed-to object. A naked void is not a valid type so derefencing a void * is not possible.
Pointer arithmetic is about changing pointer values by multiples of the sizeof the pointed-to objects. Again, because void is not a true type, sizeof(void) has no meaning so pointer arithmetic is not valid on void *. (Some implementations allow it, using the equivalent pointer arithmetic for char *.)
You should be aware that in C, unlike Java or C#, there is absolutely no possibility to successfully "guess" the type of object a void* pointer points at. Something similar to getClass() simply doesn't exist, since this information is nowhere to be found. For that reason, the kind of "generic" you are looking for always comes with explicit metainformation, like the int b in your example or the format string in the printf family of functions.
A void pointer is known as generic pointer, which can refer to variables of any data type.
So far my understating on void pointer is as follows.
When a pointer variable is declared using keyword void – it becomes a general purpose pointer variable. Address of any variable of any data type (char, int, float etc.)can be assigned to a void pointer variable.
main()
{
int *p;
void *vp;
vp=p;
}
Since other data type pointer can be assigned to void pointer, so I used it in absolut_value(code shown below) function. To make a general function.
I tried to write a simple C code which takes integer or float as a an argument and tries to make it +ve, if negative. I wrote the following code,
#include<stdio.h>
void absolute_value ( void *j) // works if used float, obviously it must work but thats not my interest here.
{
if ( *j < 0 )
*j = *j * (-1);
}
int main()
{
int i = 40;
float f = -40;
printf("print intiger i = %d \n",i);
printf("print float f = %f \n",f);
absolute_value(&i);
absolute_value(&f);
printf("print intiger i = %d \n",i);
printf("print float f = %f \n",f);
return 0;
}
But I was getting error, so I came to know my understanding with void pointer is not correct :(. So now I will move towards to collect points why is that so.
The things that i need to understand more on void pointers is that.
We need to typecast the void pointer variable to dereference it. This is because a void pointer has no data type associated with it. There is no way the compiler can know (or guess?) what type of data is pointed to by the void pointer. So to take the data pointed to by a void pointer we typecast it with the correct type of the data holded inside the void pointers location.
void main()
{
int a=10;
float b=35.75;
void *ptr; // Declaring a void pointer
ptr=&a; // Assigning address of integer to void pointer.
printf("The value of integer variable is= %d",*( (int*) ptr) );// (int*)ptr - is used for type casting. Where as *((int*)ptr) dereferences the typecasted void pointer variable.
ptr=&b; // Assigning address of float to void pointer.
printf("The value of float variable is= %f",*( (float*) ptr) );
}
A void pointer can be really useful if the programmer is not sure about the data type of data inputted by the end user. In such a case the programmer can use a void pointer to point to the location of the unknown data type. The program can be set in such a way to ask the user to inform the type of data and type casting can be performed according to the information inputted by the user. A code snippet is given below.
void funct(void *a, int z)
{
if(z==1)
printf("%d",*(int*)a); // If user inputs 1, then he means the data is an integer and type casting is done accordingly.
else if(z==2)
printf("%c",*(char*)a); // Typecasting for character pointer.
else if(z==3)
printf("%f",*(float*)a); // Typecasting for float pointer
}
Another important point you should keep in mind about void pointers is that – pointer arithmetic can not be performed in a void pointer.
void *ptr;
int a;
ptr=&a;
ptr++; // This statement is invalid and will result in an error because 'ptr' is a void pointer variable.
So now I understood what was my mistake. I am correcting the same.
References :
http://www.antoarts.com/void-pointers-in-c/
http://www.circuitstoday.com/void-pointers-in-c.
The New code is as shown below.
#include<stdio.h>
#define INT 1
#define FLOAT 2
void absolute_value ( void *j, int *n)
{
if ( *n == INT) {
if ( *((int*)j) < 0 )
*((int*)j) = *((int*)j) * (-1);
}
if ( *n == FLOAT ) {
if ( *((float*)j) < 0 )
*((float*)j) = *((float*)j) * (-1);
}
}
int main()
{
int i = 0,n=0;
float f = 0;
printf("Press 1 to enter integer or 2 got float then enter the value to get absolute value\n");
scanf("%d",&n);
printf("\n");
if( n == 1) {
scanf("%d",&i);
printf("value entered before absolute function exec = %d \n",i);
absolute_value(&i,&n);
printf("value entered after absolute function exec = %d \n",i);
}
if( n == 2) {
scanf("%f",&f);
printf("value entered before absolute function exec = %f \n",f);
absolute_value(&f,&n);
printf("value entered after absolute function exec = %f \n",f);
}
else
printf("unknown entry try again\n");
return 0;
}
Thank you,
No, it is not possible. What type should the dereferenced value have?
void abc(void *a, int b) {
char *format[] = {"%d", "%c", "%f"};
printf(format[b-1], a);
}
Here is a brief pointer on void pointers: https://www.learncpp.com/cpp-tutorial/613-void-pointers/
6.13 — Void pointers
Because the void pointer does not know what type of object it is pointing to, it cannot be dereferenced directly! Rather, the void pointer must first be explicitly cast to another pointer type before it is dereferenced.
If a void pointer doesn't know what it's pointing to, how do we know what to cast it to? Ultimately, that is up to you to keep track of.
Void pointer miscellany
It is not possible to do pointer arithmetic on a void pointer. This is because pointer arithmetic requires the pointer to know what size object it is pointing to, so it can increment or decrement the pointer appropriately.
Assuming the machine's memory is byte-addressable and does not require aligned accesses, the most generic and atomic (closest to the machine level representation) way of interpreting a void* is as a pointer-to-a-byte, uint8_t*. Casting a void* to a uint8_t* would allow you to, for example, print out the first 1/2/4/8/however-many-you-desire bytes starting at that address, but you can't do much else.
uint8_t* byte_p = (uint8_t*)p;
for (uint8_t* i = byte_p; i < byte_p + 8; i++) {
printf("%x ",*i);
}
I want to make this function generic,
without using ifs; is it possible?
The only simple way I see is to use overloading .. which is not available in C programming langage AFAIK.
Did you consider the C++ programming langage for your programm ? Or is there any constraint that forbids its use?
Void pointers are pointers that has no data type associated with it.A void pointer can hold address of any type and can be typcasted to any type. But, void pointer cannot be directly be dereferenced.
int x = 1;
void *p1;
p1 = &x;
cout << *p1 << endl; // this will give error
cout << (int *)(*p) << endl; // this is valid
You can easily print a void printer
int p=15;
void *q;
q=&p;
printf("%d",*((int*)q));
Because C is statically-typed, strongly-typed language, you must decide type of variable before compile. When you try to emulate generics in C, you'll end up attempt to rewrite C++ again, so it would be better to use C++ instead.
void pointer is a generic pointer.. Address of any datatype of any variable can be assigned to a void pointer.
int a = 10;
float b = 3.14;
void *ptr;
ptr = &a;
printf( "data is %d " , *((int *)ptr));
//(int *)ptr used for typecasting dereferencing as int
ptr = &b;
printf( "data is %f " , *((float *)ptr));
//(float *)ptr used for typecasting dereferencing as float
You cannot dereference a pointer without specifying its type because different data types will have different sizes in memory i.e. an int being 4 bytes, a char being 1 byte.
Fundamentally, in C, "types" are a way to interpret bytes in memory. For example, what the following code
struct Point {
int x;
int y;
};
int main() {
struct Point p;
p.x = 0;
p.y = 0;
}
Says "When I run main, I want to allocate 4 (size of integer) + 4 (size of integer) = 8 (total bytes) of memory. When I write '.x' as a lvalue on a value with the type label Point at compile time, retrieve data from the pointer's memory location plus four bytes. Give the return value the compile-time label "int.""
Inside the computer at runtime, your "Point" structure looks like this:
00000000 00000000 00000000 00000000 00000000 00000000 00000000
And here's what your void* data type might look like: (assuming a 32-bit computer)
10001010 11111001 00010010 11000101
This won't work, yet void * can help a lot in defining generic pointer to functions and passing it as an argument to another function (similar to callback in Java) or define it a structure similar to oop.
Even after casting a void pointer, I am getting compilation error while dereferencing it.
Could anyone please let me know the reason of this.
int lVNum = 2;
void *lVptr;
lVptr = (int*)&lVNum;
printf("\nlVptr[60 ] is %d \n",lVptr[1]);
It doesn't make sense to dereference a void pointer. How will the compiler interpret the memory that the pointer is pointing to? You need to cast the pointer to a proper type first:
int x = *(int*)lVptr;
printf("\nlVptr[60 ] is %d \n", *(int*)lVptr);
This will cast the void pointer to a pointer to an int and then dereference it correctly.
If you want to treat it as an array (of one), you could do a slightly ugly ((int *)lVptr)[0]. Using [1] is out of bounds, and therefore not a good idea (as for lVptr[60]...)
It's still a void* because that's what you declared it as. Any pointer may be implicitly converted to a void*, so that cast does nothing and you are left with a pointer to void just as you began with.
You'll need to declare it as an int*.
void *some_ptr = /* whatever */;
int *p = (int*)some_ptr;
// now you have a pointer to int cast from a pointer to void
Note that the cast to an int* is also unnecessary, for the same reason you don't have to (and should not) cast the return value of malloc in C.
void*'s can be implicitly converted to and from any other pointer type. I added the cast here only for clarity, in your code you would simply write;
int *p = some_void_ptr;
Also, this:
lVptr[1]
Is wrong. You have a pointer to a single int, not two. That dereference causes undefined behavior.
You can not dereference a void pointer because it doesn't have a type,
first you need to cast it(int *)lVptr, then dereference it *(int *)lVptr.
int lVNum = 2;
void *lVptr;
lVptr = &lVNum;
printf("\nlVptr[60 ] is %d \n",*(int *)lVptr);
Example of what you might be trying to do:
#include <stdio.h>
int main () {
void *v;
unsigned long int *i = (unsigned long int *)v;
*i = 5933016743776703571;
size_t j = sizeof(i);
printf("There are %ld bytes in v\n", j);
size_t k;
for (k = 0; k < j; k++) {
printf("Byte %ld of v: %c\n", k, ((char *)v)[k]);
}
}
Output:
There are 8 bytes in v
Byte 0 of v: S
Byte 1 of v: T
Byte 2 of v: A
Byte 3 of v: C
Byte 4 of v: K
Byte 5 of v: O
Byte 6 of v: V
Byte 7 of v: R
A void pointer is just that, a pointer to a void (nothing definable).
Useful in some instances.
For example malloc() returns a void pointer precisely because it allocated memory for an UNDEFINED purpose.
Some functions may likewise take void pointers as arguments because they don't care about the actual content other than a location.
To be honest, the snippet you posted makes absolutely no sense, can't even guess what you were trying to do.
# Code-Guru
I tried to compile it in visual studio. It gives error - expression must be a pointer to complete object.
Thanks teppic,
As you suggested, the following compiles and yields right result.
#include<stdio.h>
void main(){
printf("study void pointers \n");
int lvnum = 2;
void *lvptr;
lvptr = &lvnum;
printf("\n lvptr is %d\n",((int *)lvptr)[0]);
}
However if I try printf("\n lvptr is %d\n",((int *)lVptr)[60]);
It compiles and runs but gives random number.
Thanks a lot, friends for all the suggestions. Apologies that I assigned a void pointer to unnecessarily casted int pointer and expected it to get dereferenced. However I should have casted it when I want to dereference it.
Purpose of the snippet:
In my sources I found klocwork error which was caused by similar situation. On the contrary the program not only compiled but also gave correct results. Reason- it is a low level code (no OS) where the memory assigned to the void pointer is already reserved till the count of like 60. But the klocwork tool was unable to parse the files having that limit resulting in error. I did a lot of brain storming and ended up in something silly.
Saurabh