Arrays

M

mdh

From the list of questions...arrays certianly seem to be the biggest
source of puzzlement. I can understand why.
I reluctantly ask this...knowing it does not work, but the issue is
why? ( It is related to exercise 5-13, K&R). I have looked at the FAQ,
but still no luck.

#include <stdio.h>
#include <string.h>

int main (int argc, const char * argv[]) {
char *r[]={"abc","bcd","cde"};

char s[]="uv";
char t[]="vw";
char u[]="wx";

strcpy(r[0], s);
strcpy(r[1], t);
strcpy(r[2], u);


printf("Hello, World!\n");
return 0;
}
My compiler gives a Sigbus 10 error...whatever that means :) Please
be gentle in replying!!
 
C

CBFalconer

mdh said:
.... snip ...

#include <stdio.h>
#include <string.h>

int main (int argc, const char * argv[]) {
char *r[]={"abc","bcd","cde"};

char s[]="uv";
char t[]="vw";
char u[]="wx";

strcpy(r[0], s);
strcpy(r[1], t);
strcpy(r[2], u);

printf("Hello, World!\n");
return 0;
}
My compiler gives a Sigbus 10 error...whatever that means :)
Please be gentle in replying!!

Look at your system documentation. I suspect it means you tried to
write to the non-writable arrays indexed in r with strcpy.
 
P

pete

mdh said:
From the list of questions...arrays certianly seem to be the biggest
source of puzzlement. I can understand why.
I reluctantly ask this...knowing it does not work, but the issue is
why? ( It is related to exercise 5-13, K&R). I have looked at the FAQ,
but still no luck.

#include <stdio.h>
#include <string.h>

int main (int argc, const char * argv[]) {
char *r[]={"abc","bcd","cde"};

char s[]="uv";
char t[]="vw";
char u[]="wx";

strcpy(r[0], s);
strcpy(r[1], t);
strcpy(r[2], u);

printf("Hello, World!\n");
return 0;
}
My compiler gives a Sigbus 10 error...whatever that means :) Please
be gentle in replying!!

/* BEGIN new.c */

#include <stdio.h>
#include <string.h>

int main (void)
{
size_t index;
char r[][sizeof"abc"] = {"abc", "bcd", "cde"};
char s[] = "uv";
char t[] = "vw";
char u[] = "wx";

strcpy(r[0], s);
strcpy(r[1], t);
strcpy(r[2], u);
for (index = 0; index != sizeof r / sizeof *r; ++index) {
puts(r[index]);
}
puts("Hello, World!");
return 0;
}

/* END new.c */
 
J

Jens Thoms Toerring

mdh said:
source of puzzlement. I can understand why.
I reluctantly ask this...knowing it does not work, but the issue is
why? ( It is related to exercise 5-13, K&R). I have looked at the FAQ,
but still no luck.
#include <stdio.h>
#include <string.h>
int main (int argc, const char * argv[]) {

int main( void )

would probably do in this case;-)
char *r[]={"abc","bcd","cde"};

What you define here is an array of three pointer, with each of them
initialized to point to a string literal. String literals are strings
that the compiler stows away somewhere in memory that you are not
allowed to write to, only to read from. (On some implementations
you actually can write to string literals, but that's not something
you should get in the habit of expecting.)
char s[]="uv";
char t[]="vw";
char u[]="wx";

Here you do something very different even though on a first glance it
may look similar. You define here three arrays, each with 3 elements
and the elements are initialized with the characters of the strings
on the right hand side. And each of these arrays consist of memory
that you can read from and write to as much as you like (and as long
as you don't try to read or write past the array boundaries;-).
strcpy(r[0], s);

And here you try to write to the memory where e the string literal
is stored that r[0] is pointing to. It looks like on your system
trying to write to that kind of memory is not possible at all. So
your program dies. If you would do it the other way round like in

char *r[] = {"uv","vw","wx"};
char s[] = "abc";
char t[] = "bcd";
char u[] = "cde";

strcpy(s, r[0]);

everything would be fine since now would be copying from the string
literal (i.e. only reading it) to memory you're allowed to write to.
My compiler gives a Sigbus 10 error...whatever that means :)

