473,406 Members | 2,816 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,406 software developers and data experts.

Confusion with stdarg

Hello,

I'm encountering a problem with using stdarg that I cannot
figure out. I'm trying to develop a function for a linux
driver module that takes a variable-length sequence of
u8-type values. Below is the function:

#include <stdarg.h>
..
..
..
63 int sn9c102_write_va_regs(struct sn9c102_device* cam,
u16 index, int len, ...)
64 {
65 int res, i;
66 u8 data[32];
67 va_list args;
68
69 va_start(args, len);
70 for (i = 0; i < len; i++) {
71 data[i] = va_arg (args, u8);
72 }
73 va_end(args);
74 res = sn9c102_write_regs(cam, index, data, len);
75 if (res < 0) {
76 DEBUG(3, "Failed to write registers starting at index "
77 "0x%02X, error %d)", index, res)
78 return -1;
79 }
80 return 0;
81 }

When I compile the code, I get the following message:

sonix_pas202b.c: In function `sn9c102_write_va_regs':
sonix_pas202b.c:74: warning: implicit declaration of function
`sn9c102_write_regs'
sonix_pas202b.c:71: warning: `u8' is promoted to `int' when passed
through `...'sonix_pas202b.c:71: warning: (so you should pass `int' not
`u8' to `va_arg')

Why does the warning on line 71 occur? I believe that 'u8'
is typedef'ed somewhere in the linux kernel headers as an
'unsigned char', though I have not verified that yet. Is
there a way of telling 'va_arg' the actual type of 'u8'?

I'm compiling with GCC version 3.2.3 on Slackware Linux 9.1
(kernel 2.4.22).

Thanks,

Mac Cody

Nov 14 '05 #1
9 1811
Mac A. Cody wrote:
Hello,

I'm encountering a problem with using stdarg that I cannot
figure out. I'm trying to develop a function for a linux
driver module that takes a variable-length sequence of
u8-type values. Below is the function:

#include <stdarg.h>
.
.
.
63 int sn9c102_write_va_regs(struct sn9c102_device* cam,
u16 index, int len, ...)
64 {
65 int res, i;
66 u8 data[32];
67 va_list args;
68
69 va_start(args, len);
70 for (i = 0; i < len; i++) {
71 data[i] = va_arg (args, u8);
72 }
73 va_end(args);
74 res = sn9c102_write_regs(cam, index, data, len);
75 if (res < 0) {
76 DEBUG(3, "Failed to write registers starting at index "
77 "0x%02X, error %d)", index, res)
78 return -1;
79 }
80 return 0;
81 }

When I compile the code, I get the following message:

sonix_pas202b.c: In function `sn9c102_write_va_regs':
sonix_pas202b.c:74: warning: implicit declaration of function
`sn9c102_write_regs'
sonix_pas202b.c:71: warning: `u8' is promoted to `int' when passed
through `...'sonix_pas202b.c:71: warning: (so you should pass `int' not
`u8' to `va_arg')

Why does the warning on line 71 occur? I believe that 'u8'
is typedef'ed somewhere in the linux kernel headers as an
'unsigned char', though I have not verified that yet. Is
there a way of telling 'va_arg' the actual type of 'u8'?

I'm compiling with GCC version 3.2.3 on Slackware Linux 9.1
(kernel 2.4.22).

Thanks,

Mac Cody

Since the compiler didn't see the prototype of the function
it will promote u8 to int, and warns you about it.

Always prototype the functions before calling them, specially
when writing an OS!

Nov 14 '05 #2
jacob navia wrote:
Mac A. Cody wrote:
Hello,

I'm encountering a problem with using stdarg that I cannot
figure out. I'm trying to develop a function for a linux
driver module that takes a variable-length sequence of
u8-type values. Below is the function:

#include <stdarg.h>
.
.
.
63 int sn9c102_write_va_regs(struct sn9c102_device* cam,
u16 index, int len, ...)
64 {
65 int res, i;
66 u8 data[32];
67 va_list args;
68
69 va_start(args, len);
70 for (i = 0; i < len; i++) {
71 data[i] = va_arg (args, u8);
72 }
73 va_end(args);
74 res = sn9c102_write_regs(cam, index, data, len);
75 if (res < 0) {
76 DEBUG(3, "Failed to write registers starting at index "
77 "0x%02X, error %d)", index, res)
78 return -1;
79 }
80 return 0;
81 }

When I compile the code, I get the following message:

sonix_pas202b.c: In function `sn9c102_write_va_regs':
sonix_pas202b.c:74: warning: implicit declaration of function
`sn9c102_write_regs'
sonix_pas202b.c:71: warning: `u8' is promoted to `int' when passed
through `...'sonix_pas202b.c:71: warning: (so you should pass `int'
not `u8' to `va_arg')

