char* and char[]

M

mike79

Hello all,

I am a newbie to C, so please bear with me :)

I need to create an array in a function (a local variable) with size
of 1MB. Since local variables get stored on the stack, at run-time, I
get an error.

I tried using mallac() function. This function only works when I am
allocating memory to a char* and not a char[].

I wish to manipulate the string in my function, but I've heard that
when using char*, the value is not meant to be altered. Where as if I
use char[], I can change the value as many times as I like (which I
want to).

Could someone please tell me how to properly allocate memory to a
local variable (string), so I can copy a string to this variable, and
manipulate it any way and how ever many times I wish.

Thanks in advance,
mike79
 
B

Bertrand Mollinier Toublet

Artie said:
Perhaps this will help:

void some_function() {
/* the following is a pointer to a string literal */
char * cannot_be_altered = "this text cannot be altered";

/* the following is an array of `char's that cannot be altered
^^^^^^
ITYM can
(but is of fixed size) */
char can_be_altered[] = "this text can be altered";

/* the following allocated enough space for a 39 character string
and places that address (if successful) in a pointer to char */
char * can_also_be_altered = malloc(40);
if (can_also_be_altered != NULL)
strcpy(can_also_be_altered, "this text can also be altered";

/* the following invokes undefined behavior */
strcpy(cannot_be_altered, "fooled ya!");

/* the following is perfectly OK */
can_be_altered[0] = 'T';

/* the following invokes undefined behavior */
strcpy(can_be_altered, "some string of arbitrary length exceeding "
"what was there before");

/* the following is perfectly OK */
can_also_be_altered[0] = 'T';

/* ... and so on ... */
}
 
A

Artie Gold

Bertrand said:
^^^^^^
ITYM can

Doh!
Of course!

--ag

[Of course this _could_ lead to a long discussion on comments in code.
Hopefully it won't ;-)]
(but is of fixed size) */
char can_be_altered[] = "this text can be altered";

/* the following allocated enough space for a 39 character string
and places that address (if successful) in a pointer to char */
char * can_also_be_altered = malloc(40);
if (can_also_be_altered != NULL)
strcpy(can_also_be_altered, "this text can also be altered";

/* the following invokes undefined behavior */
strcpy(cannot_be_altered, "fooled ya!");

/* the following is perfectly OK */
can_be_altered[0] = 'T';

/* the following invokes undefined behavior */
strcpy(can_be_altered, "some string of arbitrary length exceeding "
"what was there before");

/* the following is perfectly OK */
can_also_be_altered[0] = 'T';

/* ... and so on ... */
}
 
R

Ravi Uday

Artie Gold said:
mike79 said:
Hello all,

I am a newbie to C, so please bear with me :)

I need to create an array in a function (a local variable) with size
of 1MB. Since local variables get stored on the stack, at run-time, I
get an error.

I tried using mallac() function. This function only works when I am
allocating memory to a char* and not a char[].

I wish to manipulate the string in my function, but I've heard that
when using char*, the value is not meant to be altered. Where as if I
use char[], I can change the value as many times as I like (which I
want to).

Ah, I see where you're confused!

Perhaps this will help:

void some_function() {
/* the following is a pointer to a string literal */
char * cannot_be_altered = "this text cannot be altered";

/* the following is an array of `char's that cannot be altered
(but is of fixed size) */
char can_be_altered[] = "this text can be altered";

/* the following allocated enough space for a 39 character string
and places that address (if successful) in a pointer to char */
char * can_also_be_altered = malloc(40);
if (can_also_be_altered != NULL)
strcpy(can_also_be_altered, "this text can also be altered";

/* the following invokes undefined behavior */
strcpy(cannot_be_altered, "fooled ya!");

/* the following is perfectly OK */
can_be_altered[0] = 'T';

/* the following invokes undefined behavior */
strcpy(can_be_altered, "some string of arbitrary length exceeding "
"what was there before");

/* the following is perfectly OK */
can_also_be_altered[0] = 'T';

how about
int main (){
char *p = "hello";
char c[5] = "hello";
c[1] = 'y';/* Not sure on this one !*/
p = c;/* Not sure on this one too !*/
return 0;
}
Isnt it that var 'c' memory is read only !
Also p=c; shouldnt be a problem right ?

- Ravi

}
 
P

pete

mike79 said:
Hello all,

I am a newbie to C, so please bear with me :)

I need to create an array in a function (a local variable) with size
of 1MB. Since local variables get stored on the stack, at run-time, I
get an error.

I tried using mallac() function. This function only works when I am
allocating memory to a char* and not a char[].

I wish to manipulate the string in my function, but I've heard that
when using char*, the value is not meant to be altered.

That's for the case when the pointer is pointing to
an array specified by a string literal:
char *pointer = "string literal";

If you have
pointer = malloc("string literal");
then, if (pointer != 0), then you can read and write to,
pointer[0] through pointer[sizeof"string literal" - 1]
 
P

pete

Ravi said:
Artie Gold said:
mike79 said:
Hello all,

I am a newbie to C, so please bear with me :)

