Trying to understand character arrays.

D

drM

Could anyone please offer some advice:
Trying to play with character arrays in C, the code below generates
this error.
Anyone see something wrong?
thank you in advance.

#include <stdio.h>

void test(char s[]);
char helloworld[11];

int main () {
printf("%s", test(helloworld)); // <----Invalid use of void
expression
return 0;
}


void test (char t[])
{

t[0]='H';
t[1]='e';
t[2]='l';
t[3]='l';
t[4]='o';
t[5]=' ';
t[6]='W';
t[7]='o';
t[8]='r';
t[9]='l';
t[10]='d';
t[11]='\0';

}
 
M

Michael Mair

drM said:
Could anyone please offer some advice:
Trying to play with character arrays in C, the code below generates
this error.
Anyone see something wrong?
thank you in advance.



#include <stdio.h>

void test(char s[]);
char helloworld[11];

int main () {
printf("%s", test(helloworld)); // <----Invalid use of void
expression

1) This nicely illustrates why you should not use // comments in
usenet messages
2) test()'s return type is void -- "nothing".
Nothing cannot be assigned to "anything" (anything non-void).
You can either change test() to
char *test (char *s);
or you have to do it in two steps:
test(helloworld);
printf("%s", helloworld);
3) Note that you should output '\n' as last character in order
to make sure that you see any output at all.
return 0;
}


void test (char t[])
{

t[0]='H';
t[1]='e';
t[2]='l';
t[3]='l';
t[4]='o';
t[5]=' ';
t[6]='W';
t[7]='o';
t[8]='r';
t[9]='l';
t[10]='d';
t[11]='\0';

1) If you want to change test() to char *test(char*), then
insert
return &t[0];
here
2) There are also strcpy() and strncpy()...

Cheers
Michael
 
K

Kenneth Brody

drM said:
Could anyone please offer some advice:
Trying to play with character arrays in C, the code below generates
this error.
Anyone see something wrong? [...]
void test(char s[]);
char helloworld[11]; [...]
printf("%s", test(helloworld)); // <----Invalid use of void expression
[...]

Hint 1: What does the error say?
Hint 2: What type does test() return, and how does that relate to (1)?
Hint 3: Can the type answered in (2) be passed to a function?
Hint 4: What does printf's "%s" expect?

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:[email protected]>
 
D

drM

Have just started in C, so your reply is most welcome.

"1) This nicely illustrates why you should not use // comments in
usenet messages "....Point taken.
 
V

Vladimir S. Oka

drM opined:
Have just started in C, so your reply is most welcome.

Whose reply? To what?
"1) This nicely illustrates why you should not use // comments in
usenet messages "....Point taken.

You should also make a point of quoting what and who you're replying
to. Read the link in my sig, and all the links in it...
 
D

drM

2) test()'s return type is void -- "nothing".
Nothing cannot be assigned to "anything" (anything non-void).
You can either change test() to
char *test (char *s);
or you have to do it in two steps:
test(helloworld);
printf("%s", helloworld);


Michael....If I understand you correctly, the type (void) is producing
an error, not because of the (void) test(helloworld) function, but
because of the printf function...or am I completely misunderstanding
you.
tks
 
D

drM

Michael said:
Nothing cannot be assigned to "anything" (anything non-void).
You can either change test() to
char *test (char *s);
or you have to do it in two steps:
test(helloworld);
printf("%s", helloworld);

Michael....If I understand you correctly, the type (void) is producing
an error, not because of the (void) test(helloworld) function, but
because of the printf function...or am I completely misunderstanding
you.
tks
 
K

Keith Thompson

drM said:
Michael....If I understand you correctly, the type (void) is producing
an error, not because of the (void) test(helloworld) function, but
because of the printf function...or am I completely misunderstanding
you.

It's not really one or the other, it's the combination. Your test
function was declared to return void; you tried to pass the
(nonexistent) result of that function to printf. You called printf
with a "%s" format, which means you need to pass it a char* as its
second argument.

If you had passed, say, an integer value:

printf("%s", 42);

then you would have been invoking undefined behavior. Since the types
for the arguments to printf are determined by the value of the format
string, they can't generally be checked by the compiler. But you
can't pass a nonexistent value (the result of a void function) as an
argument, so the compiler rejects the call.
 
D

drM

Keith said:
It's not really one or the other, it's the combination. Your test
function was declared to return void; ...... you
can't pass a nonexistent value (the result of a void function) as an
argument, (to printf) so the compiler rejects the call.


Thank you Keith, that clears it up for me and in fact helps me
understand the issue better.

Michael.
 
O

Old Wolf

drM said:
Could anyone please offer some advice:

There is another bug in this program:
char helloworld[11];

void test (char t[])
{
t[0]='H';
t[1]='e';
t[2]='l';
t[3]='l';
t[4]='o';
t[5]=' ';
t[6]='W';
t[7]='o';
t[8]='r';
t[9]='l';
t[10]='d';
t[11]='\0';
}

