Can I send char as array argument?

U

Uncle

I am an untrained hobbyist. Everything about programming I have learned
from the internet. Thank you all for your gracious support.

This is what I have:

#define CONST_CHAR 0
void some_func( char* arg, int len )
{
// stuff
}

Most times there is a character array sent as "arg", but sometimes I only
need to send a single character.

Don't laugh, I know this doesn't work:
void main( void )
{
some_func( (char*)CONST_CHAR, 1 );
}

This does, and it is what I'm doing now:
void main( void )
{
char array[1];
array[0] = CONST_CHAR;
some_func( array, 1 );
}

My questions are:
Is there a way to construct the arg that looks more like the first
non-working example? If there is, would it make any difference in not
having to allocate an array, ( albeit one byte, ) to send a single
character?
 
B

Ben Pfaff

[for passing a pointer to a single character]
Don't laugh, I know this doesn't work:
void main( void )
{
some_func( (char*)CONST_CHAR, 1 );
}

This does, and it is what I'm doing now:
void main( void )
{
char array[1];
array[0] = CONST_CHAR;
some_func( array, 1 );
}

Alternatively, you don't need the array syntax:

char c = CONST_CHAR;
some_func(&c, 1);
My questions are:
Is there a way to construct the arg that looks more like the first
non-working example?

In C99, you can write
some_func((char[]){CONST_CHAR});
or
some_func(&(char){CONST_CHAR});
But you probably don't have a C99 compiler.
 
B

Bruce Percy

I am an untrained hobbyist. Everything about programming I have learned
from the internet. Thank you all for your gracious support.

This is what I have:

#define CONST_CHAR 0
void some_func( char* arg, int len )
{
// stuff
}

Most times there is a character array sent as "arg", but sometimes I only
need to send a single character.

Don't laugh, I know this doesn't work:
void main( void )
{
some_func( (char*)CONST_CHAR, 1 );
}

This does, and it is what I'm doing now:
void main( void )
{
char array[1];
array[0] = CONST_CHAR;
some_func( array, 1 );
}

My questions are:
Is there a way to construct the arg that looks more like the first
non-working example? If there is, would it make any difference in not
having to allocate an array, ( albeit one byte, ) to send a single
character?

#include <stdio.h>

void some_func(const char* arg, int len )
{
int i;
for(i = 0; i < len; ++i)
printf("%c", arg);
}

int main(void)
{
const char CONST_CHAR = '0';
some_func(&CONST_CHAR, 1);
return 0;
}
 
U

Uncle

Ben Pfaff said:
[for passing a pointer to a single character]
Don't laugh, I know this doesn't work:
void main( void )
{
some_func( (char*)CONST_CHAR, 1 );
}

This does, and it is what I'm doing now:
void main( void )
{
char array[1];
array[0] = CONST_CHAR;
some_func( array, 1 );
}

Alternatively, you don't need the array syntax:

char c = CONST_CHAR;
some_func(&c, 1);
My questions are:
Is there a way to construct the arg that looks more like the first
non-working example?

In C99, you can write
some_func((char[]){CONST_CHAR});
or
some_func(&(char){CONST_CHAR});
But you probably don't have a C99 compiler.

Thanks.

I guess I don't have C99. I'm using freebies ( lcc and gcc. )
When I used some_func( &(char)CONST_CHAR ) the compiler complained:
"left hand side can't be assigned to."
I'm sure it wouldn't understand the braces at all.
 
B

Ben Pfaff

Uncle said:
Ben Pfaff said:
In C99, you can write
some_func((char[]){CONST_CHAR});
or
some_func(&(char){CONST_CHAR});
But you probably don't have a C99 compiler.

I guess I don't have C99. I'm using freebies ( lcc and gcc. )
When I used some_func( &(char)CONST_CHAR ) the compiler complained:
"left hand side can't be assigned to."
I'm sure it wouldn't understand the braces at all.

The braces are essential. Without the braces, it's a cast; with
the braces, it's a compound literal.
 
K

Kevin Goodsell

Uncle said:
I am an untrained hobbyist. Everything about programming I have learned
from the internet. Thank you all for your gracious support.

That's a very poor way to learn. Most of us work our asses off to learn
from real sources, and you are putting yourself way behind the game by
using the (mostly completely inadequate) sources available on the 'net.
This is what I have:

#define CONST_CHAR 0
void some_func( char* arg, int len )
{
// stuff
}

Most times there is a character array sent as "arg", but sometimes I only
need to send a single character.

char single_character = 's';
some_func(&single_character, 1);

Or create a separate function that takes a single char.
Don't laugh, I know this doesn't work:
void main( void )

main returns int. void is not and never has been an acceptable return
type for main.

int main(void)
{
some_func( (char*)CONST_CHAR, 1 );

This cast isn't even necessary, but the result (with or without the
cast) is to pass the function a null pointer.
}

This does, and it is what I'm doing now:
void main( void )

int main(void)
{
char array[1];
array[0] = CONST_CHAR;
some_func( array, 1 );
}