I need to create an array in a function (a local variable) with size
of 1MB. Since local variables get stored on the stack, at run-time, I
get an error.

I tried using mallac() function. This function only works when I am
allocating memory to a char* and not a char[].

I wish to manipulate the string in my function, but I've heard that
when using char*, the value is not meant to be altered. Where as if I
use char[], I can change the value as many times as I like (which I
want to).

Ah, I see where you're confused!

Perhaps this will help:

void some_function() {
/* the following is a pointer to a string literal */
char * cannot_be_altered = "this text cannot be altered";

/* the following is an array of `char's that cannot be altered
(but is of fixed size) */
char can_be_altered[] = "this text can be altered";

/* the following allocated enough space for a 39 character string
and places that address (if successful) in a pointer to char */
char * can_also_be_altered = malloc(40);
if (can_also_be_altered != NULL)
strcpy(can_also_be_altered, "this text can also be altered";

/* the following invokes undefined behavior */
strcpy(cannot_be_altered, "fooled ya!");

/* the following is perfectly OK */
can_be_altered[0] = 'T';

/* the following invokes undefined behavior */
strcpy(can_be_altered, "some string of arbitrary length exceeding "
"what was there before");

/* the following is perfectly OK */
can_also_be_altered[0] = 'T';

how about
int main (){
char *p = "hello";
char c[5] = "hello";
c[1] = 'y';/* Not sure on this one !*/
p = c;/* Not sure on this one too !*/
return 0;
}
Isnt it that var 'c' memory is read only !

No.
"hello" is an initialiser list for c.
"hello" is an array for p.
Also p=c; shouldnt be a problem right ?

/* right.c */

#include <stdio.h>

int main (void)
{
char *p = "hello";
char c[] = "hello\0";

p = c;
p[0] = 'y';
p[5] = 'w';
p = "hello";
puts(p);
puts(c);
return 0;
}
 
A

Alex Vinokur

Artie Gold said:
mike79 said:
Hello all,

I am a newbie to C, so please bear with me :)

I need to create an array in a function (a local variable) with size
of 1MB. Since local variables get stored on the stack, at run-time, I
get an error.

I tried using mallac() function. This function only works when I am
allocating memory to a char* and not a char[].

I wish to manipulate the string in my function, but I've heard that
when using char*, the value is not meant to be altered. Where as if I
use char[], I can change the value as many times as I like (which I
want to).

Ah, I see where you're confused!

Perhaps this will help:

[snip]

Also pay attention to sizeof() values :

------ C code ------
#include <stdio.h>

#define SHOW_SIZEOF(x) printf ("sizeof(%s) = %u\n", #x, sizeof (x))

int main()
{
char* cannot_be_altered = "this text cannot be altered";
SHOW_SIZEOF(cannot_be_altered);

char can_be_altered[] = "this text can be altered";
SHOW_SIZEOF(can_be_altered);

char* can_also_be_altered = (char*)malloc(40);
if (can_also_be_altered != NULL)
{
strcpy(can_also_be_altered, "this text can also be altered");
}
SHOW_SIZEOF(can_also_be_altered);

return 0;
}

--------------------

------ Run results ------

sizeof(cannot_be_altered) = 4
sizeof(can_be_altered) = 25
sizeof(can_also_be_altered) = 4

-------------------------

=====================================
Alex Vinokur
mailto:[email protected]
http://mathforum.org/library/view/10978.html
=====================================
 
B

bd

pete said:
mike79 said:
Hello all,

I am a newbie to C, so please bear with me :)

