473,387 Members | 1,574 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,387 software developers and data experts.

arrays and K&R §5.10

What follows is an adaptation of the second program in K&R §5.10. The
changes are to elucidate (validate) the difference (sameness) of char *[]
and char**. I cannot for the life of me understand why the output looks the
way it does, in particular, with all the symmetry in arguments, why one sees
apple[0] but not argv[0]. This program was designed to run from a command
line with one argument (two if you count the prog name). The .c file
follows. Afterwards I post a link to a screenshot of output.

#include <stdio.h>

int main(int argc, char **argv)
{
char **apple;

apple[0]="tja zero";
apple[1]="tja again";

while (--argc >0)
printf("%s%s", *++argv, (argc > 1) ? " " : "");
printf("\n");

printf("%s%s", *++apple, (argc > 1) ? " " : "");
printf("\n");
return (0);
}

http://home.comcast.net/~beckjensen/cstuff3.htm

++thanks. MPJ
Nov 14 '05 #1
9 1603
"Merrill & Michele" wrote
What follows is an adaptation of the second program in K&R §5.10. The
changes are to elucidate (validate) the difference (sameness) of char *[]
and char**. I cannot for the life of me understand why the output looks the way it does, in particular, with all the symmetry in arguments, why one sees apple[0] but not argv[0]. This program was designed to run from a command
line with one argument (two if you count the prog name). The .c file
follows. Afterwards I post a link to a screenshot of output.

#include <stdio.h>

int main(int argc, char **argv)
{
char **apple;

apple[0]="tja zero";
apple[1]="tja again";

while (--argc >0)
printf("%s%s", *++argv, (argc > 1) ? " " : "");
printf("\n");

printf("%s%s", *++apple, (argc > 1) ? " " : "");
printf("\n");
return (0);
}

http://home.comcast.net/~beckjensen/cstuff3.htm

++thanks. MPJ


....sheepishly...
I figured out my problem one minute after I posted, namely, that I can't
read my own screen. I did, however, have secondary and tertiary questions
here. I have never written a program that did not specify how large a
matrix is to be. What does an ANSI-compliant compiler set aside in main
memory for apple[] in this code? Please don't tell me to read the standard.
That I read so much in that vein this weekend is the reason that I can't
read my screen now. MPJ
Nov 14 '05 #2
Merrill & Michele wrote:
What follows is an adaptation of the second program in K&R §5.10. The
changes are to elucidate (validate) the difference (sameness) of char *[]
and char**. I cannot for the life of me understand why the output looks
the way it does, in particular, with all the symmetry in arguments, why
one sees
apple[0] but not argv[0]. This program was designed to run from a command
line with one argument (two if you count the prog name). The .c file
follows. Afterwards I post a link to a screenshot of output.

#include <stdio.h>

int main(int argc, char **argv)
{
char **apple;

apple[0]="tja zero";
`apple` is uninitialised. Assigning to `apple[0]` results in
undefined behaviour. The program is broken from here on.
apple[1]="tja again";

while (--argc >0)
printf("%s%s", *++argv, (argc > 1) ? " " : "");
You do realise that the loop body finished here, ie, consisted
only of the single printf?
printf("\n");

printf("%s%s", *++apple, (argc > 1) ? " " : "");
Supposing that apple *were* properly initialised, you would skip
its first element (ie `apple[0]` aka `*apple`).
printf("\n");
return (0);
Unnecessary brackets.
}

http://home.comcast.net/~beckjensen/cstuff3.htm


Don't do that. Especially since jpegs are now an attack vector.

--
Chris "electric hedgehog" Dollin
C FAQs at: http://www.faqs.org/faqs/by-newsgrou...mp.lang.c.html
C welcome: http://www.angelfire.com/ms3/bchambl...me_to_clc.html
Nov 14 '05 #3
"Merrill & Michele" <be********@comcast.net> wrote in message
news:H_********************@comcast.com...
"Merrill & Michele" wrote
What follows is an adaptation of the second program in K&R §5.10. The changes are to elucidate (validate) the difference (sameness) of char *[] and char**. I cannot for the life of me understand why the output looks
the
way it does, in particular, with all the symmetry in arguments, why
one sees
apple[0] but not argv[0]. This program was designed to run from a
command line with one argument (two if you count the prog name). The .c file follows. Afterwards I post a link to a screenshot of output.

