How to create separate character pointers?

L

Lambda

I'd like to create separate character pointers,
pass them to a function to assign each one different value,
and assign the pointers to an array.

But when I try:

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

int main(void)
{
int i;

for (i = 0; i < 5; ++i)
{
char *str = "test";
printf("%p:%s\n", str, str);
}

return 0;
}

All the pointers refer to the same address.
When the 'char *str = "test"' is run, no new pointer is created?
 
E

Eric Sosman

Lambda said:
I'd like to create separate character pointers,
pass them to a function to assign each one different value,
and assign the pointers to an array.

But when I try:

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

int main(void)
{
int i;

for (i = 0; i < 5; ++i)
{
char *str = "test";
printf("%p:%s\n", str, str);
}

return 0;
}

All the pointers refer to the same address.
When the 'char *str = "test"' is run, no new pointer is created?

Each execution of the loop creates a new `str' variable.
Each time, that variable is initialized to point to the same
"test" string. If your telephone number is written on five
pieces of paper, it doesn't mean you have five different
telephones.
 
J

James Kuyper

Lambda said:
I'd like to create separate character pointers,
pass them to a function to assign each one different value,
and assign the pointers to an array.

But when I try:

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

int main(void)
{
int i;

for (i = 0; i < 5; ++i)
{
char *str = "test";
printf("%p:%s\n", str, str);
}

return 0;
}

All the pointers refer to the same address.
When the 'char *str = "test"' is run, no new pointer is created?

A new pointer object is created each time, though on many
implementations that new pointer object is likely to be created in
exactly the same location. The key problem isn't the pointer object,
it's the pointer value that it's initialized with. When you write a
string literal such as "test" in contexts like this one, what happens is
that an unnamed array of 5 characters is created and filled in with 't',
'e', 's', 't', and '\0'. The string literal is treated as a pointer to
that array. Therefore, every time you go through the loop, you
initialize your pointer object with a pointer value that points at the
same unnamed array.

The right way to fix this depends very much on what it is that you're
trying to do. The simplest approach that matches your description would
be as follows:

#include <stdio.h>
int main(void)
{
char str1[] = "test";
char str2[] = "test";
char str3[] = "test";
char str4[] = "test";
char str5[] = "test";
char *array[5] = {str1, str2, str3, str4, str5};
int i;

for(i=0; i<5; ++i)
printf("%p:%s\n", array, array);
// Use array.

return 0;
}

Note that in this case the string literals are used to initialize an
array, not a pointer in an array. In this case, no unnamed array is
created; instead, each definition creates a separate array and
initializes that array

While the above code matches your description, I doubt that it's what
you really want. The following more complicated case is probably closer
to what you're looking for:

#include <stdio.h>
#include <stdlib.h>
#define STRINGS 5

int main(void)
{
char *array[STRINGS];
int i;
for(i=0; i<STRINGS; i++)
{
array = malloc(5);
if(array)
{
strcpy(array, "test");
printf("%p:%s\n", array, array);
}
else
{
printf("%p: failed allocation\n", array);
}
}

for(i=0; i<STRINGS; i++)
free(array);
return 0;
}
 
C

CBFalconer

James said:
.... snip ...

for(i=0; i<5; ++i)
printf("%p:%s\n", array, array);
// Use array.


To avoid awkward line wraps, avoid using the // comments in posted
material. They are also illegal under C90.
 
J

James Kuyper

CBFalconer said:
James Kuyper wrote:
... snip ...
for(i=0; i<5; ++i)
printf("%p:%s\n", array, array);
// Use array.


To avoid awkward line wraps, avoid using the // comments in posted
material.

They are also illegal under C90.

I write for the current standard, not the old one. It's been many years
since I last worked on a system that didn't have a compiler which would
support at least that much of C99.
 
M

Mark Bluemel

James said:
CBFalconer said:
James Kuyper wrote:
... snip ...
for(i=0; i<5; ++i)
printf("%p:%s\n", array, array);
// Use array.


To avoid awkward line wraps, avoid using the // comments in posted
material.

They are also illegal under C90.

I write for the current standard, not the old one. It's been many years
since I last worked on a system that didn't have a compiler which would
support at least that much of C99.


Fair enough, but Chuck's first point still applies. "/* ... */" works
fine when wrapped by a newsreader, while "//" doesn't

It's not a problem in the specific code you posted, but in general I'd
agree with Chuck that "/* ... */" is a better choice for newsgroup postings.
 
W

Willem

Eric wrote:
) <snip>
)> for (i = 0; i < 5; ++i)
)> {
)> char *str = "test";
)> printf("%p:%s\n", str, str);
)> }
)
) Each execution of the loop creates a new `str' variable.
) Each time, that variable is initialized to point to the same
) "test" string. If your telephone number is written on five
) pieces of paper, it doesn't mean you have five different
) telephones.