I need to create an array in a function (a local variable) with size
of 1MB. Since local variables get stored on the stack, at run-time, I
get an error.

I tried using mallac() function. This function only works when I am
allocating memory to a char* and not a char[].

I wish to manipulate the string in my function, but I've heard that
when using char*, the value is not meant to be altered.

That's for the case when the pointer is pointing to
an array specified by a string literal:
char *pointer = "string literal";

If you have
pointer = malloc("string literal");

"string literal" is not an integer value. Do you mean malloc(strlen("string
literal") + 1)?
 
B

bd

Ravi said:
Artie Gold said:
mike79 said:
Hello all,

I am a newbie to C, so please bear with me :)

I need to create an array in a function (a local variable) with size
of 1MB. Since local variables get stored on the stack, at run-time, I
get an error.

I tried using mallac() function. This function only works when I am
allocating memory to a char* and not a char[].

I wish to manipulate the string in my function, but I've heard that
when using char*, the value is not meant to be altered. Where as if I
use char[], I can change the value as many times as I like (which I
want to).

Ah, I see where you're confused!

Perhaps this will help:

void some_function() {
/* the following is a pointer to a string literal */
char * cannot_be_altered = "this text cannot be altered";

/* the following is an array of `char's that cannot be altered
(but is of fixed size) */
char can_be_altered[] = "this text can be altered";

/* the following allocated enough space for a 39 character string
and places that address (if successful) in a pointer to char */
char * can_also_be_altered = malloc(40);
if (can_also_be_altered != NULL)
strcpy(can_also_be_altered, "this text can also be altered";

/* the following invokes undefined behavior */
strcpy(cannot_be_altered, "fooled ya!");

/* the following is perfectly OK */
can_be_altered[0] = 'T';

/* the following invokes undefined behavior */
strcpy(can_be_altered, "some string of arbitrary length exceeding "
"what was there before");

/* the following is perfectly OK */
can_also_be_altered[0] = 'T';

how about
int main (){
char *p = "hello";
char c[5] = "hello";

Not sure - should this be [6], or will it be truncated?
c[1] = 'y';/* Not sure on this one !*/
Ok.

p = c;/* Not sure on this one too !*/

Also ok.
return 0;
}
Isnt it that var 'c' memory is read only !

No. The meaning of a string literal changes in an array initializer:
char *p = "hello"; /* p points to read-only memory of static duration */
/* The data pointer to by p remains valid once you return */
char c[6] = "hello";
/* c is a writable array of 6 chars with automatic storage duration. */
/* c (and any pointers to any elements of c) is invalid once you return from
the function */
Also p=c; shouldnt be a problem right ?

Nope. p itself is writable, but the data pointed to is not. Since you're
only changing p, it's ok.
 
R

Ravi Uday

[snip]
how about
int main (){
char *p = "hello";
char c[] = "hello";
c[1] = 'y';/* Not sure on this one !*/
p = c;/* Not sure on this one too !*/
return 0;
}
Isnt it that var 'c' memory is read only !

No.
"hello" is an initialiser list for c.
"hello" is an array for p.
Also p=c; shouldnt be a problem right ?

/* right.c */

#include <stdio.h>

int main (void)
{
char *p = "hello";
char c[] = "hello\0";
But if i do
puts (c);
strcpy(c,"HELLO");
puts(c);
Nothing seems to happen !
So what is the point if we initialize 'c' with some useful data and
not able to access it !
p = c;
p[0] = 'y';
p[5] = 'w';
p = "hello";
puts(p);
puts(c);
return 0;
}
 
J

John Bode

Hello all,

I am a newbie to C, so please bear with me :)

I need to create an array in a function (a local variable) with size
of 1MB. Since local variables get stored on the stack, at run-time, I
get an error.

I tried using mallac() function. This function only works when I am
allocating memory to a char* and not a char[].

I wish to manipulate the string in my function, but I've heard that
when using char*, the value is not meant to be altered. Where as if I
use char[], I can change the value as many times as I like (which I
want to).

Could someone please tell me how to properly allocate memory to a
local variable (string), so I can copy a string to this variable, and
manipulate it any way and how ever many times I wish.

Thanks in advance,
mike79

Use the following code as an example:

#include <stdlib.h>
#include <string.h>

int main (void)
{
char *a = "Hello";
char b[] = "Hello";
char c[8] = "Hello";
char d[8];
char *e;

strcpy (d, "Goodbye");
e = malloc (1024);
if (e)
{
strcpy (e, a);
strcat (e, d)
}

a = d;
}

Here's a hypothetical memory map to illustrate the concepts below. It
assumes that all instances of the string literal "Hello" map to the
same address; that may not be universally true, but we'll assume it
for this model. This is not meant to correspond to any real memory
model, just to demonstrate what's going on in the code:

Item Address 00 01 02 03 04 05 06 07
---- -------
"Hello" 0x00000100 'H' 'e' 'l' 'l' 'o' 0 .. ..
...
a 0x00400000 00 00 01 00 .. .. .. ..
b 0x00400008 'H' 'e' 'l' 'l' 'o' 0 .. ..
c 0x00400010 'H' 'e' 'l' 'l' 'o' 0 .. ..
d 0x00400018 .. .. .. .. .. .. .. ..
e 0x00400020 .. .. .. .. .. .. .. ..

This is what memory looks like right before the first strcpy().

The string literal "Hello" is stored as an array of 6 characters with
contents {'H', 'e', 'l', 'l', 'o', 0} with static extent, meaning the
memory for it is allocated at program startup, and is not released
until the program terminates. This memory may or may not be writable;
assume that it is not writeable.

The variable a is a pointer to char with auto extent, and it is
initialized with the address of the string literal "Hello" (a ==
0x00000100). Assume for this example that the address of a is
0x00400000. The *variable* a is writeable; you can always assign
another pointer value to it, such as a = d (a will contain the base
address of the d array, or 0x00400018), or a = "Goodbye". However,
what a initially *points to* (address 0x00000100) may not be writable,
so operations like strcpy (a, "Goodbye"); and a[0] = 'J'; may result
in undefined behavior.

The variable b is an array of char with auto extent, implicitly sized
to hold the string literal that is being used to initialize it (sizeof
b == 6), and initialized with the *contents* of the string literal.
The contents of b are writeable, so operations like strcpy (b, "Joe")
and b[0] = 'J'; will succeed. The *variable* b is not writeable; you
may not assign another address to it, so operations like b = a or b =
c are disallowed.

The variable c is an array of char with auto extent, explicitly sized
to hold 8 characters, and initialized with the contents of the string
literal. Behavior is the same as b.

The variable d is an array of char with auto extent, explicitly sized
to hold 8 characters. It has not been initialized, and must be
assumed to contain garbage. Behavior is the same as b and c. After
the call to strcpy, the contents of d are {'H', 'e', 'l', 'l', 'o', 0,
..., .., .., ..}, where '..' represent a random byte value.

The variable e is a pointer to char with auto extent. It has not been
initialized, and since it is auto, it may or may not be initialized to
NULL (assume it initially contains garbage). If the call to malloc()
succeeds, e will contain the address of a chunk of dynamically
allocated memory 1024 bytes long (assume address 0x08000000). This
memory will be writable, so operations like strcpy (e, "Hello"); and
e[0] = 'J'; will succeed. Like a, the *variable* e is writable, so
operations like e = b are permitted.

b, c, d, and e may be copied to as much as you want, as long as you
don't attempt to copy anything larger than what they're sized to hold.
Executing strcpy (b, "Goodbye"); may cause undefined behavior, since
the string being copied is longer than what b is sized to hold.

Here's what the memory looks when the program is about to exit:

Item Address 00 01 02 03 04 05 06 07
---- -------
"Hello" 0x00000100 'H' 'e' 'l' 'l' 'o' 0 .. ..
...
a 0x00400000 00 40 00 18 .. .. .. ..
b 0x00400008 'H' 'e' 'l' 'l' 'o' 0 .. ..
c 0x00400010 'H' 'e' 'l' 'l' 'o' 0 .. ..
d 0x00400018 'G' 'o' 'o' 'd' 'b' 'y' 'e' 0
e 0x00400020 08 00 00 00 .. .. .. ..
...
0x08000000 'H' 'e' 'l' 'l' 'o' 'G' 'o' 'o'
0x08000008 'd' 'b' 'y' 'e' 0 .. .. ..
...
0x08000400

Hope that helps.
 

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
474,077
Messages
2,570,567
Members
47,204
Latest member
abhinav72673

Latest Threads

Top