#include <stdio.h>

int main(int argc, char **argv)
{
char **apple;

apple[0]="tja zero";
apple[1]="tja again";

while (--argc >0)
printf("%s%s", *++argv, (argc > 1) ? " " : "");
printf("\n");

printf("%s%s", *++apple, (argc > 1) ? " " : "");
printf("\n");
return (0);
}

http://home.comcast.net/~beckjensen/cstuff3.htm

++thanks. MPJ


...sheepishly...
I figured out my problem one minute after I posted, namely, that I

can't read my own screen. I did, however, have secondary and tertiary questions here. I have never written a program that did not specify how large a
matrix is to be. What does an ANSI-compliant compiler set aside in main memory for apple[] in this code? Please don't tell me to read the standard. That I read so much in that vein this weekend is the reason that I can't read my screen now. MPJ


I'm not sure what you are trying to prove, but you have a single pointer
(apple) and you are setting it using [0] and [1] as if you had an array.
A char pointer pointer can point to an array of pointers, but it is one
pointer, not an array of pointers. It points to arrays of char, but it
is one pointer - there is no apple[1].

--
Mabden
Nov 14 '05 #4
Merrill & Michele <be********@comcast.net> wrote:
"Merrill & Michele" wrote
What follows is an adaptation of the second program in K&R §5.10. The
changes are to elucidate (validate) the difference (sameness) of char *[]
and char**. I cannot for the life of me understand why the output looks
the way it does, in particular, with all the symmetry in arguments, why one
sees apple[0] but not argv[0]. This program was designed to run from a
command line with one argument (two if you count the prog name). The .c
file follows. Afterwards I post a link to a screenshot of output.

#include <stdio.h>

int main(int argc, char **argv)
{
char **apple;

apple[0]="tja zero";
apple[1]="tja again";

while (--argc >0)
printf("%s%s", *++argv, (argc > 1) ? " " : "");
printf("\n");

printf("%s%s", *++apple, (argc > 1) ? " " : "");
printf("\n");
return (0);
}

http://home.comcast.net/~beckjensen/cstuff3.htm

++thanks. MPJ
...sheepishly...
I figured out my problem one minute after I posted, namely, that I can't
read my own screen. I did, however, have secondary and tertiary questions
here. I have never written a program that did not specify how large a
matrix is to be. What does an ANSI-compliant compiler set aside in main
memory for apple[] in this code?


You don't have any "apple[]" in your program. 'apple' is a pointer to
a char pointer. It's _NOT_ an array, it's just a pointer and all the
compiler sets aside for you is enough space to store a single pointer
to a pointer to char. Not more and not less. To be able to use it
like an array you have to first allocate memory it points to.

Moreover, after the definition it points to some random location in
memory. But then you try to assign a value to what you suddenly start
treating as an array of char pointers, i.e. you try to push values into
the the random place it's pointing to. If you're unlucky, this might
even seem to work because what 'apple' is pointing to is random and so
by chance it could point to some location you can change and you then
happily write into some memory you don't own, possibly overwriting
some important other data. If you're lucky and it points to some
memory you're not allowed to change you get a segmentation fault and
then you at least know immediately that you made a bad mistake.

To use 'apple' in the way you try to do it you first have to obtain
some memory it's pointing to. For that you need malloc(). You would
e.g. do:

char **apple;

apple = malloc( 2 * sizeof *apple );
if ( apple == NULL ) {
fprintf( stderr, "Not enought memory.\n" );
exit( EXIT_FAILURE );
}

Thereby you now have the 'apple' pointer initialized to point to
2 char pointers and you now can proceed with your assignments:

apple[ 0 ] = "tja zero";
apple[ 1 ] = "tja again";

If you should later in your program realize that you need a larger
(or smaller) array of char pointers you could use realloc() to
change the size of the memory area 'apple' is pointing to.