helloworld[] only has space for 11 characters, but you have
written 12 characters to it. This is a buffer overflow.
 
J

jaysome

Michael said:
drM said:
Could anyone please offer some advice:
Trying to play with character arrays in C, the code below generates
this error.
Anyone see something wrong?
thank you in advance.



#include <stdio.h>

void test(char s[]);
char helloworld[11];

int main () {
printf("%s", test(helloworld)); // <----Invalid use of void
expression


1) This nicely illustrates why you should not use // comments in
usenet messages

No. It illustrates why the de facto Usenet standards are broken in this
day and age. After all:

1. ISO/IEC 9899:1999(E) is dated 1999-12-01, which was over six years
ago. That C standard--the current one--allows // comments. I recall that
some regulars in here were overflowing with enthusiasm for some time
before and after the ratification of that standard. If their enthusiasm
is alive now as it was then, they should weigh in on this issue.

2. C++ is a *BIG* part of Usenet and has always allowed // comments (as
well as /* */ comments). Arguably, C++ programmers prefer to use //
comments at least sometimes, if not most or all of the time. By your
standards, should those C++ programmers revert to /* */ comments when
posting to Usenet?

I submit that other things related to Usenet are broken, not the current
C and C++ standards. The days of 72 characters per line should be
considered folklore--these days there is no reason whatsoever why line
lengths cannot be significantly a lot more than that. I propose 132.
YMMV, especially if you're using *NIX.
 
K

Keith Thompson

jaysome said:
Michael said:
drM schrieb: [...]
int main () {
printf("%s", test(helloworld)); // <----Invalid use of void
expression
1) This nicely illustrates why you should not use // comments in
usenet messages

No. It illustrates why the de facto Usenet standards are broken in
this day and age. After all:

1. ISO/IEC 9899:1999(E) is dated 1999-12-01, which was over six years
ago. That C standard--the current one--allows // comments. I recall
that some regulars in here were overflowing with enthusiasm for some
time before and after the ratification of that standard. If their
enthusiasm is alive now as it was then, they should weigh in on this
issue.

As you know, the C99 standard allows both // and /*...*/ comments.
And, as you probably also know, there aren't as many C99 conforming
compilers as we might like.
2. C++ is a *BIG* part of Usenet and has always allowed // comments
(as well as /* */ comments). Arguably, C++ programmers prefer to use
// comments at least sometimes, if not most or all of the time. By
your standards, should those C++ programmers revert to /* */ comments
when posting to Usenet?

I don't know. Perhaps you should ask in comp.lang.c++.
I submit that other things related to Usenet are broken, not the
current C and C++ standards. The days of 72 characters per line should
be considered folklore--these days there is no reason whatsoever why
line lengths cannot be significantly a lot more than that. I propose
132. YMMV, especially if you're using *NIX.

I read Usenet in an 80-column window. I could make it 132 columns if
I wanted to, but I find text composed of lines limited to 80 columns
or so easier to read. I note that you used no more than 70 columns
per line yourself.

Do you expect to get a change like this to be adopted by each of the
thousands of existing newsgroups?

But the point you're ignoring is that, since a long line was wrapped
some time after it was posted, the comment was split and a syntax
error was introduced. If a /*...*/ comment had been used instead,
this would have been less of a problem.

Personally, I like end-of-line comments better than classic C-style
comments, but there are valid reasons for using avoiding them on
Usenet.
 
C

CBFalconer

jaysome said:
Michael Mair wrote:
.... snip ...

No. It illustrates why the de facto Usenet standards are broken in
this day and age. After all:
.... snip ...

I submit that other things related to Usenet are broken, not the
current C and C++ standards. The days of 72 characters per line
should be considered folklore--these days there is no reason
whatsoever why line lengths cannot be significantly a lot more
than that. I propose 132. YMMV, especially if you're using *NIX.

And you would be dead wrong, for multiple reasons. First, long
lines are hard to read. 80 characters is already taxing. That is
why sane documents limit lines to 65 or so characters, and
newspapers split their text into columns.

Much software has grown up around the 72 and 80 char limits. It
works. There is no need to discard this.

This software includes the usenet system, and the majority of text
windows on almost any system today. Funnily wrapped lines, and
lines that are offscreen, are especially hard to read.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 
M

Michael Mair

jaysome said:
Michael said:
drM said:
Could anyone please offer some advice:
Trying to play with character arrays in C, the code below generates
this error.
Anyone see something wrong?
thank you in advance.

#include <stdio.h>

void test(char s[]);
char helloworld[11];

int main () {
printf("%s", test(helloworld)); // <----Invalid use of void
expression

1) This nicely illustrates why you should not use // comments in
usenet messages

No. It illustrates why the de facto Usenet standards are broken in this
day and age. After all:

1. ISO/IEC 9899:1999(E) is dated 1999-12-01, which was over six years
ago. That C standard--the current one--allows // comments. I recall that
some regulars in here were overflowing with enthusiasm for some time
before and after the ratification of that standard. If their enthusiasm
is alive now as it was then, they should weigh in on this issue.

