Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Please explain this issue with array of char pointers.

Reply
Thread Tools

Please explain this issue with array of char pointers.

 
 
JNLSeb
Guest
Posts: n/a
 
      01-23-2008
Here are 2 samples and after the samples are some questions.

--------------------------------
Sample 1 - Initializes the array
--------------------------------

#include "stdio.h"
#include "string.h"
#include "windows.h"
int main(int argc, char **argv) {
char *asArgs[28] = {"ABB", "aaaa"};
int v_i = 0;
for(v_i=0; v_i < 27; ++v_i){
asArgs[v_i] = malloc(100);
memset(asArgs[v_i], '\0', 100);
}
strcpy(asArgs[25], "P");
asArgs[25] = "P";
asArgs[25] ="";
asArgs[25] ="A";
strcpy(asArgs[25], "P"); //*******Will cause Fault on this 2nd call
to the string copy command.
return 0;
}


--------------------------------
Sample 2 - Does NOT initialize the array
--------------------------------

#include "stdio.h"
#include "string.h"
#include "windows.h"
int main(int argc, char **argv) {
char *asArgs[28] = {"ABB", "aaaa"};
int v_i = 0;

strcpy(asArgs[25], "P"); //******Will cause Fault on this 1st call
to the string copy command.
//*******The following commands all work.
asArgs[25] = "P";
asArgs[25] ="";
asArgs[25] ="A";
return 0;
}

Questions:
------------
1 - With Sample1, why does the first strcpy work, but the 2nd one cause the
fault?
2 - With Sample2, why does the strcpy fail?
3 - With Sample2, why can the asArgs elements be assigned values directly
when the array elements are not allocated?
4 - Is there a "proper" way to assign values to the elements of a char
array?

TIA!!!


 
Reply With Quote
 
 
 
 
vippstar@gmail.com
Guest
Posts: n/a
 
      01-23-2008