It's considered good practise to clean up after yourself, so when
you don't need the memory 'apple' is pointing to anymore you should
call free() on it. To do that you must pass the same value you got
from malloc() to free() and therefore one usually would try to avoid
changing 'apple' at all. Since you don't know in advance how many
command line arguments there are going to be you don't know at the
end if 'apple' has been incremented twice or not at all, so you
aren't able to free() the memory you allocated. So you created what
is commonly called a memory leak - you lost the information about
memory you allocated and are unable to deallocate it, so, if you
would have a long program where the code would be called again and
again, the program would use more and more memory without really
needing it.
Regards, Jens
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Nov 14 '05 #5
"Merrill & Michele" wrote .
The following seeks to elucidate (validate) the difference (sameness) of
char *[] and char**. I cannot for the life of me understand why the output looks
the
way it does, in particular, with all the symmetry in arguments, why
one sees
apple[0] but not argv[0]. This program was designed to run from a
command line with one argument (two if you count the prog name). The .c file follows. Afterwards I post a link to a screenshot of output.

#include <stdio.h>

int main(int argc, char **argv)
{
char **apple;

apple[0]="tja zero";
apple[1]="tja again";

while (--argc >0)
printf("%s%s", *++argv, (argc > 1) ? " " : "");
printf("\n");

printf("%s%s", *++apple, (argc > 1) ? " " : "");
printf("\n");
return (0);
}

http://home.comcast.net/~beckjensen/cstuff3.htm

++thanks. MPJ

...sheepishly...
What does an ANSI-compliant compiler set aside in
main
memory for apple[] in this code?
<Je***********@physik.fu-berlin.de>
You don't have any "apple[]" in your program. 'apple' is a pointer to
a char pointer. It's _NOT_ an array, it's just a pointer and all the
compiler sets aside for you is enough space to store a single pointer
to a pointer to char. Not more and not less. To be able to use it
like an array you have to first allocate memory it points to.

Moreover, after the definition it points to some random location in
memory. But then you try to assign a value to what you suddenly start
treating as an array of char pointers, i.e. you try to push values into
the the random place it's pointing to. If you're unlucky, this might
even seem to work because what 'apple' is pointing to is random and so
by chance it could point to some location you can change and you then
happily write into some memory you don't own, possibly overwriting
some important other data. If you're lucky and it points to some
memory you're not allowed to change you get a segmentation fault and
then you at least know immediately that you made a bad mistake.

To use 'apple' in the way you try to do it you first have to obtain
some memory it's pointing to. For that you need malloc(). You would
e.g. do:

char **apple;

apple = malloc( 2 * sizeof *apple );
if ( apple == NULL ) {
fprintf( stderr, "Not enought memory.\n" );
exit( EXIT_FAILURE );
}

Thereby you now have the 'apple' pointer initialized to point to
2 char pointers and you now can proceed with your assignments:

apple[ 0 ] = "tja zero";
apple[ 1 ] = "tja again";

If you should later in your program realize that you need a larger
(or smaller) array of char pointers you could use realloc() to
change the size of the memory area 'apple' is pointing to.

It's considered good practise to clean up after yourself, so when
you don't need the memory 'apple' is pointing to anymore you should
call free() on it. To do that you must pass the same value you got
from malloc() to free() and therefore one usually would try to avoid
changing 'apple' at all. Since you don't know in advance how many
command line arguments there are going to be you don't know at the
end if 'apple' has been incremented twice or not at all, so you
aren't able to free() the memory you allocated. So you created what
is commonly called a memory leak - you lost the information about
memory you allocated and are unable to deallocate it, so, if you
would have a long program where the code would be called again and
again, the program would use more and more memory without really
needing it.
Regards, Jens


Thanks for replies: Mr. Dollin, Mabden, Dr. Toerring (I assume you
defended.)

Ouch. When I stumbled into undefined behavior, I was expecting Scott Nudds
to fly out of my hard drive. I was extraordinarily surprised that this
program compiled. Does it say something about my compiler or its settings
that it didn't tell me, "Dude you're stoned."

As for Mr. Dollin's comment on the screenshot:Don't do that. Especially since jpegs are now an attack vector.

My .jpegs attack no one. They help other people to point out where I'm
being a complete ninny. MPJ


Nov 14 '05 #6
><Je***********@physik.fu-berlin.de>
[wrote -- message-ID missing, but from references: line it must have
been <2s*************@uni-berlin.de> ... snippage:]
To use 'apple' in the way you try to do it you first have to obtain
some memory it's pointing to. For that you need malloc(). You would
e.g. do:

char **apple;

apple = malloc( 2 * sizeof *apple ); [more snippage, including test for failure]

It is not absolutely *required* that one use malloc() here. For
instance, this will work just as well:

char **apple;
char *mem[2];