2. C++ is a *BIG* part of Usenet and has always allowed // comments (as
well as /* */ comments). Arguably, C++ programmers prefer to use //
comments at least sometimes, if not most or all of the time. By your
standards, should those C++ programmers revert to /* */ comments when
posting to Usenet?

I submit that other things related to Usenet are broken, not the current
C and C++ standards. The days of 72 characters per line should be
considered folklore--these days there is no reason whatsoever why line
lengths cannot be significantly a lot more than that. I propose 132.
YMMV, especially if you're using *NIX.

This may or may not be true -- however, the line did not break at
quoting but was broken in the OP. I have seen people shooting
themselves in the foot with the difference between "//.... \"
and "//.... \ ".
BTW: Even in C++, I use BCPL line comments only at the beginning
of a line and not preceded by code.

Cheers
Michael
 
A

Anders Arnholm

jaysome said:
C and C++ standards. The days of 72 characters per line should be
considered folklore--these days there is no reason whatsoever why line
lengths cannot be significantly a lot more than that. I propose 132.
YMMV, especially if you're using *NIX.

At 132 charaters a side by side diff is 265 charaters wide at least.
There are few screens that can display that is a resonabe font. Also
that long lines are hard to compare and see what charater differs. 80
and 160 wide screens works, but already three it stats to get harder
to read and work efficently.

If the magicasl number is 72, 65, 80 or 95 i can't say. 132 is to
much, i think 60 is to little. Sometimes i run uptowards 130 but those
lines always comes back hunting me later when that don't work.

/ Anders
 
J

John Bode

drM said:
Could anyone please offer some advice:
Trying to play with character arrays in C, the code below generates
this error.
Anyone see something wrong?
thank you in advance.

#include <stdio.h>

void test(char s[]);

When you pass an array as an argument to a function, what actually gets
passed is a pointer to the first element of the array; the above
prototype is a synonym for

void test(char *s);

Because of how array subscripting is defined, you can still access
individual elements of s as s[0], s[1], etc., but the *type* of s is
"pointer to char", not "array of char". This has nothing to do with
your specific error, but it's something that I guarantee is going to
trip you up soon.
char helloworld[11];

Remember that when you declare an N-element array, the array subscripts
run from 0 to N-1; in this case, you've declared helloworld to hold 11
characters, which means the you can access elements from 0 to 10.
However, in your test function below, you try to write to elements 0 to
11. Writing to that last element writes beyond the end of the array,
which leads to undefined behavior. Change this declaration so that
helloworld contains 12 elements.

There's no good reason to declare helloworld at file scope (i.e., as a
global variable). As a general rule, you want to limit the scope of
variables as much as possible to avoid maintenance headaches. Since
you're passing it as an argument to test, there's no reason to have it
globally visible to both main() and test(). Move the declaration so
that it's within main.
int main () {
printf("%s", test(helloworld)); // <----Invalid use of void

Okay, here's the actual problem. The "%s" conversion specifier expects
an argument of type "char *"; however, you've defined test() to return
void (I'm pretty sure that printf() doesn't like *any* of its arguments
to be void, which is why you get a compile-time diagnostic; how do you
format an expression that has no value?). There are two ways around
this:

1. Change the return type of test to char *, and return the value of
the input parameter (it's a good idea for the parameter names in the
function declaration match those in the function definition, btw; makes
life easier for other people reading the code):

char *test(char *t)
{
/* copy "Hello World" to t */
return t;
}

2. Leave the return type as it is, call test() before calling
printf(), and pass the modified helloworld as the argument to printf(),
like so:

test(helloworld);
printf("%s\n", helloworld);

Note: because of how C I/O works, if you don't have printf() emit a
newline, the text may not be flushed to output immediately, and it will
look like your program isn't doing anything. So you either need a
newline in the control string, as I've done above, or if you don't want
a newline at that point, you should add the line

fflush(stdout);

after the printf() statement.
expression
return 0;
}


void test (char t[])
{

t[0]='H';
t[1]='e';
t[2]='l';
t[3]='l';
t[4]='o';
t[5]=' ';
t[6]='W';
t[7]='o';
t[8]='r';
t[9]='l';
t[10]='d';
t[11]='\0';

There's a library function that allows you to do this with much less
pain:

strcpy(t, "Hello, World");

(be sure to #include <string.h>).
 
D

drM

John said:
When you pass an array as an argument to a function, what actually gets
passed is a pointer to the first element of the array; the above
prototype is a synonym for......................

John,
thank you for that explanation. I am slowly working my way through K&R,
and with some help, it is actually turning out to be a lot of fun.
 
D

Default User

CBFalconer said:
And you would be dead wrong, for multiple reasons. First, long
lines are hard to read. 80 characters is already taxing. That is
why sane documents limit lines to 65 or so characters, and
newspapers split their text into columns.

I definitely agree. While XanaNews in the size window I use can display
lines much longer than that without wrapping, it causes a lot more eye
movement and therefore strain. Narrower == gooder. Or sumpin.



Brian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top