I bet that even if you wrote printf("%p->%p:%s\n", &str, str, str);
that you can't find a compiler that wouldn't output the same each
iteration, although I'm sure the Standard would allow it.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
Y

ymuntyan

James Kuyper wrote:

... snip ...
for(i=0; i<5; ++i)
printf("%p:%s\n", array, array);
// Use array.


To avoid awkward line wraps, avoid using the // comments in posted
material. They are also illegal under C90.


Nice example of why you got to have very thick skin to read this
group. You don't even need to cast return value of malloc!

Just wonderful. Pure wisdom from Chuck.
 
C

Coos Haak

Op Thu, 08 Nov 2007 09:50:54 -0800 schreef (e-mail address removed):
James Kuyper wrote:

... snip ...
for(i=0; i<5; ++i)
printf("%p:%s\n", array, array);
// Use array.


To avoid awkward line wraps, avoid using the // comments in posted
material. They are also illegal under C90.


Nice example of why you got to have very thick skin to read this
group. You don't even need to cast return value of malloc!

Of course not, C isn't C++
 
C

CBFalconer

James said:
CBFalconer said:
James Kuyper wrote:
... snip ...
for(i=0; i<5; ++i)
printf("%p:%s\n", array, array);
// Use array.


To avoid awkward line wraps, avoid using the // comments in posted
material.

They are also illegal under C90.

I write for the current standard, not the old one. It's been many
years since I last worked on a system that didn't have a compiler
which would support at least that much of C99.


/* .. */ is valid under all systems, and is immune to usenet line
wrap.
 
J

jameskuyper

CBFalconer said:
James Kuyper wrote: ....

/* .. */ is valid under all systems,

I restrict myself to the common subset of C90 and C99 only when
required to compile for C90 (which is true only in my work
environment). Otherwise, I write C99 code which takes full advantage
of every feature of C99 that I consider an improvement over C90.

Don't expect me to follow your coding standards, though I suppose
there's no way I can stop you from complaining when I violate them.
However, I would prefer it if you would refrain from doing so. How
would you feel if I complained every time you posted code that failed
to take advantage of C99 features that I consider to be improvements?
... and is immune to usenet line
wrap.

I try to avoid posting code examples with lines long enough to wrap.
If I've failed to achieve that goal, I consider the line length to be
the problem, not the use of // comments.
 
C

CBFalconer

I restrict myself to the common subset of C90 and C99 only when
required to compile for C90 (which is true only in my work
environment). Otherwise, I write C99 code which takes full advantage
of every feature of C99 that I consider an improvement over C90.

Don't expect me to follow your coding standards, though I suppose
there's no way I can stop you from complaining when I violate them.

It's not really a complaint, just intended to point out how you can
avoid nuisances in Usenet. Another point is that the receiver may
not have a compiler that accepts //. I happen to believe in
maximizing portability, barring nasty penalties.

No more need be said about it. Until I forget :)
 
E

Eric Sosman

Willem said:
Eric wrote:
) <snip>
)> for (i = 0; i < 5; ++i)
)> {
)> char *str = "test";
)> printf("%p:%s\n", str, str);
)> }
)
) Each execution of the loop creates a new `str' variable.
) Each time, that variable is initialized to point to the same
) "test" string. If your telephone number is written on five
) pieces of paper, it doesn't mean you have five different
) telephones.

I bet that even if you wrote printf("%p->%p:%s\n", &str, str, str);
that you can't find a compiler that wouldn't output the same each
iteration, although I'm sure the Standard would allow it.

The fact that two objects share the same memory location
at different times in the program's execution does not make
them the same object.

Example 1:

char *p, *q;
p = malloc(42); /* assume success */
strcpy (p, "Zaphod");
free (p);
q = malloc(21); /* assume success */
strcpy (q, "Beeblebrox");

Even if it turns out that p and q refer (during their respective
periods of validity) to the same address, they do not refer to
the same object.

Example 2:

int f1(void) {
int i = 42;
return i;
}

int f2(void) {
int j = 24;
return j;
}

int driver(void) {
return f1() + f2();
}

Even if it turns out that i and j share the same memory location
they are different objects.

Perhaps my example of the five pieces of paper would have
been better if I'd specified that each was burned before the
next was written.
 
C

Chip Coldwell

Lambda said:
I'd like to create separate character pointers,
pass them to a function to assign each one different value,
and assign the pointers to an array.

But when I try:

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

int main(void)
{
int i;

for (i = 0; i < 5; ++i)
{
char *str = "test";
printf("%p:%s\n", str, str);
}

return 0;
}

All the pointers refer to the same address.
When the 'char *str = "test"' is run, no new pointer is created?

You are printing the value of the pointer, which is the address of the
character literal "test". If the executable were ELF formatted, this
would most likely be an address in the .rodata section.

Chip
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top