On Jan 23, 2:20 am, "JNLSeb" <(E-Mail Removed)> wrote:
> Here are 2 samples and after the samples are some questions.
>
> --------------------------------
> Sample 1 - Initializes the array
> --------------------------------
>
> #include "stdio.h"
> #include "string.h"
> #include "windows.h"
> int main(int argc, char **argv) {
> char *asArgs[28] = {"ABB", "aaaa"};
> int v_i = 0;
> for(v_i=0; v_i < 27; ++v_i){
> asArgs[v_i] = malloc(100);
> memset(asArgs[v_i], '\0', 100);
> }
> strcpy(asArgs[25], "P");
> asArgs[25] = "P";
> asArgs[25] ="";
> asArgs[25] ="A"; /* here's your mistake, point to string literal */
> strcpy(asArgs[25], "P");

An awful lot of mistakes in your code, segfault is because you write
to a string literal which is pointed to by asArgs[25].
string literals are const. you cannot write over them, except if you
enable some compiler extension. (nothing to do with ISO C after that)
>
> --------------------------------
> Sample 2 - Does NOT initialize the array
> --------------------------------
>
> #include "stdio.h"
> #include "string.h"
> #include "windows.h"
> int main(int argc, char **argv) {
> char *asArgs[28] = {"ABB", "aaaa"};
> int v_i = 0;
>
> strcpy(asArgs[25], "P"); //******Will cause Fault on this 1st call
> to the string copy command.

Because you write to NULL.
When you initialize the array of pointers asArgs you initialize only
the first two elements, and the rest are 0'ed or NULL'ed.
asArgs[25] evaluates to NULL.
> //*******The following commands all work.
> asArgs[25] = "P";
> asArgs[25] ="";
> asArgs[25] ="A";

These are not commands.

 
Reply With Quote
 
 
 
 
user923005
Guest
Posts: n/a
 
      01-23-2008
On Jan 22, 4:20*pm, "JNLSeb" <(E-Mail Removed)> wrote:
> Here are 2 samples and after the samples are some questions.
>
> --------------------------------
> Sample 1 - Initializes the array
> --------------------------------
>
> #include "stdio.h"
> #include "string.h"
> #include "windows.h"
> int main(int argc, char **argv) {
> * * char *asArgs[28] = *{"ABB", "aaaa"};
> * * int v_i = 0;
> * * for(v_i=0; v_i < 27; ++v_i){
> * * * *asArgs[v_i] = malloc(100);
> * * * *memset(asArgs[v_i], '\0', 100);
> * * }
> * * * * strcpy(asArgs[25], "P");
> * * * * asArgs[25] = "P";
> * * * * asArgs[25] ="";
> * * * * asArgs[25] ="A";
> * * * * strcpy(asArgs[25], "P"); *//*******Will cause Fault on this 2nd call
> to the string copy command.
> return 0;
>
> }
>
> --------------------------------
> Sample 2 - Does NOT initialize the array
> --------------------------------
>
> #include "stdio.h"
> #include "string.h"
> #include "windows.h"
> int main(int argc, char **argv) {
> * * char *asArgs[28] = *{"ABB", "aaaa"};
> * * int v_i = 0;
>
> * * * * strcpy(asArgs[25], "P"); //******Will cause Fault on this 1st call
> to the string copy command.
> * * * *//*******The following commands all work.
> * * * * asArgs[25] = "P";
> * * * * asArgs[25] ="";
> * * * * asArgs[25] ="A";
> return 0;
>
> }


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

int main0 (int argc, char **argv)
{
char *asArgs[28] =
{"ABB", "aaaa"};
int v_i = 0;
for (v_i = 0; v_i < 27; ++v_i)
{
asArgs[v_i] = malloc (100);
memset (asArgs[v_i], '\0', 100);
}
strcpy (asArgs[25], "P");
asArgs[25] = "P";
asArgs[25] = "";
asArgs[25] = "A";
strcpy (asArgs[25], "P"); /* Fault on 2nd call to strcpy function.
*/
return 0;

}

int main1 (int argc, char **argv)
{
char *asArgs[28] =
{"ABB", "aaaa"};
int v_i = 0;


strcpy (asArgs[25], "P"); /* Fault on 1st call to strcpy function */
asArgs[25] = "P";
asArgs[25] = "";
asArgs[25] = "A";
return 0;

}

int main (int argc, char **argv)
{
main0 (argc, argv);
main1 (argc, argv);
return 0;
}

/*
C:\tmp>splint foo.c
Splint 3.1.1 --- 12 Mar 2007

foo.c: (in function main0)
foo.c(8,3): Initializer block for asArgs has 2 elements, but declared
as char *
[28]: "ABB", "aaaa"
Initializer does not define all elements of a declared array. (Use
-initallelements to inhibit warning)
foo.c(13,2: Function memset expects arg 2 to be int gets char: '\0'
A character constant is used as an int. Use +charintliteral to allow
character constants to be used as ints. (This is safe since the
actual type
of a char constant is int.)
foo.c(13,15): Possibly null storage asArgs[] passed as non-null param:
memset (asArgs[v_i], ...)
A possibly null pointer is passed as a parameter corresponding to a
formal
parameter with no /*@null@*/ annotation. If NULL may be used for
this
parameter, add a /*@null@*/ annotation to the function parameter
declaration.
(Use -nullpass to inhibit warning)
foo.c(12,21): Storage asArgs[] may become null
foo.c(16,3): Observer storage assigned to unqualified reference:
asArgs[25] = "P"
Observer storage is transferred to a non-observer reference. (Use
-observertrans to inhibit warning)
foo.c(16,16): Storage becomes observer
foo.c(17,3): Observer storage assigned to unqualified reference:
asArgs[25] = ""
foo.c(17,16): Storage becomes observer
foo.c(18,3): Observer storage assigned to unqualified reference:
asArgs[25] = "A"
foo.c(18,16): Storage becomes observer
foo.c(5,16): Parameter argc not used
A function parameter is not used in the body of the function. If the
argument
is needed for type compatibility or future plans, use /*@unused@*/
in the
argument declaration. (Use -paramuse to inhibit warning)
foo.c(5,29): Parameter argv not used
foo.c: (in function main1)
foo.c(27,3): Initializer block for asArgs has 2 elements, but declared
as char
* [28]: "ABB", "aaaa"
foo.c(32,3): Observer storage assigned to unqualified reference:
asArgs[25] = "P"
foo.c(32,16): Storage becomes observer
foo.c(33,3): Observer storage assigned to unqualified reference:
asArgs[25] = ""
foo.c(33,16): Storage becomes observer
foo.c(34,3): Observer storage assigned to unqualified reference:
asArgs[25] = "A"
foo.c(34,16): Storage becomes observer
foo.c(28,7): Variable v_i declared but not used
A variable is declared but never used. Use /*@unused@*/ in front of
declaration to suppress message. (Use -varuse to inhibit warning)
foo.c(24,16): Parameter argc not used
foo.c(24,29): Parameter argv not used
foo.c: (in function main)
foo.c(41,3): Return value (type int) ignored: main0(argc, argv)
Result returned by function call is not used. If this is intended,
can cast
result to (void) to eliminate message. (Use -retvalint to inhibit
warning)
foo.c(42,3): Return value (type int) ignored: main1(argc, argv)
foo.c(5,5): Function exported but not used outside foo: main0
A declaration is exported, but not used outside this module.
Declaration can
use static qualifier. (Use -exportlocal to inhibit warning)
foo.c(22,1): Definition of main0
foo.c(24,5): Function exported but not used outside foo: main1
foo.c(37,1): Definition of main1

Finished checking --- 19 code warnings
*/

> Questions:
> ------------
> 1 - With Sample1, why does the first strcpy work, but the 2nd one cause the
> fault?


What do you think?

> 2 - With Sample2, why does the strcpy fail?


What do you think and why?

> 3 - With Sample2, why can the asArgs elements be assigned values directly
> when the array elements are not allocated?


Tell me what you think about it?

> 4 - Is there a "proper" way to assign values to the elements of a char
> array?


Yes.

> TIA!!!


WIA!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
Reply With Quote
 
Pedro Graca
Guest
Posts: n/a
 
      01-23-2008
JNLSeb wrote:
> Here are 2 samples and after the samples are some questions.
>
> --------------------------------
> Sample 1 - Initializes the array
> --------------------------------
>
> #include "stdio.h"

#include <stdio.h>

> #include "string.h"

#include <string.h>

> #include "windows.h"

Ok, I guess

> int main(int argc, char **argv) {
> char *asArgs[28] = {"ABB", "aaaa"};

Declare and initialize an array of 28 char *.
The first element of the array points to the string "ABB",
the 2nd element points to the string "aaaa".
(Note this strings can be anywhere inside your computer --
particularly they do not *need* to be in memory you can write to)
The other 26 elements are initialized to NULL.

> int v_i = 0;
> for(v_i=0; v_i < 27; ++v_i){
> asArgs[v_i] = malloc(100);

You just "lost" the addresses of the strings "ABB" and "aaaa"!

> memset(asArgs[v_i], '\0', 100);
> }

Almost all array elements now point to some chunk of memory that
belongs to them. You can read from and write to that memory. Array
element asArgs[27] is still NULL.
> strcpy(asArgs[25], "P");

Ok. Copy 2 bytes ('P' and the string terminator) to asArgs[25].

> asArgs[25] = "P";

You've just lost the memory chunk assigned to asArgs[25].
You also made the pointer point to the string "P" somewhere inside
your computer.
This somewhere isn't necessarily a place you can write to!

> asArgs[25] ="";

Same as above (except for losing the memory chunk).

> asArgs[25] ="A";

Same as above.

> strcpy(asArgs[25], "P"); //*******Will cause Fault on this 2nd call
> to the string copy command.

Now you try to write 2 bytes ('P' and the string terminator) to the
address of that last "A".
You do not own that address. For instance, it can be in ROM.
(Oh! and // comments tend to break the code when posted to Usenet)

> return 0;
> }
>
>
> --------------------------------
> Sample 2 - Does NOT initialize the array

Oh, yes it does!

> --------------------------------
>
> #include "stdio.h"
> #include "string.h"
> #include "windows.h"
> int main(int argc, char **argv) {
> char *asArgs[28] = {"ABB", "aaaa"};

Initialize the array with 26 NULL pointers!

> int v_i = 0;
>
> strcpy(asArgs[25], "P"); //******Will cause Fault on this 1st call
> to the string copy command.

Trying to write to a NULL pointer, usually causes Faults!

> //*******The following commands all work.
> asArgs[25] = "P";
> asArgs[25] ="";
> asArgs[25] ="A";
> return 0;
> }
>
> Questions:
> ------------
> 1 - With Sample1, why does the first strcpy work, but the 2nd one cause the
> fault?

Because the address pointed to on the first strcpy() is part of memory
you "own"; on the second copy it isn't.

> 2 - With Sample2, why does the strcpy fail?

Because you're trying to write to a NULL pointer.

> 3 - With Sample2, why can the asArgs elements be assigned values directly
> when the array elements are not allocated?

each of the asArgs elements is a pointer
asArgs[23] is a char *
You cannot put a letter into a char *, but you can put the address of
a string containing a letter there.

char *pointer;
pointer = "P"; /* ok, but pointer points to memory you do not "own" */
pointer = 'P'; /* invalid -- cannot assign a character to a pointer */

> 4 - Is there a "proper" way to assign values to the elements of a char
> array?

Yes
But you do not have a char array in the example you posted -- you have
an array of char *
 
Reply With Quote
 
user923005
Guest
Posts: n/a
 
      01-23-2008
On Jan 22, 5:02*pm, Pedro Graca <(E-Mail Removed)> wrote:
> JNLSeb wrote:
> > Here are 2 samples and after the samples are some questions.

>
> > --------------------------------
> > Sample 1 - Initializes the array
> > --------------------------------

>
> > #include "stdio.h"

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

>
> #include <string.h>
>
> > #include "windows.h"

>
> Ok, I guess
>
> > int main(int argc, char **argv) {
> > * * char *asArgs[28] = *{"ABB", "aaaa"};

>
> Declare and initialize an array of 28 char *.
> The first element of the array points to the string "ABB",
> the 2nd element points to the string "aaaa".
> (Note this strings can be anywhere inside your computer --
> particularly they do not *need* to be in memory you can write to)
> The other 26 elements are initialized to NULL.
>
> > * * int v_i = 0;
> > * * for(v_i=0; v_i < 27; ++v_i){
> > * * * *asArgs[v_i] = malloc(100);

>
> You just "lost" the addresses of the strings "ABB" and "aaaa"!
>
> > * * * *memset(asArgs[v_i], '\0', 100);
> > * * }

>
> Almost all array elements now point to some chunk of memory that
> belongs to them. You can read from and write to that memory. Array
> element asArgs[27] is still NULL.> * * * * strcpy(asArgs[25], "P");
>
> Ok. Copy 2 bytes ('P' and the string terminator) to asArgs[25].
>
> > * * * * asArgs[25] = "P";

>
> You've just lost the memory chunk assigned to asArgs[25].
> You also made the pointer point to the string "P" somewhere inside
> your computer.
> This somewhere isn't necessarily a place you can write to!
>
> > * * * * asArgs[25] ="";

>
> Same as above (except for losing the memory chunk).
>
> > * * * * asArgs[25] ="A";

>
> Same as above.
>
> > * * * * strcpy(asArgs[25], "P"); *//*******Will cause Fault on this 2nd call
> > to the string copy command.

>
> Now you try to write 2 bytes ('P' and the string terminator) to the
> address of that last "A".
> You do not own that address. For instance, it can be in ROM.
> (Oh! and // comments tend to break the code when posted to Usenet)
>
> > return 0;
> > }

>
> > --------------------------------
> > Sample 2 - Does NOT initialize the array

>
> Oh, yes it does!
>
> > --------------------------------

>
> > #include "stdio.h"
> > #include "string.h"
> > #include "windows.h"
> > int main(int argc, char **argv) {
> > * * char *asArgs[28] = *{"ABB", "aaaa"};

>
> Initialize the array with 26 NULL pointers!
>
> > * * int v_i = 0;

>
> > * * * * strcpy(asArgs[25], "P"); //******Will cause Fault on this 1st call
> > to the string copy command.

>
> Trying to write to a NULL pointer, usually causes Faults!
>
> > * * * *//*******The following commands all work.
> > * * * * asArgs[25] = "P";
> > * * * * asArgs[25] ="";
> > * * * * asArgs[25] ="A";
> > return 0;
> > }

>
> > Questions:
> > ------------
> > 1 - With Sample1, why does the first strcpy work, but the 2nd one cause the
> > fault?

>
> Because the address pointed to on the first strcpy() is part of memory
> you "own"; on the second copy it isn't.
>
> > 2 - With Sample2, why does the strcpy fail?

>
> Because you're trying to write to a NULL pointer.
>
> > 3 - With Sample2, why can the asArgs elements be assigned values directly
> > when the array elements are not allocated?

>
> each of the asArgs elements is a pointer
> asArgs[23] is a char *
> You cannot put a letter into a char *, but you can put the address of
> a string containing a letter there.
>
> char *pointer;
> pointer = "P"; /* ok, but pointer points to memory you do not "own" */
> pointer = 'P'; /* invalid -- cannot assign a character to a pointer */
>
> > 4 - Is there a "proper" way to assign values to the elements of a char
> > array?

>
> Yes
> But you do not have a char array in the example you posted -- you have
> an array of char *


Are you really incapable of recognizing a homework problem?

You have done him a terrible disservice by feeding him the answers on
a plate instead of letting _him_ figure out *why* the problems were
symptoms of various mistakes.
 
Reply With Quote
 
Jack Klein
Guest
Posts: n/a
 
      01-23-2008
On Tue, 22 Jan 2008 16:36:39 -0800 (PST), http://www.velocityreviews.com/forums/(E-Mail Removed) wrote in
comp.lang.c:

> On Jan 23, 2:20 am, "JNLSeb" <(E-Mail Removed)> wrote:
> > Here are 2 samples and after the samples are some questions.
> >
> > --------------------------------
> > Sample 1 - Initializes the array
> > --------------------------------
> >
> > #include "stdio.h"
> > #include "string.h"
> > #include "windows.h"
> > int main(int argc, char **argv) {
> > char *asArgs[28] = {"ABB", "aaaa"};
> > int v_i = 0;
> > for(v_i=0; v_i < 27; ++v_i){
> > asArgs[v_i] = malloc(100);
> > memset(asArgs[v_i], '\0', 100);
> > }
> > strcpy(asArgs[25], "P");
> > asArgs[25] = "P";
> > asArgs[25] ="";
> > asArgs[25] ="A"; /* here's your mistake, point to string literal */
> > strcpy(asArgs[25], "P");

> An awful lot of mistakes in your code, segfault is because you write
> to a string literal which is pointed to by asArgs[25].
> string literals are const. you cannot write over them, except if you
> enable some compiler extension. (nothing to do with ISO C after that)


String literals in C have the type "array of char", and they do most
specifically do not have the type "array of const char".

Attempting to modify a string literal in C is undefined behavior
because the C standard specifically states that it is, not because
they have the type qualifier "const".

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 
Reply With Quote
 
Pedro Graca
Guest
Posts: n/a
 
      01-23-2008
user923005 wrote:
> Are you really incapable of recognizing a homework problem?

I must have been more tired than I thought.

> You have done him a terrible disservice by feeding him the answers on
> a plate instead of letting _him_ figure out *why* the problems were
> symptoms of various mistakes.

I'd like to offer my apologies to JNLSeb and extend them to the C
community.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
length of 2D Array >> char **myString= (char **) malloc (sizeof (char *)); davidb C++ 6 09-01-2006 05:57 PM
length of 2D Array >> char **myString= (char **) malloc (sizeof (char *)); davidb C++ 0 09-01-2006 03:22 PM
(const char *cp) and (char *p) are consistent type, (const char **cpp) and (char **pp) are not consistent lovecreatesbeauty C Programming 1 05-09-2006 08:01 AM
Problem- strcat with char and char indexed from char array aldonnelley@gmail.com C++ 3 04-20-2006 07:32 AM
/usr/bin/ld: ../../dist/lib/libjsdombase_s.a(BlockGrouper.o)(.text+0x98): unresolvable relocation against symbol `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostre silverburgh.meryl@gmail.com C++ 3 03-09-2006 12:14 AM



Advertisments