apple = mem;

Unless "apple" ever changes, though, there is little point to
introducing it as an auxiliary -- one might as well just use mem[0]
and mem[1] directly.

The big advantage to malloc() is that you can pass it a number that
is at least partly determined at runtime. The size "2" in the
above must be a constant in C89. (C99 does allow variable sizes,
at least for ordinary local arrays allocated at block entry,
producing "variable length arrays" or VLAs. The precise constraints
on VLAs are a little hard to describe.)

In article <news:d_********************@comcast.com>
Merrill & Michele <be********@comcast.net> wrote:
Ouch. When I stumbled into undefined behavior, I was expecting Scott Nudds
to fly out of my hard drive. I was extraordinarily surprised that this
program compiled. Does it say something about my compiler or its settings
that it didn't tell me, "Dude you're stoned."
Better compilers will generally print warnings for "obvious" cases
of undefined behavior (though perhaps only by specific request, as
is often true for gcc: -O and -Wuninitialized are both required
here, although -Wuninitialized can be requested under the general
"-Wall" group).

Undefined behavior is allowed to do *anything*, though, including
the most insidious of all: appear to work as intended, just until
it becomes important that it actually work.
As for Mr. Dollin's comment on the screenshot:Don't do that. Especially since jpegs are now an attack vector.

My .jpegs attack no one. They help other people to point out where I'm
being a complete ninny. MPJ


He is referring to Yet Another Bug in Microsoft-ware. One of the
MS-Windows dynamic libraries that decodes JPG files has Yet Another
Buffer Overflow in it (well, at least we cannot blame gets() for
this one :-) ). This buffer overflow -- probably resulting from
C code with undefined behavior! -- allows attackers to run arbitrary
executable code on Microsoft Windows boxes whenever the unsuspecting
user views a JPG image.

Given the prevalence of JPGs, it is not clear what to do about this
in general, other than "not use Microsoft-ware". :-) That particular
DLL has an MS-provided fix, but one must be aware that the fix only
fixes one copy; there may be other copies and/or other versions of
that DLL in use, and those will continue to have the bug. Thus,
if you use Windows, you may be taking a risk every time you view
a JPG image (unless you know for sure which program(s) will be
using a corrected DLL). If the image is stored on a compromised
Microsoft server, even a "known-pedigree" JPG image may have had
virus or worm code loaded into it after the fact.

In this particular case, however, the "thing to do" about it is to
use nothing but plain text in comp.lang.c.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #7
Merrill & Michele <be********@comcast.net> wrote:
Ouch. When I stumbled into undefined behavior, I was expecting Scott Nudds
to fly out of my hard drive. I was extraordinarily surprised that this
program compiled. Does it say something about my compiler or its settings
that it didn't tell me, "Dude you're stoned."


No. First of all, C gives you enough rope to hang yourself and
that's for a good reason: sometimes you need that much rope. And
then undefined behaviour isn't always something bad. Writing e.g.
to memory you don't own (i.e. never allocated) is sometimes even
necessary. If you're writing a device driver you may have to write
into certain memory locations you know registers of the device are
mapped to. Of course, the C standard can't know about that, so it
is undefined behaviour from a standard C point of view - but it's
(hopefully) very well defined what's going to happen by the the
documentation for the machine/device you're doing that on. So the
compiler has no reason to complain about it.

Actually, undefined behaviour just means what it says - the be-
haviour is not defined by the C standard. That doesn't mean that
Scott Nudds is going to do something indecent with your hard drive.
It's just one of the many (less likely) possibilities. What's im-
portant is to know what's defined and what's undefined so that one
can avoid the later unless one has to use it because one knows what
is going to happen (from some other information, not the C standard)
and there's no other good method to make that happen.

Regards, Jens
--
\ Jens Thoms Toerring ___ Je***********@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Nov 14 '05 #8
On Mon, 4 Oct 2004 11:24:30 -0500, "Merrill & Michele"
<be********@comcast.net> wrote in comp.lang.c:
"Merrill & Michele" wrote
What follows is an adaptation of the second program in K&R §5.10. The
changes are to elucidate (validate) the difference (sameness) of char *[]
and char**. I cannot for the life of me understand why the output looks

the
way it does, in particular, with all the symmetry in arguments, why one