Why does the warning on line 71 occur? I believe that 'u8'
is typedef'ed somewhere in the linux kernel headers as an
'unsigned char', though I have not verified that yet. Is
there a way of telling 'va_arg' the actual type of 'u8'?

I'm compiling with GCC version 3.2.3 on Slackware Linux 9.1
(kernel 2.4.22).

Thanks,

Mac Cody

Since the compiler didn't see the prototype of the function
it will promote u8 to int, and warns you about it.

Always prototype the functions before calling them, specially
when writing an OS!


Jacob,

Thanks for the quick response! Since the linux kernel headers
are included (I just didn't show them.) and the compiler does
not otherwise balk at the 'u8' typing (as on line 64 in the
code above), the compiler must be seeing a prototype somewhere
along the way (doesn't it?). Maybe I'm missing something here.

Thanks again,

Mac

Nov 14 '05 #3


Mac A. Cody wrote:
jacob navia wrote:
Mac A. Cody wrote:
Hello,

I'm encountering a problem with using stdarg that I cannot
figure out. I'm trying to develop a function for a linux
driver module that takes a variable-length sequence of
u8-type values. Below is the function:

#include <stdarg.h>
.
.
.
63 int sn9c102_write_va_regs(struct sn9c102_device* cam,
u16 index, int len, ...)
64 {
65 int res, i;
66 u8 data[32];
67 va_list args;
68
69 va_start(args, len);
70 for (i = 0; i < len; i++) {
71 data[i] = va_arg (args, u8);
72 }
73 va_end(args);
74 res = sn9c102_write_regs(cam, index, data, len);
75 if (res < 0) {
76 DEBUG(3, "Failed to write registers starting at index "
77 "0x%02X, error %d)", index, res)
78 return -1;
79 }
80 return 0;
81 }

When I compile the code, I get the following message:

sonix_pas202b.c: In function `sn9c102_write_va_regs':
sonix_pas202b.c:74: warning: implicit declaration of function
`sn9c102_write_regs'
sonix_pas202b.c:71: warning: `u8' is promoted to `int' when passed
through `...'sonix_pas202b.c:71: warning: (so you should pass `int'
not `u8' to `va_arg')

Why does the warning on line 71 occur? I believe that 'u8'
is typedef'ed somewhere in the linux kernel headers as an
'unsigned char', though I have not verified that yet. Is
there a way of telling 'va_arg' the actual type of 'u8'?

I'm compiling with GCC version 3.2.3 on Slackware Linux 9.1
(kernel 2.4.22).

Thanks,

Mac Cody

Since the compiler didn't see the prototype of the function
it will promote u8 to int, and warns you about it.

Always prototype the functions before calling them, specially
when writing an OS!


Jacob,

Thanks for the quick response! Since the linux kernel headers
are included (I just didn't show them.) and the compiler does
not otherwise balk at the 'u8' typing (as on line 64 in the
code above), the compiler must be seeing a prototype somewhere
along the way (doesn't it?). Maybe I'm missing something here.


Yes. Variable arguments of vararg functions get promoted, i.e. you
cannot pass just a char but will always get an int. That is, you
(necessarily) pass the u8 values as int values -- and have to retrieve
them as such. The same happens to functions without prototypes.
Something else: You should check against a buffer overrun of data
in the loop l70 -- l72.
Cheers
Michael
--
E-Mail: Mine is a gmx dot de address.

Nov 14 '05 #4
On Mon, 03 Jan 2005 00:58:05 -0600, "Mac A. Cody"
<ma*****@castcom.net> wrote in comp.lang.c:
Hello,

I'm encountering a problem with using stdarg that I cannot
figure out. I'm trying to develop a function for a linux
driver module that takes a variable-length sequence of
u8-type values. Below is the function:

#include <stdarg.h>
.
.
.
63 int sn9c102_write_va_regs(struct sn9c102_device* cam,
u16 index, int len, ...)
You can't pass unsigned characters as part of the "..." arguments to
variadic functions. You can't pass any of the character types, or
signed or unsigned short, or floats. The arguments to such functions,
after the fixed ones, undergo the default promotions.

See section 15 on functions with variable argument lists in the FAQ
for this group, link in my signature. Specifically see:

15.10 Why isn't "va_arg(argp, float)" working?

....at: http://www.eskimo.com/~scs/C-faq/q15.10.html
64 {
65 int res, i;
66 u8 data[32];
67 va_list args;
68
69 va_start(args, len);
70 for (i = 0; i < len; i++) {
71 data[i] = va_arg (args, u8);
72 }
73 va_end(args);
74 res = sn9c102_write_regs(cam, index, data, len);
75 if (res < 0) {
76 DEBUG(3, "Failed to write registers starting at index "
77 "0x%02X, error %d)", index, res)
78 return -1;
79 }
80 return 0;
81 }

When I compile the code, I get the following message:

sonix_pas202b.c: In function `sn9c102_write_va_regs':
sonix_pas202b.c:74: warning: implicit declaration of function
`sn9c102_write_regs'
Well, obviously you don't have a prototype for this function in scope.
Find the proper header and include it.
sonix_pas202b.c:71: warning: `u8' is promoted to `int' when passed
through `...'sonix_pas202b.c:71: warning: (so you should pass `int' not
`u8' to `va_arg')

Why does the warning on line 71 occur? I believe that 'u8'
is typedef'ed somewhere in the linux kernel headers as an
'unsigned char', though I have not verified that yet. Is
there a way of telling 'va_arg' the actual type of 'u8'?
No, there is no way at all to pass variable arguments to a variadic
function with a type less than int. They will be promoted to int by
the caller, assuming that it has a prototype for the variadic function
in scope. So you have to retrieve them as type int, then you can
assign them to your unsigned char array. There will be no change in
value.
I'm compiling with GCC version 3.2.3 on Slackware Linux 9.1
(kernel 2.4.22).

Thanks,

Mac Cody


--
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.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 14 '05 #5
jacob navia <ja***@jacob.remcomp.fr> wrote:
Mac A. Cody wrote:
#include <stdarg.h> 63 int sn9c102_write_va_regs(struct sn9c102_device* cam,
u16 index, int len, ...)
64 { 66 u8 data[32];
67 va_list args; 71 data[i] = va_arg (args, u8); 74 res = sn9c102_write_regs(cam, index, data, len); When I compile the code, I get the following message:

sonix_pas202b.c: In function `sn9c102_write_va_regs':
sonix_pas202b.c:74: warning: implicit declaration of function
`sn9c102_write_regs'
sonix_pas202b.c:71: warning: `u8' is promoted to `int' when passed
through `...'sonix_pas202b.c:71: warning: (so you should pass `int' not
`u8' to `va_arg')

Since the compiler didn't see the prototype of the function
it will promote u8 to int, and warns you about it.
Bullshit. There _is_ a prototype. The lack of declaration of
sn9c102_write_regs (what a monster of a name, btw!) is completely beside
the point, for line 71. The problem is with the application of va_arg
and sn9c102_write_va_regs, for both of which a good declaration is in
scope.
The real problem is not a _lack_ of prototype, but the fact that the
prototype in question is a variadic one. This means that the arguments
in the variadic part are subject to the Usual Arithmetic Conversions as
much as when there had not been a prototype at all. There's nothing you
can do about that, either. There simply is no typing information in
"...", therefore the UACs kick in, and therefore there is no way a
variadic function can receive anything smaller than an int as one of its
variable arguments.
Always prototype the functions before calling them, specially
when writing an OS!


Always remember that prototyping doesn't protect you from the UACs if
you're using variadic functions.

Richard
Nov 14 '05 #6
Michael Mair wrote:
Yes. Variable arguments of vararg functions get promoted, i.e. you
cannot pass just a char but will always get an int. That is, you
(necessarily) pass the u8 values as int values -- and have to retrieve
them as such. The same happens to functions without prototypes.
Okay, I understand now. The webpage I found didn't mention the point
about the promtion of chars to ints.
Something else: You should check against a buffer overrun of data
in the loop l70 -- l72.
Good point. An overrun at that point would not be a nice thing.
Cheers
Michael


Thanks for responding!

Regards,

Mac

Nov 14 '05 #7
Richard Bos wrote:
jacob navia <ja***@jacob.remcomp.fr> wrote:
Since the compiler didn't see the prototype of the function
it will promote u8 to int, and warns you about it.

Bullshit. There _is_ a prototype. The lack of declaration of
sn9c102_write_regs (what a monster of a name, btw!) is completely beside


That name wasn't my idea, though sn9c102_write_va_regs isn't much
better! :^/
the point, for line 71. The problem is with the application of va_arg
and sn9c102_write_va_regs, for both of which a good declaration is in
scope.
The real problem is not a _lack_ of prototype, but the fact that the
prototype in question is a variadic one. This means that the arguments
in the variadic part are subject to the Usual Arithmetic Conversions as
much as when there had not been a prototype at all. There's nothing you
can do about that, either. There simply is no typing information in
"...", therefore the UACs kick in, and therefore there is no way a
variadic function can receive anything smaller than an int as one of its
variable arguments.

Thanks for the clarification!
Always prototype the functions before calling them, specially
when writing an OS!


Correct. I just have not placed the function in its final location,
where all of that will clear up.
Always remember that prototyping doesn't protect you from the UACs if
you're using variadic functions.

Richard


Thanks again,

Mac

Nov 14 '05 #8
Jack Klein wrote:
On Mon, 03 Jan 2005 00:58:05 -0600, "Mac A. Cody"
<ma*****@castcom.net> wrote in comp.lang.c:

Hello,

I'm encountering a problem with using stdarg that I cannot
figure out. I'm trying to develop a function for a linux
driver module that takes a variable-length sequence of
u8-type values. Below is the function:

#include <stdarg.h>
.
.
.
63 int sn9c102_write_va_regs(struct sn9c102_device* cam,
u16 index, int len, ...)

You can't pass unsigned characters as part of the "..." arguments to
variadic functions. You can't pass any of the character types, or
signed or unsigned short, or floats. The arguments to such functions,
after the fixed ones, undergo the default promotions.

See section 15 on functions with variable argument lists in the FAQ
for this group, link in my signature. Specifically see:

15.10 Why isn't "va_arg(argp, float)" working?

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


That reference was very helpful. Thanks!
64 {
65 int res, i;
66 u8 data[32];
67 va_list args;
68
69 va_start(args, len);
70 for (i = 0; i < len; i++) {
71 data[i] = va_arg (args, u8);
72 }
73 va_end(args);
74 res = sn9c102_write_regs(cam, index, data, len);
75 if (res < 0) {
76 DEBUG(3, "Failed to write registers starting at index "
77 "0x%02X, error %d)", index, res)
78 return -1;
79 }
80 return 0;
81 }

When I compile the code, I get the following message:

sonix_pas202b.c: In function `sn9c102_write_va_regs':
sonix_pas202b.c:74: warning: implicit declaration of function
`sn9c102_write_regs'

Well, obviously you don't have a prototype for this function in scope.
Find the proper header and include it.


Obviously true. I didn't think to mention it due to its
obviousness. In my haste, I failed to cut it out of my message.
sonix_pas202b.c:71: warning: `u8' is promoted to `int' when passed
through `...'sonix_pas202b.c:71: warning: (so you should pass `int' not
`u8' to `va_arg')

Why does the warning on line 71 occur? I believe that 'u8'
is typedef'ed somewhere in the linux kernel headers as an
'unsigned char', though I have not verified that yet. Is
there a way of telling 'va_arg' the actual type of 'u8'?

No, there is no way at all to pass variable arguments to a variadic
function with a type less than int. They will be promoted to int by
the caller, assuming that it has a prototype for the variadic function
in scope. So you have to retrieve them as type int, then you can
assign them to your unsigned char array. There will be no change in
value.


Yes, I see that now. After twenty years of C programming (off and on),
this is the first time I've ever used the stdarg facility. Guess you
can never be too old to learn something about C!

Thanks,

Mac

Nov 14 '05 #9
On Mon, 03 Jan 2005 15:31:52 +0000, Richard Bos wrote:

....
The real problem is not a _lack_ of prototype, but the fact that the
prototype in question is a variadic one. This means that the arguments
in the variadic part are subject to the Usual Arithmetic Conversions as
much as when there had not been a prototype at all.


Or rather the default argument promotions.

Lawrence

Nov 14 '05 #10

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

Similar topics

8
by: Klaus Schneider | last post by:
Hi all! I'm having trouble with a template function with variable arguments when I parse an enum type as variable argument. Example: template <class T> bool test(int num, ...) { va_list ap;...
5
by: Francesco Bochicchio | last post by:
Hi all, anybody knows if there is a (standard, portable) way to dinamically build a list of parameters to call a C function? Something like va_start & co, but to be used on the calling side? ...
6
by: Clint Olsen | last post by:
I had this crazy idea to use stdarg macros to copy data in a generic fashion, regardless of type. However, I'm not sure it will work in part due to the ANSI C default argument promotions and the...
3
by: Beta What | last post by:
Hello, I have a question about casting a function pointer. Say I want to make a generic module (say some ADT implementation) that requires a function pointer from the 'actual/other modules'...
3
by: cman | last post by:
Can somebody explain the following code segment, from stdargs.h (from linux 0.01) #define __va_rounded_size(TYPE) \ (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof...
13
by: nariknahom | last post by:
Hi, Can someone tell me what is wrong with the below program? ------------------------------------------- int main() { f1( 25 50,"testing stdarg. ", "it is working", "if it is working." );...
8
by: vaib | last post by:
hi all , It really seems that C never ceases to amaze . All this time i've been doing C and i thought i was quite adept at it but i was wrong . So without wasting any more time , here's the...
9
by: tonybalinski | last post by:
I'd like to be able to scan a va_list twice in a v... function, but can't see how to do it. For example char *strdupcat(const char *first, ...) { char *result, pos; va_list arg; size_t len;...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
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...
0
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,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

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.