I don't want you to feel as though we're harrassing you,
No...I have followed other threads and I do **not** feel harrassed.
I am at times equally frustrated at not being able to clearly
articulate my questions well.
but that's
the key part I've never understood about this thread,
An honest question and I will attempt to answer it.
May I start with an analogy ( true, by the way). In 1992 12 of us
sailed from St Augustine in Florida to Lisbon. One of the crew was
Michael Smith. A year later, in 1993 he would get the Noble Prize in
Chemistry for his work in "oligonucleotide-based, site-directed
mutagenesis and its development for protein studies". As a graduate
he wanted to understand the configurations of protein. As we sat
around the breakfast table in the middle of the ocean, he would
explain how it worked. This is the analogy he ( or his s.o..can't
remember which) gave. Imagine that you have an engine. You have no
manual, but you develop a tool to open the engine, take something out,
and put it back together again. Then you fire up the engine and see
what happens. ( Instead of looking at engines, he was looking at the
way proteins folded). If you do this enough times, taking out
different bits each time, eventually you might be able to draw a
conclusion as to what the piece you removed did. That is often the way
I have approached things in my life....maybe not driving around blind
corners, but certainly in thought experiments etc.
Now...through the course of this thread, I realize that this cannot be
applied directly to C, because of one **small** issue, calle undefined
behavior
Whereas one might get a **predictably** **different**
response by pulling out bits and pieces from DNA or an engine,
deliberately doing so in C is different.
So, at the beginning of the thread, this is what I thought.
So, let me preface this by saying
****What I am about to write is wrong thinking***
If I do not understand something, (in C) by **deliberately** creating
an error, I can try and figure out, by looking at the result , how the
**original** expression/function/whatever works
****End of wrong thinking*****
*****Correct thinking*****
If one sees a diagnostic, it **could** mean ub, but in any case, **GO
NO FURTHER** until it is understood. The end result **should** be the
same ie in terms of understanding the issue, but it sure as heck won't
frustrate the clc the way this thread has done!!!!!
**** End of hopefully correct thinking****
it. How did you reach the incorrect conclusion that they did match?
People make mistakes all the time, I'm certainly not an exception, but
I don't understand the nature of this particular mistake.
I hope the above explanation sheds some light on it. ( and see below)
The first time we saw your actual code was in your message with
Date: Sat, 6 Sep 2008 18:16:07 -0700 (PDT)
In that message, your very own code showed a correct prototype for
minprintf() commented out, in which the first parameter was declared
as 'char *'. The very next line shows an incorrect prototype,
James, originally I was going to just post the above and not answer
the specifics...but clearly you have taken the trouble to look back
through the thread, so the very least I can do is go back and show
what I was trying to ask, the relevant replies and hopefully clarify
this for you.
How could you modify the prototype without being aware of the fact
that your change would break your code? How could you see a compiler's
warning message that explained what the problem was, add a comment to
your code about that message, and yet remain unaware of the problem?
The only way this makes sense to me is if you thought that 'int' was
a synonym for 'char*', and I can't figure out what might have given
you that idea.
So, I hope this will answer some of your queries.
It all started off with a question about Macros.
Sept 5, 4:15pm (mdh) ( all times PDT)The section is titled Variable-length Argument lists.
May I ask a question about the use of "macros".
Could anyone help me understand the significance of using macros vs
functions, as I think it is more significant than I realize.
<<<<<
5:20pm (KT) (Amongst others)The reason va_start, va_arg, va_end, and va_copy are defined as
macros
is that they *can't* be defined as functions.
For example, va_arg takes two arguments, an expression of type
va_list
(I'm actually not sure it can be an arbitrary expression) and a type
name.
<<<<<<<
Then I asked about clarification of the expression va_list ap.
6:43 pm (mdh)This declares ap a pointer of type va_list? And the reason ap is a
pointer is simply because that is the way it is defined??
<<<<<
and again KT answered at 7:21pmThe standard merely says that it's "an object type suitable for
holding information needed
by the macros va_start, va_arg, va_end, and va_copy"
<<<<<<<<
There was some discussion as to why I thought what I thought, but that
was sorted out. The one thing that I could not put into context was
what the role of the "char *fmt" in the decalration "(char *fmt, ...)
was. I knew it was obviously important, in va_start.
Also at 6:43pm (mdh)
va_start(ap, fmt);
So, from what you say, if I understand this, the type here (fmt) is
"pointer to char" and the expression 'ap' is initialized or "returned"
as a pointer to char (to the first argument)?
<<<<<<<<<
And again, KT answered in the same reply at 7:21pm
va_start doesn't return anything. It initializes ap, an object of
type va_list. (That's part of the reason it's a macro; a function
can't modify an argument.) The va_list object exists to allow access
to the variadic arguments; you can think of it as a kind of abstract
index into the argument list.
The second argument to va_start is the name of the parameter just
before the ", ...".
<<<<<<<<<<<<<
After getting some sleep, I still could not understand the exact role
of "char *fmt", so the next day posted this...and this is where it all
started going downhill.
Sept 6, 11:46 am (mdh)
May I pursue another issue a little further.
void minprintf(char *fmt, ...);
or
void minprintf(int fmt, ...);
The only difference is ( maybe the **only** will raise some chuckles)
that char *fmt points to all the arguments in my debugger, but int
returns an integer( surprise, surprise!). For fear of flogging a dead
horse, is that the difference?
<<<<<<<<<<
Clearly...in hindsight, this was ***WRONG THINKING*** !!!!!...but
that is where this came from. In addition, the use of the term
debugger muddied the water even further.
I think the clc gave me a little to much credit in thinking I
understood the gravity and significance of ub. At this point, a bunch
of different questions were posed, and I tried to be diligent in
answering them as best I could, including a plea for actual code.
BS at 12:09 pm
Show your code for a minprintf with an int as its
first parameter and a sample calling statement.
<<<<<<<<<
HvD at 1:10pm
Then, please post a minimal complete program that includes the
declaration
void minprintf(int fmt, ...);, defines that function exactly the way you
have defined it now, and calls it.
<<<<<<<<<<<
Again, I tried to hone in on the one thing that was not making sense
to me.
mdh at 12:30pm
Are you saying that the role of the declaration "char *fmt" is to
tell the compiler that each argument needs to be extracted as a char?
<<<<<<<<<<<
RH ( who has been one of the stalwarts, in helping me navigate C)
quickly cut to the chase
RH at 1.23pm
f I change the declaration /and/ the definition, I get a different
diagnostic message:
foo.c:36: warning: passing arg 1 of `minprintf' makes integer from
pointer
without a cast
Can you convince me that these diagnostic messages have no
significance?
<<<<<<<<<<<<
Again...**WRONG THINKING** on my part.
KT answered ( my 12:30pm query) at 4.02pm
The *only* thing the "char *fmt, ..." part of the declaration tells
the compiler is that the first argument is of type char*, and there
will be zero or more arguments of unspecified type(s) following that.
........
For example, if a call
looks like this:
minprintf("%s = %d\n", "foobar", 42);
then minprintf itself needs to make the following calls to fetch the
parameter values:
va_list ap;
va_start(ap, fmt);
va_arg(ap, char*);
va_arg(ap, int);
va_end(ap);
<<<<<<<<<<
That should have been the end of it, but there now seemed to be a
concurrent thread that had honed in on the **WRONG THINKING** part of
my replies ie trying to explain how diagnostics had been ignored, and
meaning given to ub.
At 6:03pm ( mdh) I posted the code I think you are referring to
void minprintf(int fmt, ...)
/*void minprintf(char *fmt, ...)*/{
.....etc etc
<<<<<<<<<<
So James, I hope you understand now where that craziness came from. A
combination of **WRONG THINKING** and trying to diligently respond to
people trying to help me.
At some point, RH said.
RH at 6:50pm
/* So, here is the source of my confusion,
You hand va_start the name of the last named parameter,
When you call va_arg(), you are telling the compiler that (a) you
know
there's another argument to collect, and (b) you know its type.
and
Keith is referring
to fmt itself, which is of type char *, not type char.
For completeness,
debugger output (value of fmt) with declaration 'int fmt' =
Forget it. That isn't completeness. That's complete nonsense.
<<<<<<<<<<<<<<<<
??***
I won't make the "for completeness" mistake again!!!!
Hopefully, I have not lost BS forever!
BS at 11:20 am ( today)
But you executed code that did not compile correctly. Then you asked
why it appeared to work anyway and why your debugger showed something
you didn't expect.
<<<<<<<<<
I hope my earlier explanation covers this.
So James, I hope this does justice to all the time you have taken to
help. As I look through this thread, it's confusing to me too, at
times!!. Perhaps, it would have been more appropriate to start another
thread once the issues of the macros had been settled, as it **might**
have made it cleaner.
So, to all of the people who answered this thread, I am sorry if this
lead to frustration. One of the great joys is being part of the clc
and interacting with such amazing programmers. You have no idea
( well, maybe you do) how stimulating this is.
So thank you and ....
This is a learning curve to me too.