Repost: String pointer and char array

Sorry that the question I posted few minutes ago didn't correctly describe the problem. So please ignore it. I repost the question as below:

==============================================

I am developing an application on PPC405 (Walnut). But somehow in the string in the C function doesn't work. The code is as below:

void example() { char *str = "this is a test"; while (*str != 0) { putc(*str++); } return; }

putc() is a function to put a char on the serial console.

This function ends up with a strange string on the serial console ">>..." Same things happens if I use char str[10] = \ {'t','h','i','s',' ','i','s',' ','a',' ','t','e','s','t','\0'}; to assign str.

But if I modify the function to the following one:

void example_modified() { char str[10]; str[0] = 't'; str[1] = 'e'; str[2] = 's'; str[4] = 't'; str[5] = '\0';

int i = 0; for (i = 0; str[i] != 0; i++) { putc(str[i]); } return; }

Then it works. So I am wondering if there is something wrong with the stack setting. Can anybody tell me what makes the above two functions different? Why assigning string str individually works while assigning them together doesn't work? Isn't str[]="test" a shortcut of " str[0] = 't'; str[1] = 'e'; str[2] = 's'; str[4] = 't'; str[5] = '\0';"?

Thanks!

Frank

Reply to
Frank
Loading thread data ...

It looks like your want to create an array and print it out.

So we can have:

#include

int main(void) {

/* declare and assign character array */

char sA[40] = "this is a test";

/* declare character pointer */

char *pA;

/* assign character array (char sA[0]) to pointer */

pA = sA;

/* print pointer array */

puts(pA);

return 0; }

Is the above what you are trying to do? If you want to do loop and print out each character at a time, just use pointer math.

I think you need to study pointers more. Pointers contain memory addresses, not values.

Brian

Frank wrote:

Reply to
tweak

On 10 Jun 2004 17:24:08 -0700, snipped-for-privacy@yahoo.com (Frank) wrote in comp.lang.c:

As somebody already pointed out, putc() is a standard C library function that requires two arguments. If your compiler provides a function by that name that takes only one argument, it is severely broken from a C language point of view. To the point where whatever happens is not a language issue, and is off-topic in comp.lang.c.

Your question may or may not be topical in the embedded Linux group, I don't know. But leave out the cross-posts to comp.lang.c, please, it doesn't belong here.

--
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/~ajo/docs/FAQ-acllc.html
Reply to
Jack Klein

Not if it is a standalone implementation (non-hosted). There are no requirements to provide the capability of the C library. In fact, none of the library functions are required, only macro definitions such as . I see no reason why such an implmentation couldn't reuse the putc identifier to provide some similar facility within the capabilities of the particular embedded system.

It's true, we don't discuss standalone implementations in comp.lang.c; I hear comp.arch.embedded is a good place.

--
Simon.
Reply to
Ralmin

  1. Because the standard library identifier putchar would be better suited for this purpose.
  2. If a freestanding library chooses to use identifiers from the standard C library, it better preserves their semantics. It's not required by the standard but it's an elementary quality of implementation issue; would you use such a library where the semantics of putchar(x) were: read a byte from I/O port x?

Dan

--
Dan Pop
DESY Zeuthen, RZ group
Email: Dan.Pop@ifh.de
Reply to
Dan Pop

It could also be a serial comms handshaking problem. The second string is shorted so doesn't cause the receiver beffer to overflow and drop bits.

Just a thought.

Reply to
nospam

Hello everybody,

I think I didn't make my question clear enough.

This is a standalone application running on the the walnut (ppc405). I didn't include stdio.h or stdlib.h. putc() is a function I create by myself in order to write a char on the serial console through the UART. It handles at the hardware level. It's not the standard putc in C library. Sorry about the misleading. Maybe I should change name to serial_putc(). So let me put the question here again:

void example1() { char *str = "test"; while (*str != 0) { serial_putc(*str++); } return; }