sees
apple[0] but not argv[0]. This program was designed to run from a command
line with one argument (two if you count the prog name). The .c file
follows. Afterwards I post a link to a screenshot of output.

#include <stdio.h>

int main(int argc, char **argv)
{
char **apple;

apple[0]="tja zero";
apple[1]="tja again";

while (--argc >0)
printf("%s%s", *++argv, (argc > 1) ? " " : "");
printf("\n");

printf("%s%s", *++apple, (argc > 1) ? " " : "");
printf("\n");
return (0);
}

http://home.comcast.net/~beckjensen/cstuff3.htm

++thanks. MPJ


...sheepishly...
I figured out my problem one minute after I posted, namely, that I can't
read my own screen. I did, however, have secondary and tertiary questions
here. I have never written a program that did not specify how large a
matrix is to be. What does an ANSI-compliant compiler set aside in main
memory for apple[] in this code? Please don't tell me to read the standard.
That I read so much in that vein this weekend is the reason that I can't
read my screen now. MPJ


The term is 'array', not 'matrix'. There are some languages that have
native support for a matrix data type, but C is not among them. C
does not even really have multi-dimensional arrays, merely arrays of
arrays. The array in C is very strictly a linear type.

As for how much memory is allocated for apple[], there is no
'apple[]', there is a pointer named 'apple', which is NOT an array.

POINTER RULE 1: Defining a pointer in C DOES NOT create anything for
the pointer to point to, nor does it point the pointer at anything at
all.

POINTER RULE 2: Never forget pointer rule 1.

--
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 #9
In <3s********************************@4ax.com> Jack Klein <ja*******@spamcop.net> writes:
The term is 'array', not 'matrix'. There are some languages that have
native support for a matrix data type, but C is not among them. C
does not even really have multi-dimensional arrays, merely arrays of ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^arrays. The array in C is very strictly a linear type.


Although I happen to agree with Jack on this one, the C standard itself
seems to suggest the opposite:

3 Successive subscript operators designate an element of a
multidimensional array object. If E is an n-dimensional array
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
(n >= 2) with dimensions i × j × . . . × k, then E (used as
other than an lvalue) is converted to a pointer to an (n -
1)-dimensional array with dimensions j × . . . × k. If the unary
* operator is applied to this pointer explicitly, or implicitly
as a result of subscripting, the result is the pointed-to (n -
1)-dimensional array, which itself is converted into a pointer if
used as other than an lvalue. It follows from this that arrays
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
are stored in row-major order (last subscript varies fastest).
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Currently looking for a job in the European Union
Nov 14 '05 #10

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

Similar topics

2
by: J. Campbell | last post by:
I have a class that contains an array of integers that hold the state of my 'system'. The system must be updated periodically. I need to update the whole system at once, at which point the system...
2
by: LeTubs | last post by:
Hi I have few questions in realtion to arrays, I assume that they are not available as a data type, is this correct ? The reason why is that I want to store a large amount of data for a...
4
by: Zion Zadik | last post by:
Dear all, I have a set of c# data classes which i need to fill their data from xml files. serialization looks to be the best way to accomplish this task. Since the data classes are compiled and...
2
by: Mark Hannon | last post by:
I am trying to wrap my brain around storing form elements inside variables & arrays before I move on to a more complicated project. I created this simple example to experiment and as far as I can...
1
by: strotee | last post by:
#include <iostream> #include <ctime> using namespace std; // function declarations void swap(int *a, int *b); void sort(int arr, int beg, int end); int main() {
2
by: assgar | last post by:
Hi Developemnt on win2003 server. Final server will be linux Apache,Mysql and PHP is being used. I use 2 scripts(form and process). The form displays multiple dynamic rows with chechboxs,...
12
by: arnuld | last post by:
i was able to create a solution for a Horizontal-Histogram. i was completely unable to understand this Vertical-Histogram phenomenon. even though i have looked at the solution at this page: ...
4
by: pmactdot | last post by:
Hi, I'm looking for some assistance on a case study...I have two arrays <head>: one for daily special dish name, second for the daily dish description, then I have two document.write: a daily...
0
by: David Thompson | last post by:
On Wed, 09 Apr 2008 12:34:43 +0500, arnuld <arnVuld@ippiVmail.com> wrote: I think you've got the idea, but: - I would be careful about using 'equal'. Pointers and arrays are different things,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
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
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
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:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

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.