LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 06-16-2023, 01:21 AM   #1
ajiten
Member
 
Registered: Jun 2023
Posts: 375

Rep: Reputation: 4
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;
      |             ^

Last edited by ajiten; 06-16-2023 at 01:46 AM.
 
Old 06-16-2023, 03:11 AM   #2
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,866
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
What is the goal? What do you wish to accomplish with this code?
 
Old 06-16-2023, 03:13 AM   #3
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,863

Rep: Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311Reputation: 7311
what do you want to print?
The pointer itself? printf("%p \n", p)
The integer? printf("%i \n", *(int *)p)
or ?
 
Old 06-16-2023, 04:28 AM   #4
ajiten
Member
 
Registered: Jun 2023
Posts: 375

Original Poster
Rep: Reputation: 4
As stated in my post's title ...

Quote:
Originally Posted by NevemTeve View Post
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.
 
Old 06-16-2023, 04:31 AM   #5
ajiten
Member
 
Registered: Jun 2023
Posts: 375

Original Poster
Rep: Reputation: 4
Quote:
Originally Posted by pan64 View Post
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.

Last edited by ajiten; 06-16-2023 at 06:37 AM.
 
Old 06-16-2023, 04:48 AM   #6
ajiten
Member
 
Registered: Jun 2023
Posts: 375

Original Poster
Rep: Reputation: 4
Hope would get some help soon.

Last edited by ajiten; 06-16-2023 at 06:39 AM.
 
Old 06-16-2023, 06:37 AM   #7
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,866
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
There are not much of things you can do with a piece of data without knowing its type. Printing hexdump might be an option.
Code:
#include <stdio.h>

void hexdump(unsigned len, const void *p)
{
    const unsigned char *q= p;
    const unsigned char *qlim= q + len;

    for (q= p; q < qlim; ++q) {
        printf ("%02x", *q);
    }
    fputc('\n', stdout);
}

int main()
{
    int x[10] = {1,2,3,4,5,6,7,8,9,10};
    char c[5] = "ABCDE";

    hexdump(sizeof x, x);
    hexdump(sizeof c, c);

    return 0;
}
 
Old 06-16-2023, 06:55 AM   #8
ajiten
Member
 
Registered: Jun 2023
Posts: 375

Original Poster
Rep: Reputation: 4
Quote:
Originally Posted by NevemTeve View Post
There are not much of things you can do with a piece of data without knowing its type. Printing hexdump might be an option.
Code:
#include <stdio.h>

void hexdump(unsigned len, const void *p)
{
    const unsigned char *q= p;
    const unsigned char *qlim= q + len;

    for (q= p; q < qlim; ++q) {
        printf ("%02x", *q);
    }
    fputc('\n', stdout);
}

int main()
{
    int x[10] = {1,2,3,4,5,6,7,8,9,10};
    char c[5] = "ABCDE";

    hexdump(sizeof x, x);
    hexdump(sizeof c, c);

    return 0;
}
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().

On Cygwin, it prints:
Code:
0100000002000000030000000400000005000000060000000700000008000000090000000a000000
4142434445
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'?

Last edited by ajiten; 06-16-2023 at 07:04 AM.
 
Old 06-16-2023, 07:32 AM   #9
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,866
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
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;
}
 
1 members found this post helpful.
Old 06-16-2023, 08:53 AM   #10
ajiten
Member
 
Registered: Jun 2023
Posts: 375

Original Poster
Rep: Reputation: 4
Quote:
Originally Posted by NevemTeve View Post
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:
Code:
 
User@DESKTOP-OKV7A0Q ~
$ ./f1
0: 1
1: 33554432
2: 131072
3: 512
4: 2
5: 570425344
6: 2228224
7: 8704
8: 34
9: 83886080
0: 'A'
1: 'B'
2: 'C'
3: 'D'
4: 'E'
=============

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]);
      |                                               ^

Last edited by ajiten; 06-16-2023 at 09:18 AM.
 
Old 06-16-2023, 11:17 AM   #11
astrogeek
Moderator
 
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=15, FreeBSD_12{.0|.1}
Posts: 6,267
Blog Entries: 24

Rep: Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195
Quote:
Originally Posted by ajiten View Post
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 View Post
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...

Code:
printf("%d: %d\n", i, *(int *)p+i);

Last edited by astrogeek; 06-16-2023 at 05:15 PM.
 
1 members found this post helpful.
Old 06-16-2023, 11:19 AM   #12
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,866
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
@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)

Last edited by NevemTeve; 06-16-2023 at 11:20 AM.
 
1 members found this post helpful.
Old 06-16-2023, 06:57 PM   #13
dugan
LQ Guru
 
Registered: Nov 2003
Location: Canada
Distribution: distro hopper
Posts: 11,226

Rep: Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320Reputation: 5320
Quote:
Originally Posted by ajiten View Post
Code:
char c[5] = "ABCDE";
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.

Code:
char c[6];
strcpy(c, "ABCDE");

Last edited by dugan; 06-16-2023 at 07:05 PM.
 
2 members found this post helpful.
Old 06-16-2023, 07:28 PM   #14
astrogeek
Moderator
 
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=15, FreeBSD_12{.0|.1}
Posts: 6,267
Blog Entries: 24

Rep: Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195Reputation: 4195
Quote:
Originally Posted by dugan View Post
This mistake leapt out at me. "ABCDE" actually 6 characters long, because there's a terminating null character.
Indeed! I saw that then forgot about it before I posted. Short term memory is not what it used to be!
 
1 members found this post helpful.
Old 06-16-2023, 11:56 PM   #15
ajiten
Member
 
Registered: Jun 2023
Posts: 375

Original Poster
Rep: Reputation: 4
Quote:
Originally Posted by NevemTeve View Post
@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:
Code:
$ cc -pedantic -W -Wall -Werror f2.c -o f2

Last edited by ajiten; 06-17-2023 at 12:45 PM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
pthread giving error: invalid conversion from ‘void* (*)(int*)’ to ‘void* (*)(void*)’ knobby67 Programming 4 05-05-2017 10:54 AM
[SOLVED] Scheme -> Lisp. How can I pass a function as parameter to another function ? muggabug Programming 2 12-26-2012 10:23 AM
[SOLVED] How can i pass an entire Array into a function parameter by value? (no pointer pass) esgol Programming 26 07-31-2012 11:34 AM
( C ) How do you declare a function pointer where a parameter is a function pointer? spursrule Programming 5 11-27-2007 07:56 PM
void foo(void) and void foo() lackluster Programming 9 02-15-2003 10:57 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 09:15 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration