473,566 Members | 3,202 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Passing and returning arrays to and from functions

Can someone please help, I'm trying to pass an array to a function, do some
operation on that array, then return it for further use. The errors I am
getting for the following code are, differences in levels of indirection, so
I feel it must have something to do with the way I am representing the array
in the call and the return.

Below I have commented the problem parts.

Thanks in advance for any help offered.
Pete

#include <stdio.h>
#include <string.h>

char P10(char key[]); /* prototype */

void main()
{

char key[20];
int i;

printf("\nEnter a 10 bit Binary Sting: ");
gets(key); /* Copy representation of 10 bit binary string
entered from keyboard to key[]. "not to use for binary operations
just representation */

/* below I'm getting an error 'char[]' differs in levels of indirection to
'char'
and '=' left operand must be l-value */

key = P10(key); /* function call. copy returned array into key[] */
printf("Key is now : \n");
for(i=0; i<10; ++i) { /* loop to print returned array key[] */
printf("%c\n", key[i]);
}
}
char P10(char Ctext[]) { /* Trivial function to permute input string */

int Perm10[10]={3,5,2,7,4,10, 1,9,8,6};
int i;
int index;

/* Trace statement checking key[] has been passed */
for(i=0;i<10;++ i) {
printf("Ctext = %c\n", Ctext[i]);
}
/* Trivial Permutation function */
for(i=0; i<10; i++) {
index = Perm10[i];
printf("index = %d\n", index);
Ctext[i] = Perm10[index-1];
}
/* Below shows the error 'return' : 'char' differs in
levels of indirection from 'char *' */

return Ctext; /* return Ctext[]/key[] to calling function */
}

Nov 14 '05 #1
10 3133

"Pete" <No****@blank.c om> wrote
#include <stdio.h>
#include <string.h>

char P10(char key[]); /* prototype */
This is right but it suggests misunderstandin g.
void main()
This should be int main() to be ANSI-compliant.
{

char key[20];
int i;

printf("\nEnter a 10 bit Binary Sting: ");
gets(key); /* Copy representation of 10 bit binary string
entered from keyboard to key[]. "not to use for binary operations
just representation */
gets() is OK for a test program, but not for real code, because you will
corrupt memory if someone type in more than 19 characters (19 + NUL)
/* below I'm getting an error 'char[]' differs in levels of indirection to
'char'
and '=' left operand must be l-value */

key = P10(key); /* function call. copy returned array into key[] */
This is where the misunderstandin g creeps in.
printf("Key is now : \n");
for(i=0; i<10; ++i) { /* loop to print returned array key[] */
printf("%c\n", key[i]);
}
}
char P10(char Ctext[]) { /* Trivial function to permute input string */

int Perm10[10]={3,5,2,7,4,10, 1,9,8,6};
int i;
int index;

/* Trace statement checking key[] has been passed */
for(i=0;i<10;++ i) {
printf("Ctext = %c\n", Ctext[i]);
}
/* Trivial Permutation function */
for(i=0; i<10; i++) {
index = Perm10[i];
printf("index = %d\n", index);
Ctext[i] = Perm10[index-1];
}
/* Below shows the error 'return' : 'char' differs in
levels of indirection from 'char *' */

return Ctext; /* return Ctext[]/key[] to calling function */
}


The first point is that most C primers introduce multi-dimensional arrays at
about the same time as one-dimensional arrays. This is IMO a mistake. In C,
one-dimensional arrays are basic, but multi-dimensional arrays are advanced
features.

What does this have to do with you, since you only use a 1 dimensional
array?

The answer is that the primer obscures the truth that C does not pass or
return arrays to functions. It passes the address of the first element of
the array.

Your function should therefore be

char P10(char *Ctext)

However virtually any programmer would want some security about the length
of the array (and not just rely on the caller reading the comments and
guessing from the name that P10 takes 10 characters)

So the prototype becomes

/*
P2 - permute an array
Ctext - text to permute
N - length of text ( must be 10 in current version)
*/
char P10(char *Ctext, int N)

Now since we are passing a pointer to the array, the array will be permuted
in place. There is thus no need to return anything. So the function becomes

void P2(char *Ctext, int N)

However let's say you do not want to modify the array passed. What do we do
then? The answer is

void P2(const char *Ctext, int N, char *output)

If you are going to allow Ctext and output to be the same, you will have to
code carefully.
Nov 14 '05 #2
On Fri, 17 Sep 2004 12:08:12 +1000, "Pete" <No****@blank.c om> wrote in
comp.lang.c:
Can someone please help, I'm trying to pass an array to a function, do some
operation on that array, then return it for further use. The errors I am
getting for the following code are, differences in levels of indirection, so
I feel it must have something to do with the way I am representing the array
in the call and the return.
That's because you can't pass or return bare arrays to or from
functions.
Below I have commented the problem parts.

Thanks in advance for any help offered.
Pete

#include <stdio.h>
#include <string.h>

char P10(char key[]); /* prototype */
This prototype is exactly equivalent to:

char P10(char *key);

....because the name of an array is always converted to a pointer to
its first element when used as an argument to a function. C allows
the notation that you used as a synonym to the one that I used. I
really wished that had never been allowed, because it only adds to the
array/pointer confusion that many newbies have.

And even if you could return an array from a function, which you
can't, you have prototyped a function with a return type of a single
char only.

Actually, you want to change the return type of this function to void,
see my comments in the function itself.
void main()
This is a problem part that you neglected to comment. The only
standard, portable return type for main() in a hosted C environment is
'int'. No matter what the illiterate help files for some compilers
say.

int main()

....or even better:

int main(void)
{

char key[20];
int i;

printf("\nEnter a 10 bit Binary Sting: ");
gets(key); /* Copy representation of 10 bit binary string
Here's another problem that you didn't comment. Any, any, ANY use of
the function gets() is a defect. It is the only function in the
standard C library that can NEVER be used safely, and most especially
NOT TO BE used for interactive user input.

What do you think will happen is a user types 40 or 50 characters
before pressing enter, and gets() tries to put them all in your 20
character string? Bad things will happen.
entered from keyboard to key[]. "not to use for binary operations
just representation */

/* below I'm getting an error 'char[]' differs in levels of indirection to
'char'
and '=' left operand must be l-value */

key = P10(key); /* function call. copy returned array into key[] */
Right, you can't assign to an array like 'key', or any other array for
that matter.

Fortunately, you don't need to. When you pass 'key' to P10, that
function will actually receive a pointer to key[0]. Any change it
makes to key[0] and other characters via the pointer it receives
change the contents of the original array. So you don't need to
return it, it just changes as the function runs.

So make this:

P10(key);
printf("Key is now : \n");
for(i=0; i<10; ++i) { /* loop to print returned array key[] */
printf("%c\n", key[i]);
}
....and since you are going to fix your source to properly define
main() as returning an int, add this here:

return 0; }
char P10(char Ctext[]) { /* Trivial function to permute input string */
Change to:

void P10(char Ctext[])

....or even better to help avoid confusion in the future:

void P10(char *Ctext)
int Perm10[10]={3,5,2,7,4,10, 1,9,8,6};
int i;
int index;

/* Trace statement checking key[] has been passed */
for(i=0;i<10;++ i) {
printf("Ctext = %c\n", Ctext[i]);
}
/* Trivial Permutation function */
for(i=0; i<10; i++) {
index = Perm10[i];
printf("index = %d\n", index);
Ctext[i] = Perm10[index-1];
}
/* Below shows the error 'return' : 'char' differs in
levels of indirection from 'char *' */
The body of this function above here actually does what you want it to
do, because even though P10 receives Ctext as a pointer to char, you
can use subscripting on a pointer.
return Ctext; /* return Ctext[]/key[] to calling function */
Since this is now a function returning 'void', just omit this line.
}


Run, do not walk, to the FAQ for this group, link in my signature, and
read all of the entire section on pointers and arrays.

Then get a good C book, such as "The C Programming Language, Second
Edition" by Kernighan & Ritchie.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.l earn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 14 '05 #3
Hello,
However let's say you do not want to modify the array passed. What do we do
then? The answer is

void P2(const char *Ctext, int N, char *output)
size_t N is not only nicer but even makes most sense when using char
arrays... :-)
If you are going to allow Ctext and output to be the same, you will have to
code carefully.


Spell it out: The actual "permutatio n function" provided by the OP
is crap. I reordered the posting and comment on it now:

I enter with Ctext[]="1111110000 ";
char P10(char Ctext[]) { /* Trivial function to permute input string */

int Perm10[10]={3,5,2,7,4,10, 1,9,8,6};
int i;
int index;

/* Trace statement checking key[] has been passed */
for(i=0;i<10; ++i) {
printf("Cte xt = %c\n", Ctext[i]);
}
/* Trivial Permutation function */
for(i=0; i<10; i++) {
index = Perm10[i]; i=0: index=3; printf("index = %d\n", index);
Ctext[i] = Perm10[index-1]; Ctext[0]=Perm10[3-1]=2;
There was never a two in the original Ctext.

}
/* Below shows the error 'return' : 'char' differs in
levels of indirection from 'char *' */

return Ctext; /* return Ctext[]/key[] to calling function */
}


I am not sure what this is to mean. I think it should have been
something along the lines
Ctext[i]=Ctext[index-1];
However, this is crap, too: Imagine the very simple permutation
{3,1,2} working on {'0','0','1'}. This gives us the outcome:
Ctext[0]=Ctext[3-1]; /*='1';*/
Ctext[1]=Ctext[1-1]; /*='1';*/
Ctext[2]=Ctext[2-1]; /*='1';*/
Either you break up your permutation in a series of permutations
of two values and perform an exchange using an intermediate
variable:
/* Perm: {{3,2},{1,2}} */
temp=Ctext[3-1]; Ctext[3-1]=Ctext[2-1]; /*='0';*/
Ctext[2-1]=temp; /*='1';*/
temp=Ctext[1-1]; Ctext[1-1]=Ctext[2-1]; /*='1';*/
Ctext[2-1]=temp; /*='0';*/
or you use a temporary array to which you write the
outcome of your permutations. After that, you copy your
temporary values into the original array:
tempArr[i]=Ctext[index-1];
in your original loop effects tempArr holding the right permutation
of Ctext. Before returning, do
for (i=0; i<10; i++)
Ctext[i] = tempArr[i];

Try to wrap your mind arround the ideas of zero-based arrays and
zero-based permutations to get rid of the "-1".
Cheers
Michael

Nov 14 '05 #4
"Pete" <No****@blank.c om> wrote in message news:<41******* ***@news.iprimu s.com.au>...
Can someone please help, I'm trying to pass an array to a function, do some
operation on that array, then return it for further use. The errors I am
getting for the following code are, differences in levels of indirection, so
I feel it must have something to do with the way I am representing the array
in the call and the return.

Below I have commented the problem parts.

Thanks in advance for any help offered.
Pete

#include <stdio.h>
#include <string.h>

char P10(char key[]); /* prototype */

As Jack explained, "char key[]" in this context is synonymous with
"char *key"; in both cases, what you're actually passing to the
function is a pointer to the first element in the array, not a copy of
the array itself. Among other things, this means that you can't
automatically determine how many elements are in the array. When
passing an array argument, it's always good practice to pass the array
size (number of elements) as a separate argument, e.g.

char P10 (char *key, size_t keycount);
void main()
On a compliant, hosted implementation, this should be

int main (void)
{

char key[20];
int i;

printf("\nEnter a 10 bit Binary Sting: ");
gets(key); /* Copy representation of 10 bit binary string
entered from keyboard to key[]. "not to use for binary operations
just representation */

Never ever ever *EVER* use gets(). It *will* introduce a point of
failure in your program. Use fgets() instead:

fgets (key, sizeof key, stdin);

fgets() behaves slightly differently from gets() -- for example, if
you're entering data from the keyboard and hit Return, fgets() will
attempt to store that newline character to the target buffer if
there's room. The lines below will strip out the newline character if
it's present:

if (strchr (key, '\n'))
*(strchr (key, '\n')) = 0;

If the newline character isn't present, then you know that the user
typed a string longer than what you're sized to store.
/* below I'm getting an error 'char[]' differs in levels of indirection to
'char'
and '=' left operand must be l-value */

key = P10(key); /* function call. copy returned array into key[] */
First problem is that you have your function typed to return char
(single character) and you're attempting to assign that result to an
array of char (key). Second problem is that you cannot assign values
to an array identifier directly.

Since you are writing your results to the array parameter, there's no
reason to return the array value (functions cannot return array values
directly anyway).

Change the function so that it returns "void" (i.e., no value), and
pass the array size as a parameter, like so:

P10 (key, sizeof key);

Also remember to change the prototype above.
printf("Key is now : \n");
for(i=0; i<10; ++i) { /* loop to print returned array key[] */
printf("%c\n", key[i]);
}
}
char P10(char Ctext[]) { /* Trivial function to permute input string */

void P10 (char *Ctext, size_t CtextSize)
int Perm10[10]={3,5,2,7,4,10, 1,9,8,6};
int i;
int index;

/* Trace statement checking key[] has been passed */
for(i=0;i<10;++ i) {
for (i = 0; i < 10 && i < CtextSize; i++) {
printf("Ctext = %c\n", Ctext[i]);
}
/* Trivial Permutation function */
for(i=0; i<10; i++) {
index = Perm10[i];
printf("index = %d\n", index);
Ctext[i] = Perm10[index-1];
}
/* Below shows the error 'return' : 'char' differs in
levels of indirection from 'char *' */

return Ctext; /* return Ctext[]/key[] to calling function */
Again, this is because you typed the function to return char, but
you're attempting to return a value that's type char *. Type the
function to return void and remove the return statement completely.
}

Nov 14 '05 #5

"John Bode" <jo*******@my-deja.com> wrote offered.
printf("\nEnter a 10 bit Binary Sting: ");
gets(key); /* Copy representation of 10 bit binary string
entered from keyboard to key[]. "not to use for binary operations just representation */

Never ever ever *EVER* use gets(). It *will* introduce a point of
failure in your program. Use fgets() instead:

fgets (key, sizeof key, stdin);

fgets() behaves slightly differently from gets() -- for example, if
you're entering data from the keyboard and hit Return, fgets() will
attempt to store that newline character to the target buffer if
there's room. The lines below will strip out the newline character if
it's present:

if (strchr (key, '\n'))
*(strchr (key, '\n')) = 0;

No, no, no.
These lines are an error.
Think about it, what will happen on overflow?

Replacing undefined behaviour with wrong behaviour is not an improvement.
If the newline character isn't present, then you know that the user
typed a string longer than what you're sized to store.

So to use fgets() you need to check for the newline, and if it is not
present print out an error message such as "line too long", and then gobble
the rest of the input.
Nov 14 '05 #6
"Malcolm" <ma*****@55bank .freeserve.co.u k> wrote in message news:<ci******* ***@news6.svr.p ol.co.uk>...
"John Bode" <jo*******@my-deja.com> wrote offered.
printf("\nEnter a 10 bit Binary Sting: ");
gets(key); /* Copy representation of 10 bit binary string
entered from keyboard to key[]. "not to use for binary operations just representation */

Never ever ever *EVER* use gets(). It *will* introduce a point of
failure in your program. Use fgets() instead:

fgets (key, sizeof key, stdin);

fgets() behaves slightly differently from gets() -- for example, if
you're entering data from the keyboard and hit Return, fgets() will
attempt to store that newline character to the target buffer if
there's room. The lines below will strip out the newline character if
it's present:

if (strchr (key, '\n'))
*(strchr (key, '\n')) = 0;

No, no, no.
These lines are an error.
Think about it, what will happen on overflow?


What overflow?
Replacing undefined behaviour with wrong behaviour is not an improvement.

If the newline character isn't present, then you know that the user
typed a string longer than what you're sized to store.

So to use fgets() you need to check for the newline, and if it is not
present print out an error message such as "line too long", and then gobble
the rest of the input.


Or, alternately, store what's been read so far to a larger (preferably
extendable) buffer and repeat the operation until a newline (or EOF)
is seen, then work on the target buffer.
Nov 14 '05 #7

"John Bode" <jo*******@my-deja.com> wrote
fgets (key, sizeof key, stdin);

if (strchr (key, '\n'))
*(strchr (key, '\n')) = 0;

No, no, no.
These lines are an error.
Think about it, what will happen on overflow?


What overflow?

If the line the user enters is longer than sizeof key, what will happen?
What fatal mistake are you making in these three lines?

Nov 14 '05 #8
"Malcolm" <ma*****@55bank .freeserve.co.u k> wrote in message news:<ci******* ***@newsg1.svr. pol.co.uk>...
"John Bode" <jo*******@my-deja.com> wrote
> fgets (key, sizeof key, stdin);
>
> if (strchr (key, '\n'))
> *(strchr (key, '\n')) = 0;
>
>
No, no, no.
These lines are an error.
Think about it, what will happen on overflow?

What overflow?

If the line the user enters is longer than sizeof key, what will happen?


fgets() will read sizeof key-1 characters, write them to key along
with a terminating null character, and the remaining characters will
remain in standard input.

Remember, I'm using _f_gets() instead of gets().

If no newline character is found in key, strchr(key, '\n') returns
NULL, so the branch *(strchr (key, '\n')) = 0 isn't taken.
What fatal mistake are you making in these three lines?


Why don't you tell me?

I *have* tested this, you know. But, if you need convincing:

