Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Newsgroups | comp.lang.c |
| Subject | Re: what is data type 'int *' ? |
| Date | 2015-02-05 08:43 -0800 |
| Organization | None to speak of |
| Message-ID | <ln1tm4mhpx.fsf@nuthaus.mib.org> (permalink) |
| References | <mauauc$p5v$1@dont-email.me> <maumml$m0o$2@dont-email.me> |
Richard Heathfield <rjh@cpax.org.uk> writes:
> On 04/02/15 23:45, bilsch wrote:
>> > A Sams book on C programming
[...]
>> > int main()
>
> Keith Thompson would argue that this is better:
>
> int main(void)
>
> If you want to know why, ask Keith. There is a point to it, but I can
> never remember what it is, so it's probably not /that/ important, but
> Keith may disagree on that, and he's a chap that decent chaps listen to
> (even if they can't always remember exactly what he said!).
I recommend using `int main(void){}` rather than `int main(){}`, but
it's a fairly trivial issue whose full explanation far outweighs its
actual importance.
Every C compiler I've seen will accept either `int main(void)` or
`int main()` without complaint. My argument is that compilers are
required by the standard to accept the former, but not the latter
(though they're *permitted* to accept both).
The standard states that main shall be defined as:
int main(void) { /* ... */ }
or as
int main(int argc, char *argv[]) { /* ... */ }
"or equivalent", or in some other implementation-defined manner. I've
argued that, for slightly obscure technical reasons that some quite
smart people disagree with, "int main()" is not equivalent to
"int main(void)". I won't go into those reasons here unless someone
insists on it. When I get the proverbial Round Tuit, I'll post an
article on my technical blog so I can just link to it when the subject
comes up.
One of the goals of the ANSI C standard was to maintain backward
compatibility with pre-ANSI C, which did not have the "void"
keyword -- so arguably `int main() { /* ... */ }` *should* have been
explicitly permitted, and the committee may well have intended to do
so. If so, in my opinion they did not clearly express that intent.
Apart from whether compilers are required to accept it or not,
`void main(){}` is an *old-style* definition. Old-style function
declarations and definitions are "obsolescent" feature, meaning that
the committee has warned us that support for them may be removed
in a future edition of the standard. But in more than two decades,
they've never actually done so.
[...]
> Since ptr also has the type "pointer to int", there is no problem
> assigning the value "&var" to the object named "ptr". (There *is* a
> problem doing it the other way around, because you can't change an
> object's address via assignment: &var = ptr; is not legal.)
Similarly,
var = 42;
is legal, but
42 = var;
is not.
> But we can get around this apparent limitation by sending the address of
> the object instead. To continue the analogy, imagine writing your house
> address on a piece of paper. Take a photograph of the piece of paper,
> and hand the photograph to the arsonist. Well, a photograph of a
> hand-written address is just as useful as the original, right? So now
> the arsonist can find your home, and now he can burn it down. Or maybe
> he can mow your lawn, if he's in a good mood. A photo of an ADDRESS is
> just as good as the original address.
Or he can just burn the photograph, which has no effect on the actual
house. The analogy is that a function with a pointer parameter can
either modify that pointer (which has no effect on the object it points
to) or it can *dereference* the pointer and modify the object it points
to.
Passing a pointer means a function *can* modify the object it points to,
but it doesn't have to. Sometimes it makes sense to pass a pointer
rather than passing the value of the object just because the object is
big, and passing a copy would be relatively inefficient. (You can use
"const" to forbid changing the object; I won't elaborate on that here.)
[...]
> printf is a function, like any other (all right, not /quite/ like any
> other, because the way it's prototyped is a bit strange; but it's still
> just a function). And, like most functions, it takes parameters.
>
> Argument: something you pass to a function
> Parameter: something a function receives
I'd say a function *takes* arguments and *has* parameters, but that's a
small quibble, and you've explained the distinction anyway.
> Here, we pass printf two arguments. They are:
>
> "direct access var = %i\n"
>
> and
>
> var
>
> in that lexical order.
>
> C now *evaluates* these arguments.
>
> The string "direct access var = %i\n" is in fact an array of characters.
> When you evaluate an array, what you get (in C, at least!) is a pointer
> to the first element in that array. That's enough information for printf
> to be able to find the rest of the array, and it knows when to stop
> because C strings are null-terminated ('\0' at the end, automatically
> inserted into 'string literals' like this one, in almost all cases, and
> the only exception is one that you shouldn't have to worry about for now).
>
> var is evaluated as 1.
>
> So what the compiler sends to printf is actually the address of the 'd'
> of "direct access var = %i\n", and a 1.
>
> The printf function uses your first argument (its first parameter) to
> work out how much more information you are (claiming to be) sending to
> it. The % is the giveaway. % means "heads-up, something happening here".
> (That is why you have to be wary when your program outputs percentages.
> To tell printf to print a % sign, you have to write %% rather than just
> % on its own.)
>
> The character(s) following the % sign tell printf what to do. %i means
> "print an int", so printf looks in its parameter list for the next
> parameter, treats it as an int, and displays the value on stdout, the
> standard output device, normally your screen. And that's why printf
> prints 1.
>
> Interestingly, if you forget to send it var as well (and we've all done
> it), printf won't care. It'll grab what it /thinks/ is the next
> parameter (which in practice will be some random gobs of RAM), and print
> /that/ as an int. Fortunately, many compilers are wise to this nowadays,
> and will squeal at you at compilation time.
>
>> > printf("\nindirect access var= %i",*ptr);
>
> Apart from the terrible formatting, this line is fine. The string is
> evaluated as before. *ptr is evaluated as: "the value of the object
> pointed to by ptr". Since ptr points to var (i.e. holds the address of
> var), *ptr means in this case "the value of var", i.e. 1. And so printf
> actually receives 1 as its second parameter. It doesn't know anything at
> all about ptr.
>
>> >
>> > /* display the address of var two ways */
>
> What the author didn't tell you is that both these ways are wrong.
>
>> > printf("\nthe address of var is %i\n",ptr);
>> > printf("\nthe address of var is %i\n",&var);
>
> ptr has type int *, but %i tells printf to expect an int.
>
> In many cases, ptr and int have the same size (in bits), so printf
> doesn't necessarily know or care that there's a problem here. But *we*
> should care, because int * is not int, and int is not int *.
>
> To print a pointer value, use %p. Since there are infinitely many
> pointer types (for certain values of "infinitely"), it would be
> impractical to have a different format specifier for every pointer type.
> So the printf function offers just one (two if you count %s, which is
> rather different in semantics): %p for void *.
>
> In general, void * is a synonym for "any old object pointer type". But,
> where variadic functions are concerned, it pays to be careful because
> printf doesn't know in advance that you're sending a void * as your
> second argument. In fact, the first and second times you called it, you
> passed an int, not a void *. In other words, the type can change from
> call to call. So printf can't tell until runtime what type to expect. So
> it can't define its own parameter list in terms of void *, and that
> means you can't expect an automatic conversion, so you have to supply
> one explicitly, by means of a cast: (void *)ptr - hence we get:
>
> printf("\nthe address of var is %p\n", (void *)ptr);
> printf("\nthe address of var is %p\n", (void *)&var);
>
> And there we have it.
>
> I *hope* I have unpacked your question in sufficient detail that you can
> now actually understand what is going on. But, if I haven't, please do
> feel free to ask follow-up questions.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Back to comp.lang.c | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
what is data type 'int *' ? bilsch <king621@comcast.net> - 2015-02-04 23:45 +0000
Re: what is data type 'int *' ? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-02-05 00:09 +0000
Re: what is data type 'int *' ? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-02-05 01:24 +0000
Re: what is data type 'int *' ? James Kuyper <jameskuyper@verizon.net> - 2015-02-05 07:00 -0500
Re: what is data type 'int *' ? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-02-05 14:09 +0000
Re: what is data type 'int *' ? Robert Wessel <robertwessel2@yahoo.com> - 2015-02-05 13:08 -0600
Re: what is data type 'int *' ? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-02-06 00:33 +0000
Re: what is data type 'int *' ? Robert Wessel <robertwessel2@yahoo.com> - 2015-02-05 19:30 -0600
Re: what is data type 'int *' ? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-02-06 10:17 +0000
Re: what is data type 'int *' ? Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-02-07 13:21 -0800
Re: what is data type 'int *' ? Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2015-02-04 19:47 -0500
Re: what is data type 'int *' ? bilsch <king621@comcast.net> - 2015-02-05 09:40 +0000
Re: what is data type 'int *' ? Richard Heathfield <rjh@cpax.org.uk> - 2015-02-05 09:51 +0000
Re: what is data type 'int *' ? Keith Thompson <kst-u@mib.org> - 2015-02-05 08:04 -0800
Re: what is data type 'int *' ? glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-02-06 00:42 +0000
Re: what is data type 'int *' ? Keith Thompson <kst-u@mib.org> - 2015-02-05 19:09 -0800
Re: what is data type 'int *' ? Kaz Kylheku <kaz@kylheku.com> - 2015-02-05 01:17 +0000
Re: what is data type 'int *' ? Richard Heathfield <rjh@cpax.org.uk> - 2015-02-05 03:04 +0000
Re: what is data type 'int *' ? Richard Heathfield <rjh@cpax.org.uk> - 2015-02-05 03:06 +0000
Re: what is data type 'int *' ? Richard Heathfield <rjh@cpax.org.uk> - 2015-02-05 03:06 +0000
Re: what is data type 'int *' ? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-02-05 10:20 +0000
Re: what is data type 'int *' ? Richard Heathfield <rjh@cpax.org.uk> - 2015-02-05 10:47 +0000
Re: what is data type 'int *' ? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-02-05 12:18 +0000
Re: what is data type 'int *' ? Richard Heathfield <rjh@cpax.org.uk> - 2015-02-05 12:40 +0000
Re: what is data type 'int *' ? Keith Thompson <kst-u@mib.org> - 2015-02-05 08:24 -0800
Re: what is data type 'int *' ? James Kuyper <jameskuyper@verizon.net> - 2015-02-05 11:42 -0500
Re: what is data type 'int *' ? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-02-05 17:13 +0000
Re: what is data type 'int *' ? Keith Thompson <kst-u@mib.org> - 2015-02-05 08:43 -0800
Re: what is data type 'int *' ? bilsch <king621@comcast.net> - 2015-02-05 09:45 +0000
THANKS FOR THE INFO bilsch <king621@comcast.net> - 2015-02-05 09:47 +0000
csiph-web