Unable to pass array as parameter, using void pointer, s.t. the contents too are accessed in the called function.
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Unable to pass array as parameter, using void pointer, s.t. the contents too are accessed in the called function.
In the below program, there is one type of error, repeated twice, on execution in Cygwin.
Code:
#include <stdio.h>
void foo(void *p)
{
while(* (int *)p) //Doubt #1: first typecast to integer, then deference it. Else (i.e., without typecast and just stating : while( *p)) get one additional error, as shown below in 'Errors2'.
//Doubt #2: how to change the typecast to 'char' data-type, as have chosen fixed typecast to 'int'?
print("%p \n", *p);
//Doubt #3: How to access the contents of the array, and if use: **p, then do I need change from %p to %d, or %c; accordingly.
//Currently, due to unable to compile, not able to see the difference, in output, between **p, and *p. Though, seems that to access the contents, need **p instead.
}
int main()
{
int x[10] = {1,2,3,4,5,6,7,8,9,10};
char c[5] = "ABCDE";
void * p = x;
*p = c;
foo(&x);
foo(&c);
return (0);
}
Errors:
Code:
b.c: In function ‘foo’:
b.c:3:54: warning: dereferencing ‘void *’ pointer
3 | void foo(void *p) { while(*(int *)p) printf("%p \n", *p); }
| ^~
b.c:3:54: error: invalid use of void expression
b.c: In function ‘main’:
b.c:10:9: warning: dereferencing ‘void *’ pointer
10 | *p = c;
| ^~
b.c:10:12: error: invalid use of void expression
10 | *p = c;
| ^
Errors 2:
Code:
b.c:3:28: warning: dereferencing ‘void *’ pointer
3 | void foo(void *p) { while (*p) printf("%p \n", **p); }
| ^~
b.c:3:28: error: void value not ignored as it ought to be
3 | void foo(void *p) { while (*p) printf("%p \n", **p); }
| ^
b.c:3:49: warning: dereferencing ‘void *’ pointer
3 | void foo(void *p) { while (*p) printf("%p \n", **p); }
| ^~
b.c:3:49: error: void value not ignored as it ought to be
b.c: In function ‘main’:
b.c:10:9: warning: dereferencing ‘void *’ pointer
10 | * p = c;
| ^~~
b.c:10:13: error: invalid use of void expression
10 | * p = c;
| ^
What is the goal? What do you wish to accomplish with this code?
Want to not only pass two different arrays, using void pointer, but also want to access the contents of the two arrays, in the common function, to which these two arrays are
passed in successive invocations.
what do you want to print?
The pointer itself? printf("%p \n", p)
The integer? printf("%i \n", *(int *)p)
or ?
The contents of both the arrays, need be accessed, using a common function (here foo()), irrespective of the data type of the arrays passed; using just a void pointer.
If try to run with the simple modification, of having an integer specifier, for the output; still get the same error; apart from the usual issue of having another array (char), to be passed too, to the same function.
Please state how to directly access the contents of the array, using the void pointer.
Though have understood that cannot use one function, to access two different types of arrays, as the output specifier would differ then; and the contents' data type can not be stated beforehand.
But, to get this information, am not clear how you intend to use hexdump().
The output is unclear to me, as what is being printed, and also how it helps.
Also, am not clear as to why fputc() prints a single character of newline to the stdout (default file descriptor), even if multiple characters are used instead of just: '\n'?
Never mind, here is the fixed version of your original program:
Code:
#include <stdio.h>
void foo(int type, unsigned n, void *p)
{
if (type=='C') {
for (unsigned i=0; i<n; ++i) {
printf("%d: '%c'\n", i, ((char *)p)[i]);
}
} else if (type=='I') {
for (unsigned i=0; i<n; ++i) {
printf("%d: %d\n", i, ((int *)p)[i]);
}
}
}
int main()
{
int x[10] = {1,2,3,4,5,6,7,8,9,10};
char c[5] = "ABCDE";
foo('I', 10, &x);
foo('C', 5, &c);
return 0;
}
Thanks for introducing to many new rules, in C; say the type of character variables is denoted by 'C', and that of integer variable is denoted by 'I'.
Seems never read this aspect of the C language before.
There were some inadverent typos, after the removal of which, the code is:
Code:
#include <stdio.h>
void foo(int type, unsigned n, void *p)
{
if (type=='C'){
for (unsigned i=0; i<n; ++i){
printf("%d: '%c'\n", i, *(char *)(p+i));
}
} else if (type=='I'){
for (unsigned i=0; i<n; ++i){
printf("%d: %d\n", i, *(int *)(p+i));
}
}
}
int main()
{
int x[10] = {1,2,34,5,6,7,8,9,10};
char c[5]= "ABCDE";
foo('I', 10, &x);
foo('C', 5, &c);
return 0;
}
-----
Though still can't understand why the output is like that, as shown below:
The reason for choosing the expression of: *(char *)(p+i), or: *(int *)(p+i), was that the alternative forms of: *(char *)p[i], and *(int *)p[i], did not work; as gave error:
Code:
$ cc f1.c -o f1
f1.c: In function ‘foo’:
f1.c:7:59: warning: dereferencing ‘void *’ pointer
7 | printf("%d: '%c'\n", i, *(char *)p[i]);
| ^
f1.c:7:50: error: invalid use of void expression
7 | printf("%d: '%c'\n", i, *(char *)p[i]);
| ^
f1.c:11:56: warning: dereferencing ‘void *’ pointer
11 | printf("%d: %d\n", i, *(int *)p[i]);
| ^
f1.c:11:48: error: invalid use of void expression
11 | printf("%d: %d\n", i, *(int *)p[i]);
| ^
===============================
Error #2: By your original code, after removing just the typos:
Code:
#include <stdio.h>
void foo(int type, unsigned n, void *p)
{
if (type=='C') {
for (unsigned i=0; i<n; ++i) {
printf("%d: '%c'\n", i, ((char *)p)[i]);
}
} else if (type=='I') {
for (unsigned i=0; i<n; ++i) {
printf("%d: %d\n", i, ((int *)p)[i]);
}
}
}
int main()
{
int x[10] = {1,2,3,4,5,6,7,8,9,10};
char c[5] = "ABCDE";
foo('I', 10, &x);
foo('C', 5, &c);
return 0;
}
Output:
Code:
$ cc f2.c -o f2
f2.c: In function ‘foo’:
f2.c:7:58: warning: dereferencing ‘void *’ pointer
7 | printf("%d: '%c'\n", i, (char *)p[i]);
| ^
f2.c:7:49: error: invalid use of void expression
7 | printf("%d: '%c'\n", i, (char *)p[i]);
| ^
f2.c:11:55: warning: dereferencing ‘void *’ pointer
11 | printf("%d: %d\n", i, (int *)p[i]);
| ^
f2.c:11:47: error: invalid use of void expression
11 | printf("%d: %d\n", i, (int *)p[i]);
| ^
Thanks for introducing to many new rules, in C; say the type of character variables is denoted by 'C', and that of integer variable is denoted by 'I'.
Seems never read this aspect of the C language before.
That isn't an aspect of the language, it is simply passing additional arguments into the function to tell it the type and size of the array.
Quote:
Originally Posted by ajiten
There were some inadverent typos, after the removal of which, the code is:
Code:
#include <stdio.h>
void foo(int type, unsigned n, void *p)
{
if (type=='C'){
for (unsigned i=0; i<n; ++i){
printf("%d: '%c'\n", i, *(char *)(p+i));
}
} else if (type=='I'){
for (unsigned i=0; i<n; ++i){
printf("%d: %d\n", i, *(int *)(p+i));
}
}
}
int main()
{
int x[10] = {1,2,34,5,6,7,8,9,10};
char c[5]= "ABCDE";
foo('I', 10, &x);
foo('C', 5, &c);
return 0;
}
That does not produce the desired output because your pointer arithmetic is not correct.
Also, there is no need to pass the address of the array variables to make them a pointer as they are already simply pointers to the base of the arrays.
Try this:
Code:
#include <stdio.h>
void foo(int type, unsigned n, void *p)
{
if (type=='C') {
for (unsigned i=0; i<n; ++i) {
printf("%d: '%c'\n", i, *((char *)(p)+i));
}
} else if (type=='I') {
for (unsigned i=0; i<n; ++i) {
printf("%d: %d\n", i, *((int *)(p)+i));
}
}
}
int main()
{
int x[10] = {1,2,3,4,5,6,7,8,9,10};
char c[5] = "ABCDE";
foo('I', 10, x);
foo('C', 5, c);
return 0;
}
The difference in the pointer arithmetic is that your version:
Code:
printf("%d: %d\n", i, *(int *)(p+i));
...performs the addition before the pointer p has been cast to type, so the result is not an incremented pointer to type, but just a number.
This one:
Code:
printf("%d: %d\n", i, *((int *)(p)+i));
... first casts the pointer to its type, then performs the addition which produces a valid pointer to the type.
You could do it with less parenthesis, but I tend to use them when needed to make things clear to myself! This also works for the same reason given...
@OP Make sure to achieve warning-less compilation (use options -pedantic -W -Wall -Werror); you can access the array elements this way:
((int *)p)[i] or *((int *)p + i), ((char *)p)[i] or *((char *)p + i)
This mistake leapt out at me. "ABCDE" actually 6 characters long, because there's a terminating null character. Also, string constants are read-only, and you don't want to point a non-const char to it. There are other problems, and I assume that the compiler warnings would have flagged them.
The usual idiom for a string constant is this. It will work for what you're doing.
Code:
const char* c = "ABCDE";
If you need to modify the string, then you need to do this.
@OP Make sure to achieve warning-less compilation (use options -pedantic -W -Wall -Werror); you can access the array elements this way:
((int *)p)[i] or *((int *)p + i), ((char *)p)[i] or *((char *)p + i)
Kindly elaborate as giving on google: "-pedantic -W -Wall -Werror" fetched nothing at all. Also, not fetched anything relevant with the statement of: 'warning-less compilation C compiler -pedantic -W -Wall -Werror'. So, any literature search is not possible, not even with googlebooks.
Though compilation was done successfully, with the command:
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.