[root@rh170 other]# cat key.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main (void)
{
char key[10];

printf ("sockitome: ");
fflush (stdout);

fgets (key, sizeof key, stdin);
if (strchr(key, '\n'))
*(strchr(key, '\n')) = 0;

printf ("key = %s\n", key);

return 0;
}

[root@rh170 other]# gcc -o key -ansi -pedantic -Wall key.c
[root@rh170 other]# ./key
sockitome: blurga
key = blurga
[root@rh170 other]# ./key
sockitome: Supercalifragil isticexpealidoc ious
key = Supercali
[root@rh170 other]#

Did it yak when I typed in more characters than key was sized to hold?
No. The leftover characters in standard input need to be dealt with,
but that's a separate problem.

I freely admit that under most circumstances I *should* be checking
the result of fgets() for NULL, but for the purposes of this
demonstration I didn't think it necessary.
Nov 14 '05 #9

"John Bode" <jo*******@my-deja.com> wrote

I *have* tested this, you know. But, if you need convincing:

[root@rh170 other]# cat key.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main (void)
{
char key[10];

printf ("sockitome: ");
fflush (stdout);

fgets (key, sizeof key, stdin);
if (strchr(key, '\n'))
*(strchr(key, '\n')) = 0;

printf ("key = %s\n", key);

return 0;
}

Did it yak when I typed in more characters than key was sized to hold?
No. The leftover characters in standard input need to be dealt with,
but that's a separate problem.
The mistake is to think that getting rid of undefined behaviour solves all
your problems.
It gives the wrong result on overflow, and by throwing away the newline you
make it impossible to know if the user typed a whole line or not.

Now you can say, "in this case we always take the first nine characters, so
in fact throwing away the newline is OK". This is why no compiler can ever
catch wrong behaviour, as opposed to undefined behaviour. In fact for an
interactive program just truncating is very unlikely to be acceptable - the
user needs to know why a portion of his entry is missing - and even for an
automated system it is hardly conceivable that you wouldn't want to know if
fed an overlong key.
Nov 14 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

58
10077
by: jr | last post by:
Sorry for this very dumb question, but I've clearly got a long way to go! Can someone please help me pass an array into a function. Here's a starting point. void TheMainFunc() { // Body of code... TCHAR myArray; DoStuff(myArray);
5
3072
by: Gent | last post by:
I have two questions which are very similar: Is it possible to return an object in C++. Below is part of my code for reference however I am more concerned about the concept. It seems like the function below is returning a pointer to pointers who are GUID. I am trying to write a wrapper to use in my VB code and what I would prefer to do is be...
9
4771
by: justanotherguy63 | last post by:
Hi, I am designing an application where to preserve the hierachy and for code substitability, I need to pass an array of derived class object in place of an array of base class object. Since I am using vector class(STL), the compiler does not allow me to do this. I do realize there is a pitfall in this approach(size of arrays not...
25
2906
by: Victor Bazarov | last post by:
In the project I'm maintaining I've seen two distinct techniques used for returning an object from a function. One is AType function(AType const& arg) { AType retval(arg); // or default construction and then.. // some other processing and/or changing 'retval' return retval; }
2
1957
by: dave.harper | last post by:
I'm relatively new to C++, but have a question regarding functions and arrays. I'm passing a relatively large array to a function several thousand times during the course of a loop, and it seems to get bogged down. Do the arrays previously passed to the function stay memory resident? If not, what's causing it and what can I do to correct...
8
29024
by: Tweaxor | last post by:
Hey, I was trying to figure out was it possible in C to pass the values in an array from one function to another function. Is the possible in C? ex. y is the array that holds seven values If possible how could one pass these seven values in the array to a function that would check the values. I tried return y but it didn't work
11
8103
by: John Pass | last post by:
Hi, In the attached example, I do understand that the references are not changed if an array is passed by Val. What I do not understand is the result of line 99 (If one can find this by line number) which is the last line of the following sub routine: ' procedure modifies elements of array and assigns ' new reference (note ByVal) Sub...
5
5470
by: shyam | last post by:
Hi All I have to write a function which basically takes in a string and returns an unknown number( at compile time) of strings i hav the following syntax in mind char *tokenize(char *) is it ok?
17
3226
by: I.M. !Knuth | last post by:
Hi. I'm more-or-less a C newbie. I thought I had pointers under control until I started goofing around with this: ================================================================================ /* A function that returns a pointer-of-arrays to the calling function. */ #include <stdio.h> int *pfunc(void);
0
7903
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
8115
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
0
7959
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
6272
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
0
5216
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3648
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
0
3630
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
1205
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
930
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.