That often means that you try to write to a memory address that
is not properly aligned for the object you want to write to it.
E.g. on some machines an int must always be stored at an even
address (or even an address that's can be divided by four). If
you try to assign to write an int instead to an odd address
then you get a SIGBUS error. Often this is achieved by careless
programmers by using improper casts, like e.g.

char s[ 10 ];
char *p = s + 1;
int x = 3;
* ( int * ) p = x;

This may fail with a SIGBUS if 's' starts at an even address (but
there are also a lot of systems where it won't fail since they
have no such restriction). You should always use memcpy() if you
really have to do such things.

But on some systems you get a SIGBUS also if you try to write to
the memory of a string literal (I think on FreeBSD for all attempts
to write to read-only memory). On others you may get a SIGSEGV, i.e.
a segmentation fault (e.g. on Linux).

Regards, Jens
 
M

mdeh

On 2007-04-25 12:21:30 -0700, (e-mail address removed) (Jens Thoms Toerring) said:

Thanks Jens.
I would have replied a lot sooner, but Google seems to have taken a
siesta!!! Posts are taking up to 24 hours to be seen by me.

char *r[]={"abc","bcd","cde"};

What you define here is an array of three pointer, with each of them
initialized to point to a string literal. String literals are strings
that the compiler stows away somewhere in memory that you are not
allowed to write to, only to read from.


As someone else privately explained...I should think of these as
constants ie unchangeable.

char s[]="uv";
char t[]="vw";
char u[]="wx";

Here you do something very different even though on a first glance it
may look similar. You define here three arrays, each with 3 elements
and the elements are initialized with the characters of the strings
on the right hand side.


So, conceptually, is this like "assigning" bytes to a variable....even
though this analogy might get some people pulling their hair out? In
other words, I have set aside memory to hold , in this case characters,
whereas in the first instance, I only have control over the pointers?
So, I should be able to direct the pointers to another literal? Or,
once I have defined char *r[], as such, it is unchangeable?

But on some systems you get a SIGBUS also if you try to write to
the memory of a string literal


Thanks...lets see if this new usenet reader works :)
 
R

Richard Heathfield

mdeh said:
So, I should be able to direct the pointers to another literal?

Yes, you can. You can even direct them to non-literals, e.g.

char s[] = "Oh what a beautiful MOOOORRRRNNNIIIINNNGG";
char t[] = "Oh what a beautiful day!"

r[] is an array of three char *, so each of its elements is a char *.
And s and t are both arrays of char, and because of The Rule you can
almost always think of an array name as the address of the first
element, i.e. a char *, so you can do this:

r[0] = s;
r[1] = t;

If you do so, r[2] still points to the "cde" literal. Nothing points to
the "abc" or "bcd" literals any more (unless you were careful to
preserve those pointers) but that's no big deal, really. r[0] now
points to that first 'O' character in s - and of course s is an array
of char, memory that you own, so it's okay to update it through s or
indeed through r. You could now reasonably say, for example:

r[0][1] = 'n';

and s would now be storing "On what a beautiful MOOOORRRRNNNIIIINNNGG"
instead.

Just remember that Everything Has To Be Somewhere, and that there are
(at least) three kinds of Somewhere: Somewhere You Can Look, Somewhere
You Can Look And Touch, and Somewhere You Can't Even Look.
 
J

Jens Thoms Toerring

mdeh said:
char *r[]={"abc","bcd","cde"};

What you define here is an array of three pointer, with each of them
initialized to point to a string literal. String literals are strings
that the compiler stows away somewhere in memory that you are not
allowed to write to, only to read from.

As someone else privately explained...I should think of these as
constants ie unchangeable.

Definitely. And since the compiler can assume that they are
read-only it can do re-use parts of literal strings. E.g. if
you have

char *r[ ] = { "Hello world", "world" };

you may end up with r[1] == r[0] + 6, i.e. the second pointer
pointing to the "world" part of the string literal the first
pointer points to.
char s[]="uv";
char t[]="vw";
char u[]="wx";

Here you do something very different even though on a first glance it
may look similar. You define here three arrays, each with 3 elements
and the elements are initialized with the characters of the strings
on the right hand side.
So, conceptually, is this like "assigning" bytes to a variable...

It's just a shortcut for the normal array initialization:

char s[ ] = { 'u', 'w', '\0' };

But since initializing strings that way would be rather tedious
to type in and hard to read we're allowed to shorten that to the
more convenient version of writing it as if we would be assigning
a string. The drawback is, of course, that it makes it easier to
get confused about the difference between

char s[ ] = "uv";

and

char *s = "uw";

which do very different things while looking rather similar at
the first glance.
Regards, Jens
 
M

mdeh

mdeh said:
char *r[]={"abc","bcd","cde"};
So, I should be able to direct the pointers to another literal?

Yes, you can. You can even direct them to non-literals, e.g.

char s[] = "Oh what a beautiful MOOOORRRRNNNIIIINNNGG";
char t[] = "Oh what a beautiful day!"

, so you can do this:

r[0] = s;
r[1] = t;

snip...
You could now reasonably say, for example:

r[0][1] = 'n';

and s would now be storing "On what a beautiful MOOOORRRRNNNIIIINNNGG"



Thank you for explaining that.
 
M

mdeh

So, conceptually, is this like "assigning" bytes to a variable...

It's just a shortcut for the normal array initialization:

char s[ ] = { 'u', 'w', '\0' };

The drawback is, of course, that it makes it easier to
get confused about the difference between

Yep!!!


Thanks to both of you for explaining this so well.
 

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

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
DewittMill
Top