L in return

F

frank

What's the L doing in here:

#include <stdio.h>
#include <wchar.h>

int my_function(wchar_t *a){
return wprintf(a);
}
int main(){
return my_function(L"hi there\n");
}

// gcc -Wall -Wextra hi1.c -o out

I think I want to rewrite this slightly to address the compiler's
criticism:

dan@dan-desktop:~/source$ gcc -Wall -Wextra hi1.c -o out
hi1.c: In function ‘my_function’:
hi1.c:5: warning: implicit declaration of function ‘wprintf’
dan@dan-desktop:~/source$ ./out
hi there

Am I correct to think that wprintf expects at least 2 args?
 
S

Seebs

What's the L doing in here:

It's not in a return, it's in a string literal.
int my_function(wchar_t *a){

wchar_t * usually means a wide string
return my_function(L"hi there\n");

And whaddya know, you've used a wide string.
dan@dan-desktop:~/source$ gcc -Wall -Wextra hi1.c -o out
hi1.c: In function ?my_function?:
hi1.c:5: warning: implicit declaration of function ?wprintf?
dan@dan-desktop:~/source$ ./out
hi there

Am I correct to think that wprintf expects at least 2 args?

No, you are not.

Is it REALLY that hard to read the messages? It did not say "warning: wprintf
needs at least 2 args". It said "warning: implicit declaration of
function wprintf." Why do you think it said that? Could it be because
you did not provide a declaration of wprintf? Maybe you should include
the header which is needed to use wprintf.

-s
 
F

frank

It's not in a return, it's in a string literal.


wchar_t * usually means a wide string


And whaddya know, you've used a wide string.


No, you are not.

Is it REALLY that hard to read the messages? It did not say "warning:
wprintf needs at least 2 args". It said "warning: implicit declaration
of function wprintf." Why do you think it said that? Could it be
because you did not provide a declaration of wprintf? Maybe you should
include the header which is needed to use wprintf.

-s

According to p. 387, H&S V, these are the two #includes you snipped.
 
A

Alan Curry

#include <stdio.h>
#include <wchar.h>

int my_function(wchar_t *a){
return wprintf(a);
}
int main(){
return my_function(L"hi there\n");
}

// gcc -Wall -Wextra hi1.c -o out

I think I want to rewrite this slightly to address the compiler's
criticism:

dan@dan-desktop:~/source$ gcc -Wall -Wextra hi1.c -o out
hi1.c: In function ‘my_function’:
hi1.c:5: warning: implicit declaration of function ‘wprintf’

The program is fine, but gcc's default mode is too old-fashioned. wprintf was
added in the 199409 ("C95") revision of the language, so you need at least
gcc -std=iso9899:199409 to use it.
 
K

Keith Thompson

frank said:
What's the L doing in here:

#include <stdio.h>
#include <wchar.h>

int my_function(wchar_t *a){
return wprintf(a);
}
int main(){
return my_function(L"hi there\n");
}

// gcc -Wall -Wextra hi1.c -o out

I think I want to rewrite this slightly to address the compiler's
criticism:

dan@dan-desktop:~/source$ gcc -Wall -Wextra hi1.c -o out
hi1.c: In function ‘my_function’:
hi1.c:5: warning: implicit declaration of function ‘wprintf’
dan@dan-desktop:~/source$ ./out
hi there

Apparently gcc combined with glibc hides the declaration of wprintf
by default. You can make it visible with "-std=iso9899:199409" or
"-std=c99".
Am I correct to think that wprintf expects at least 2 args?

No.
 
K

Keith Thompson

Seebs said:
It's not in a return, it's in a string literal.

Which is in a return statement.
wchar_t * usually means a wide string


And whaddya know, you've used a wide string.

It's understandable that someone who hadn't encountered the L"..."
syntax before wouldn't realize that the L is part of the string
literal.
No, you are not.

Is it REALLY that hard to read the messages? It did not say "warning: wprintf
needs at least 2 args". It said "warning: implicit declaration of
function wprintf." Why do you think it said that? Could it be because
you did not provide a declaration of wprintf? Maybe you should include
the header which is needed to use wprintf.

He did. It's declared in <wchar.h>. The problem is that he needs to
invoke gcc with the right -std=... option to make it visible.
 
F

frank

The program is fine, but gcc's default mode is too old-fashioned.
wprintf was added in the 199409 ("C95") revision of the language, so you
need at least gcc -std=iso9899:199409 to use it.

Alright, thx alan. There are some strange things happening with gcc that
I'm gonna have to work around. This switch fixes the problem with
widechar, but it now sees my c99 comments as errors!

-std=c99 works. It's time for me to go face my public as a karaoke
star. Cheers,
 
F

frank


int wprintf(const wchar_t * restrict format, ...);

Isn't the first argument supposed to look like " %s \n" and then the
second to be pointer to the text literal?
 
S

Seebs

He did. It's declared in <wchar.h>. The problem is that he needs to
invoke gcc with the right -std=... option to make it visible.

Oh!

Whoops, sorry frank. I missed the header when looking at the code
originally, I guess. Sorry about that!

-s
 
S

Seebs

int wprintf(const wchar_t * restrict format, ...);
Isn't the first argument supposed to look like " %s \n" and then the
second to be pointer to the text literal?

No.

"..." means "and possibly more arguments". Whether or not there are ANY
arguments corresponding to "..." depends.

wprintf(L"hello\n");

is fine because the string doesn't contain any format characters. But
if you did
wprintf(L"hello, %s\n");
that would be an error because you used a %s but didn't provide a
corresponding argument.

-s
 
K

Keith Thompson

frank said:
int wprintf(const wchar_t * restrict format, ...);

Isn't the first argument supposed to look like " %s \n" and then the
second to be pointer to the text literal?

Just as with printf, the first argument is the format string, which
specifies the number and type(s) of any following arguments. If the
format string contains no '%' characters (or if any '%' characters are
doubled), then the format string is (or should be) the only argument.

wprintf(L"One argument\n");
wprintf(L"Two arguments: %s\n", s1);
wprintf(L"Three arguments: %s %s\n", s1, s2);
wprintf(L"Four arguments: %s%s %s %s\n", s1, s2, s3);
 
K

Keith Thompson

Seebs said:
I have never seen that error occur if <wchar.h> was included.

I have. Try it with "gcc -Wall -Wextra".

In the glibc version of <wchar.h>, the declaration of wprintf is
#ifdef'ed out unless the C version is specified to be at least C95,
which it isn't by default.

(Without the warning options, the declaration is missing but there's
no warning on the call.)
 
S

Seebs

In the glibc version of <wchar.h>, the declaration of wprintf is
#ifdef'ed out unless the C version is specified to be at least C95,
which it isn't by default.
Ohhhhh.

(Without the warning options, the declaration is missing but there's
no warning on the call.)

Wacky.

-s
 
F

frank

Just as with printf, the first argument is the format string, which
specifies the number and type(s) of any following arguments. If the
format string contains no '%' characters (or if any '%' characters are
doubled), then the format string is (or should be) the only argument.

wprintf(L"One argument\n");
wprintf(L"Two arguments: %s\n", s1);
wprintf(L"Three arguments: %s %s\n", s1, s2); wprintf(L"Four
arguments: %s%s %s %s\n", s1, s2, s3);

I thought this would compile without objection, but not so:

dan@dan-desktop:~/source$ cat hi2.c
#include <stdio.h>
#include <wchar.h>

int my_function(wchar_t *a){
return wprintf("%ls\n", a);
}
int main(){
return my_function(L"hi there");
}

// gcc -std=c99 -Wall -Wextra hi2.c -o out
dan@dan-desktop:~/source$ gcc -std=c99 -Wall -Wextra hi2.c -o out
hi2.c: In function ‘my_function’:
hi2.c:5: warning: passing argument 1 of ‘wprintf’ from incompatible
pointer type
dan@dan-desktop:~/source$

I guess my point is that a is not const wchar_t * restrict format. So
when it's just wprintf(a), then it's different than the specification.
 
B

Ben Bacarisse

frank said:
I thought this would compile without objection, but not so:

dan@dan-desktop:~/source$ cat hi2.c
#include <stdio.h>
#include <wchar.h>

int my_function(wchar_t *a){
return wprintf("%ls\n", a);
}
int main(){
return my_function(L"hi there");
}

// gcc -std=c99 -Wall -Wextra hi2.c -o out
dan@dan-desktop:~/source$ gcc -std=c99 -Wall -Wextra hi2.c -o out
hi2.c: In function ‘my_function’:
hi2.c:5: warning: passing argument 1 of ‘wprintf’ from incompatible
pointer type
dan@dan-desktop:~/source$

I guess my point is that a is not const wchar_t * restrict format. So
when it's just wprintf(a), then it's different than the
specification.

The complaint is about argument 1 -- the "%ls\n". You need a wide
string: L"%ls\n".
 
S

Seebs

I thought this would compile without objection, but not so:

dan@dan-desktop:~/source$ cat hi2.c
#include <stdio.h>
#include <wchar.h>

int my_function(wchar_t *a){
return wprintf("%ls\n", a);
}
int main(){
return my_function(L"hi there");
}

// gcc -std=c99 -Wall -Wextra hi2.c -o out
dan@dan-desktop:~/source$ gcc -std=c99 -Wall -Wextra hi2.c -o out
hi2.c: In function ?my_function?:
hi2.c:5: warning: passing argument 1 of ?wprintf? from incompatible
pointer type
dan@dan-desktop:~/source$

I guess my point is that a is not const wchar_t * restrict format. So
when it's just wprintf(a), then it's different than the specification.

No, it's not.

The problem is that the FORMAT STRING ("%ls\n") you used is not a wchar_t *.

Notice: Argument *1*.

-s
 
F

frank

I wanted to say a few more words about this. I've been trying to wrap my
head around what "const wchar_t * restrict format" is. I encountered it
first in a serious way when I started to work my way through H&S V, where
this is similar to one of the arguments for the functions in the fprintf
family. For fwprintf, for example, it's the second argument.

int my_function(wchar_t *a){
return wprintf(a);
}

Isn't the a here not const and thus not something that could be "const
wchar_t * restrict format"?
The complaint is about argument 1 -- the "%ls\n". You need a wide
string: L"%ls\n".

Thx, ben. Apparently I need both cap L's:

dan@dan-desktop:~/source$ gcc -std=c99 -Wall -Wextra hi2.c -o out
dan@dan-desktop:~/source$ ./out
hi there
dan@dan-desktop:~/source$ cat hi2.c
#include <stdio.h>
#include <wchar.h>

int my_function(wchar_t *a){
return wprintf( L"%ls\n", a);
}
int main(){
return my_function(L"hi there");
}

// gcc -std=c99 -Wall -Wextra hi2.c -o out
dan@dan-desktop:~/source$ gcc -std=c99 -Wall -Wextra hi2.c -o out
hi2.c: In function ‘main’:
hi2.c:8: warning: passing argument 1 of ‘my_function’ from incompatible
pointer type
dan@dan-desktop:~/source$ cat hi2.c
#include <stdio.h>
#include <wchar.h>

int my_function(wchar_t *a){
return wprintf( L"%ls\n", a);
}
int main(){
return my_function("hi there");
}

// gcc -std=c99 -Wall -Wextra hi2.c -o out
dan@dan-desktop:~/source$
 
K

Keith Thompson

frank said:
I wanted to say a few more words about this. I've been trying to wrap my
head around what "const wchar_t * restrict format" is. I encountered it
first in a serious way when I started to work my way through H&S V, where
this is similar to one of the arguments for the functions in the fprintf
family. For fwprintf, for example, it's the second argument.

int my_function(wchar_t *a){
return wprintf(a);
}

Isn't the a here not const and thus not something that could be "const
wchar_t * restrict format"?
[...]

Let's look at a (perhaps) simpler example.

#include <stdio.h>

void func(char *param)
{
*param = 'H';
puts(param);
}

void const_func(const char *param)
{
#if 0
*param = 'H'; /* illegal, violates "const" promise */
#endif
puts(param);
}

int main(void)
{
char s[] = "hello, world";
char *arg = s;
const char *const_arg = s;

func(arg); /* ok */
#if 0
func(const_arg); /* illegal, violates promise made by */
/* declaration of const_arg */
#endif
const_func(arg); /* ok, doesn't violate any "const" promise */
const_func(const_arg); /* ok */
return 0;
}

Passing a pointer-to-(non-const)-char to a function that takes a
pointer-to-const-char, as in "const_func(arg);" above, is perfectly
valid. The "const" on the parameter declaration is a promise
not to use the parameter to modify what the parameter points to.
The code doesn't try to violate that promise, so there's no problem.

Passing a pointer-to-const to a function that takes a
pointer-to-non-const, on the other hand, is a constraint violation.
The declaration "const char *const_arg;" promises not to use
const_arg to modify the data it points to. You can't pass that
pointer to a function that doesn't make a similar promise. But as
we can see, you can modify the same data through another path.

The above program should compile and run without error. If you change
"#if 0" to "#if 1", the compiler will complain.
 
F

frank

On Thu, 19 Nov 2009 13:08:33 -0800, Keith Thompson wrote:

[snipped and re-ordered for thematic reasons]
Passing a pointer-to-(non-const)-char to a function that takes a
pointer-to-const-char, as in "const_func(arg);" above, is perfectly
valid. The "const" on the parameter declaration is a promise not to use
the parameter to modify what the parameter points to. The code doesn't
try to violate that promise, so there's no problem.

Passing a pointer-to-const to a function that takes a
pointer-to-non-const, on the other hand, is a constraint violation. The
declaration "const char *const_arg;" promises not to use const_arg to
modify the data it points to. You can't pass that pointer to a function
that doesn't make a similar promise. But as we can see, you can modify
the same data through another path.

The above program should compile and run without error. If you change
"#if 0" to "#if 1", the compiler will complain.

I'm just about there with this material and this is certainly good source
to get right at the meat of it. This shows when the #ifs are changed:

dan@dan-desktop:~/source$ gcc -std=c99 -Wall -Wextra hi3.c -o out
hi3.c: In function ‘const_func’:
hi3.c:13: error: assignment of read-only location ‘*param’
dan@dan-desktop:~/source$ cat hi3.c

#include <stdio.h>

void func(char *param)
{
*param = 'H';
puts(param);
}

void const_func(const char *param)
{
#if 1
*param = 'H'; /* illegal, violates "const" promise */
#endif
puts(param);
}

int main(void)
{
char s[] = "hello, world";
char *arg = s;
const char *const_arg = s;

func(arg); /* ok */
#if 0
func(const_arg); /* illegal, violates promise made by */
/* declaration of const_arg */
#endif
const_func(arg); /* ok, doesn't violate any "const" promise */
const_func(const_arg); /* ok */
return 0;
}

// gcc -std=c99 -Wall -Wextra hi3.c -o out
dan@dan-desktop:~/source$ gcc -std=c99 -Wall -Wextra hi3.c -o out
hi3.c: In function ‘main’:
hi3.c:26: warning: passing argument 1 of ‘func’ discards qualifiers from
pointer target type
dan@dan-desktop:~/source$ cat hi3.c

#include <stdio.h>

void func(char *param)
{
*param = 'H';
puts(param);
}

void const_func(const char *param)
{
#if 0
*param = 'H'; /* illegal, violates "const" promise */
#endif
puts(param);
}

int main(void)
{
char s[] = "hello, world";
char *arg = s;
const char *const_arg = s;

func(arg); /* ok */
#if 1
func(const_arg); /* illegal, violates promise made by */
/* declaration of const_arg */
#endif
const_func(arg); /* ok, doesn't violate any "const" promise */
const_func(const_arg); /* ok */
return 0;
}

// gcc -std=c99 -Wall -Wextra hi3.c -o out
Let's look at a (perhaps) simpler example.

#include <stdio.h>

void func(char *param)
{
*param = 'H';
puts(param);
}

Why don't we see an H in stdout here?

dan@dan-desktop:~/source$ gcc -std=c99 -Wall -Wextra hi4.c -o out
dan@dan-desktop:~/source$ ./out
here in func

Hello, world
Hello, world
Hello, world
dan@dan-desktop:~/source$ cat hi4.c

#include <stdio.h>

void func(char *param)
{
puts("here in func\n");
*param = 'H';
puts(param);
}

void const_func(const char *param)
{
#if 0
*param = 'H'; /* illegal, violates "const" promise */
#endif
puts(param);
}

int main(void)
{
char s[] = "hello, world";
char *arg = s;
const char *const_arg = s;

func(arg); /* ok */
#if 0
func(const_arg); /* illegal, violates promise made by */
/* declaration of const_arg */
#endif
const_func(arg); /* ok, doesn't violate any "const" promise */
const_func(const_arg); /* ok */
return 0;
}

// gcc -std=c99 -Wall -Wextra hi4.c -o out
dan@dan-desktop:~/source$
 

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

Similar Threads

constructing robust constructors 15
L-value problem 5
wcslen function 2
calling a singly-linked list 16
when to ignore warnings 1
prototypes 4
herding the bits of a float into an integer array 35
faq 19.1 57

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,076
Latest member
OrderKetoBeez

Latest Threads

Top