My questions are:
Is there a way to construct the arg that looks more like the first
non-working example? If there is, would it make any difference in not
having to allocate an array, ( albeit one byte, ) to send a single
character?

A single char (or rather, the address of a single char) is mostly
indistinguishable from a 1 element char array.

Beware, though. Many functions taking a char* actually expect a pointer
to a (properly terminated) string. In which case, the best you can do
with a single char is pass the empty string:

char c = '\0';
some_func(&c, 1);

(Usually a function taking a string wouldn't also take its length, of
course.)

-Kevin
 
A

August Derleth

Ben Pfaff said:
[for passing a pointer to a single character]
My questions are:
Is there a way to construct the arg that looks more like the first
non-working example?

In C99, you can write some_func((char[]){CONST_CHAR}); or
some_func(&(char){CONST_CHAR}); But you probably don't have a C99
compiler. --
"This is a wonderful answer.
It's off-topic, it's incorrect, and it doesn't answer the question."
--Richard Heathfield

Thanks.

I guess I don't have C99. I'm using freebies ( lcc and gcc. )

gcc implements a surprising amount of C99, but it isn't a conformant C99
compiler in any of its modes. C89 and C90 are more common these days, and
one could argue that they are the `true' standard in lieu of wide
acceptance of C99.

(gcc also implements some odd extensions to C, such as nested subroutines
(that is, subroutines declared inside subroutines, as per Pascal and Ada),
but such things are not on-topic here. I mention it simply because I
cannot understand why people writing a C compiler felt compelled to
implement nested subroutines.)

I don't know how conformant lcc is to anything, but I don't use it.
 
A

Anupam

Uncle said:
I am an untrained hobbyist. Everything about programming I have learned
from the internet. Thank you all for your gracious support.

This is what I have:

#define CONST_CHAR 0
void some_func( char* arg, int len )
{
// stuff
}

Most times there is a character array sent as "arg", but sometimes I only
need to send a single character.

Don't laugh, I know this doesn't work:
void main( void )
{
some_func( (char*)CONST_CHAR, 1 );
}
Presumably, you are passing the address of this character to modify
its contents. However if it is a constant ...is it? It sure seems so
(from CONST_CHAR) ... then you may not modify a constant. The results
of such
a thing is undefined.
For instance :
char *a="abc";
a[0]='k';
This is undefined behaviour.
This does, and it is what I'm doing now:
void main( void )
{
char array[1]; /* Or char ch; */
array[0] = CONST_CHAR; /* Or ch=CONST_CHAR; */
some_func( array, 1 ); /* Or some_func(&ch,1);
}
Here you are storing it in a variable and passing its address. Quite
different from casting a 0 to a char*, I would say.
My questions are:
Is there a way to construct the arg that looks more like the first
non-working example? If there is, would it make any difference in not
having to allocate an array, ( albeit one byte, ) to send a single
character?

You just have to store your literal someplace and pass the address
I'm
afraid.
Regards,
Anupam
 
U

Uncle

This is what I have:

#define CONST_CHAR 0
void some_func( char* arg, int len )
{
// stuff
}
Presumably, you are passing the address of this character to modify
its contents. However if it is a constant ...is it? It sure seems so
(from CONST_CHAR) ... then you may not modify a constant. The results
of such
a thing is undefined.

Actually some_func is basically just this:
void some_func( char* arg, int len )
{
mutex_release();
try_send( fd, arg, len, 0 );
mutex_aquire();
}
If the thread doesn't have the mutex it won't get here,
and try_send is just a socket send that closes fd and sets an error flag
on failure.
I put the mutex stuff in because I was afraid send might take a little time
to return.
"arg" is not modified.
For instance :
char *a="abc";
a[0]='k';
This is undefined behaviour.

I don't understand why this is undefined.
int main( void )
{
char *a="abc";
a[0]='k';
printf( a );
}
ouputs "kbc" on both of my systems. I would like to know where it might not
work, since I have quite a bit of this sort of thing in my code.

Just wondering, too; ( remember-- I'm untrained )
Is char*a above null terminated by the assignment? Is there a valid a[4] ==
'\0' ?
 
A

A. Sinan Unur

For instance :
char *a="abc";
a[0]='k';
This is undefined behaviour.

I don't understand why this is undefined.
http://www.eskimo.com/~scs/C-faq/q16.6.html

int main( void )
{
char *a="abc";
a[0]='k';
printf( a );
}
ouputs "kbc" on both of my systems. I would like to know where it
might not work, since I have quite a bit of this sort of thing in my
code.

also http://www.eskimo.com/~scs/C-faq/q1.32.html
Just wondering, too; ( remember-- I'm untrained )
Is char*a above null terminated by the assignment? Is there a valid
a[4] == '\0' ?

You are forgetting that C arrays are zero-based. Hence:

char *a = "abc";

means

a[0] == 'a' && a[1] == 'b' && a[2] == 'c'; && a[3] == '\0'

a[4] is out of bounds.

Also,

http://www.eskimo.com/~scs/C-faq/q4.10.html

seems relevant to your subject line.
 
A

Anupam

Uncle said:
Actually some_func is basically just this:
void some_func( char* arg, int len )

Try void some_func(const char* arg, int len)
since *arg presumably is not changed by the function.
{
mutex_release();
try_send( fd, arg, len, 0 );
mutex_aquire();
}
If the thread doesn't have the mutex it won't get here,
and try_send is just a socket send that closes fd and sets an error flag
on failure.
I put the mutex stuff in because I was afraid send might take a little time
to return.
"arg" is not modified.
For instance :
char *a="abc";
a[0]='k';
This is undefined behaviour.

I don't understand why this is undefined.
Because char *a="abc";
only reserves space on the function call data area for a... the pointer.
The space for the strinh literal "abc" may be reserved anywhere including
some sort of designated ROM.
int main( void )
{
char *a="abc";
a[0]='k';
printf( a );
}
ouputs "kbc" on both of my systems. I would like to know where it might not
work, since I have quite a bit of this sort of thing in my code.
Rather use char a[]="abc';
This reserves space for 4 characters and initialises them with 'a','b','c'and '\0'.
Just wondering, too; ( remember-- I'm untrained )
Is char*a above null terminated by the assignment? Is there a valid a[4] ==
'\0' ?
It is terminated by a '\0' .. ie a[3]='\0' since C arrays are 0 based.
 
J

John Bode

Uncle said:
I am an untrained hobbyist. Everything about programming I have learned
from the internet. Thank you all for your gracious support.

Just be aware, over 90% of Web-based C tutorials are crap. So are 90%
of the books on C programming. If you're serious about learning C,
you'll want to get at least one authoritative reference, such as
Kernighan & Ritchie's "The C Programming Language".
This is what I have:

#define CONST_CHAR 0
void some_func( char* arg, int len )
{
// stuff
}

Most times there is a character array sent as "arg", but sometimes I only
need to send a single character.

Don't laugh, I know this doesn't work:
void main( void )
{
some_func( (char*)CONST_CHAR, 1 );
}

This does, and it is what I'm doing now:
void main( void )
{
char array[1];
array[0] = CONST_CHAR;
some_func( array, 1 );
}

My questions are:
Is there a way to construct the arg that looks more like the first
non-working example? If there is, would it make any difference in not
having to allocate an array, ( albeit one byte, ) to send a single
character?

Okay, first, a little background. An object is a region of memory
that may be examined or written to. A pointer is an expression that
evaluates to the location of an object (i.e., an address). In your
code above, CONST_CHAR is a constant expression that evaluates to the
value 0, which is not an object in memory; therefore, you can't refer
to it with a pointer. You can't pass the address of CONST_CHAR to
some_func because CONST_CHAR has no address.

Somehow you have to assign the value represented by CONST_CHAR to
something that is an object, and then pass the address of that object
to some_func. Your solution was to declare a 1-element array of char
and assigned the value of CONST_CHAR to that single array element,
then pass the array as the argument. Another solution would be to
declare a single char variable, assign CONST_CHAR to it, and pass a
pointer to that variable:

char c = CONST_CHAR;
some_func (&c, 1);

The '&' operator yields the address of c, so the expression "&c" is a
pointer. You don't have to use the '&' operator when passing the
array as an argument, because under those circumstances the array
reference "decays" into a pointer to the first element of the array.
When we both have a couple of hours to kill we'll discuss how arrays
and pointers are hopelessly intertwined in C. Just remember when
anyone says that pointers and arrays are the same thing in C, laugh in
their face knowingly.

Oh, and change "void main (void)" to "int main (void)". main()
*always* returns int.

int main (void)
{
char c = CONST_CHAR;
some_func (&c, 1);

return EXIT_SUCCESS;
}

Just because it compiles and appears to run correctly doesn't mean
"void main(void)" is correct. There's no guarantee that it won't fail
under some circumstances.
 
P

Peter Shaggy Haywood

Groovy hepcat Uncle was jivin' on Fri, 5 Dec 2003 18:53:19 -0500 in
comp.lang.c.
Can I send char as array argument?'s a cool scene! Dig it!
I am an untrained hobbyist. Everything about programming I have learned
from the internet. Thank you all for your gracious support.

This is what I have:

#define CONST_CHAR 0

This macro is not only pointless but also misleading. The name of
this macro implies either a cast or a declaration of const char.
However, it expands to an integer constant expression having type int.
void some_func( char* arg, int len )
{
// stuff
}

Most times there is a character array sent as "arg", but sometimes I only
need to send a single character.

Don't laugh, I know this doesn't work:
void main( void )
{
some_func( (char*)CONST_CHAR, 1 );

This creates a null pointer. An integer constant expression with the
value 0 is a null pointer constant.
}

This does, and it is what I'm doing now:
void main( void )
{
char array[1];
array[0] = CONST_CHAR;
some_func( array, 1 );
}

No, this does not work (on any conforming implementation). main()
returns an int in all portable C programs, never void.

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
 

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

Forum statistics

Threads
473,744
Messages
2,569,481
Members
44,900
Latest member
Nell636132

Latest Threads

Top