void example2() { char str[10]; str[0] = 't'; str[1] = 'e'; str[2] = 's'; str[4] = 't'; str[5] = '\0';

int i = 0; for (i = 0; str[i] != 0; i++) { serial_putc(str[i]); } return; }

example1() output a messy string but example2() works fine.

Since example2() works, I assume the serial_putc() works just fine.

In order to make sure it is a problem of the variable assigning, I wrote the following simple test function: void example1_test() { char *str = "test"; if (*str == 't') { serial_putc('y'); } else { serial_putc('n'); } return; }

And the output result is 'n'. Which means the str cannot be assigned with a string value as what I expected. I am very confused about the difference between assigning a char array with str[]="test" and assigning every single element of the str separately. Has anybody had same problem before? I would appreciate any of your help.

Thanks!

Frank

Reply to
Frank

[Stuff snipped]

Looks like your startup code is broken. Cant remember offhand what the various sections are called, but the initialisation data ("test") is put into a code segment, which should be copied by the startup code to a data segment. When you have *str="test", the compiler loads str with a pointer to the address in the data segment, not the code segment. Can you check what value are actually being loaded into str, and what is at that address according to the map file ? Are the correct startup code being used for your environment ?

What does the following code produce ?

void example1(void) { int foo1=5;

printf("%d",foo); }

Regards Anton Erasmus

Reply to
Anton Erasmus

Ok, Frank, what is the major difference between the failing and the working code?

Try these changes:

int i;

for(i = 0; str[i]; ++i) { putc(str[i]); } /*

If that works, then something with the precedence in *str++ is wrong, I'd guess.

[....]
Reply to
Robert Stankowic

The quotes leave me highly confused as to what the problem is, but is seems to me that the following should do the job:

fputs(str, stdout); /* if no added final '\n' needed */ or puts(str); /* if need to append final '\n' */

--
Chuck F (cbfalconer@yahoo.com) (cbfalconer@worldnet.att.net)
   Available for consulting/temporary embedded and systems.
     USE worldnet address!
Reply to
CBFalconer

Hi, CB! I am confused as well - the only difference in the OP's working and failing example seems to be that he uses dereferencing and increment in one case and indexing in the other.

My guess (admttedly a wild guess) was, that the compiler parses *str++ as (*str)++, but rethinking that - it's very unlikely, the result then should be "TUVWX...", and compilers don't have such primitive bugs :)

Maybe some UB elsewhere?

Reply to
Robert Stankowic

void example() { char *str = "this is a test"; while (*str != 0) {putc(*str++);} fflush(stdout); /* note fflush(stdout); */ return; }

Reply to
RoSsIaCrIiLoIA

Did you find a solution yet?

I suspect the compiler (is it GCC?) is allocating strings in a different memory region than you expect, or trying to use indirect addressing with a register which has been whacked.

One other possibility is the compiler is optimizing serial_putc(*str++) so much that the serial port cannot keep up.

Things to do other than more code experiments: compile without optimization compile to assembler

All of the following are equivalent allocation methods, but your compiler might allocate differently depending on which pass of the compiler is used for which kind of declaration. All embed these strings in the object code at compile time:

char *charPtr_Quoted = "test"; char charArrayAutoSize_Quoted[] = "test"; char charArrayAutoSize_Quoted[] = {'t','e','s','t','\0'}; // char charArraySize10_Quoted[10] = "test"; // Small string of explicit length. char charArraySize1024_Quoted[1024] = "test"; // Large string might go elsewhere

This is special because it assigns those characters to those spots at Run-Time (also uses a significant amount of space in you object code, a literal char and one or two instructions per line):

Control the experiment by trying swapping printing methods and allocation methods.

If you can print the run-time initialized string that worked with the for loop...

...with the while loop...

char *cursor = (char*) str; > while (*cursor != 0) { > serial_putc(*cursor++); > }

... then it is an allocation / register problem with char *str="test" , and there is no problem with code running too fast for the serial port.

Reply to
Stephen D

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.