The Shed is going Social! Join us on FaceBook and Twitter and chime in on the conversation.
|
 |
|
Dev Shed Forums
> Programming Languages
> C Programming
|
Char wars
Discuss Char wars in the C Programming forum on Dev Shed. Char wars C programming forum discussing all C derivatives, including C#, C++, Object-C, and even plain old vanilla C. These languages are low level languages, and used on projects such as device drivers, compilers, and even whole computer operating systems.
|
|
 |
|
|
|
|

Dev Shed Forums Sponsor:
|
|
|

April 21st, 2012, 01:23 PM
|
|
Contributing User
|
|
Join Date: Apr 2012
Posts: 58
Time spent in forums: 1 Day 17 h 52 m 2 sec
Reputation Power: 2
|
|
|
Char wars
Well, make that "pointer to char" wars. ....hahaha....
I am an experienced C programmer. I am a not-so-experienced C++ programmer.
I got stuck with this C test program.
using Debian Lenny in KDE's Konsole
gcc (Debian 4.3.2-1.1) 4.3.2
g++ (Debian 4.3.2-1.1) 4.3.2
My objective in writing this test program was to use printf() to print an arbitrary substring of a char array while avoiding the overhead of a function call like strcpy().
So I figured I'd just insert a NULL right after where I wanted the substring to end, and pass printf() a char pointer set to where I wanted the substring to begin.
gcc compiles my pwp.c program with just one warning:
Code:
pwp.c: In function 'main':
pwp.c:43: warning: assignment from incompatible pointer type
I do not understand this error message.
Nonetheless, gcc makes an executable that runs perfectly. Outputs the following:
Code:
A string declared as an array.
A string declared as a pointer.
A string constant copied in.
A string initialized at compile time.
...now for the char pointer stuff...
A str
A str
constant copied in.
constant cop
However, when I copy this file pwp.c to pwp.cpp and try to compile with g++,
the compiler bombs with these errors:
Code:
$g++ -Wall pwp.cpp -o pwp+.o
pwp.cpp: In function 'int main()':
pwp.cpp:20: warning: deprecated conversion from string constant to 'char*'
pwp.cpp:43: error: cannot convert 'char (*)[30]' to 'char*' in assignment
My source file pwp.c:
Code:
$nl pwp.c
1 /* playing_with_pointers.c - copied from strings.c
2 Demonstrates printf, with no format specifier, prints strings initialized in
3 any of four ways.
4 Shows printf will recognize NULL as string terminator.
5 Shows printf will work with a string location other than zero.
6 Shows printf will work with both cases simultaneously.
7 */
8 #include <stdio.h>
9 #include <string.h>
10 int main()
11 {
12 /* Example 1 */
13 char string1[] = "A string declared as an array.\n";
14 /* Example 2 */
15 char *string2 = "A string declared as a pointer.\n";
16 /* Example 3 */
17 char string3[30];
18 char *cptr;
19 /* Example 4 */
20 char string4[40]="A string initialized at compile time.";
21
22 strcpy(string3, "A string constant copied in.\n");
23 printf (string1);
24 printf (string2);
25 printf (string3);
26 printf (string4);
27 printf("\n");
28 // Now start playing with char pointer.
29 printf("\n...now for the char pointer stuff...\n");
30 cptr=&string3[5];
31 *cptr='\0'; //Place NULL where first lowercase i used to be.
32 cptr=&string3;
33 printf(string3);
34 cptr=string3; //Pass char pointer to printf()
35 printf("\n%s", cptr );
36 //Replace i and try printing from some other location in string.
37 cptr=&string3[5]; *cptr='i'; cptr=&string3[9];
38 printf("\n%s", cptr );
39 //Now both cases together
40 cptr=&string3[21]; *cptr='\0'; //Place NULL where second lowercase i used to be.
41 cptr=&string3[9]; //printf() shoudl now display constant cop
42 printf("\n%s\n", cptr);
43 return 0;
44 }
I am befuddled. I hope somebody more experienced than me with C++ can explain what is wrong with my code, or what I forgot. Again, it runs fine when compiled under gcc despite the warning.
|

April 21st, 2012, 09:48 PM
|
 |
Contributing User
|
|
|
|
|
Line 32 is incorrect.
cptr=&string3;
cptr is a pointer to character.
string3 is an array which is a pointer.
&string3 is a pointer to a pointer.
The types disagree.
Line 32 does not influence the result of the c program because cptr is reassigned on line 34 before its value is used. I expect optimization to discard your line 32.
g++ tells you where to go.
I'm sure there's a gcc flag to prevent the c version from compiling.
__________________
[code] Code tags[/code] are essential for python code!
|

April 22nd, 2012, 12:09 AM
|
 |
Contributed User
|
|
|
|
|
The error message line numbers don't line up with your code.
Your line numbering tool is only numbering non-blank lines. The compiler counts all lines.
|

April 22nd, 2012, 04:02 AM
|
 |
Contributing User
|
|
Join Date: Aug 2003
Location: UK
|
|
Quote: | Originally Posted by salem Your line numbering tool is only numbering non-blank lines. The compiler counts all lines. | Regarding that, paste the original code here using language specific code tags and the forum will put line numbers in for you.
|

April 22nd, 2012, 10:41 AM
|
|
Contributing User
|
|
Join Date: Apr 2012
Posts: 58
Time spent in forums: 1 Day 17 h 52 m 2 sec
Reputation Power: 2
|
|
|
abuse of char pointers
B49P23TIvg,
thank you for pointing out the offending line. Commenting it out resulted in source code that g++ turned into executable code. You're right an optimizing compiler would have eliminated that code. But it would have also hidden poor code (the line you found).
Anyway, I don't know how to turn on optimizing with either compiler anyway. Not yet convinced I should.
Now regarding my abuse of char pointers...
When I changed all five remaining source lines of the form
cptr=&string3[5];
to
cptr=string3[5];
gcc compiled it, but running the executable gave me a segmentation fault:
Code:
A string declared as an array.
A string declared as a pointer.
A string constant copied in.
A string initialized at compile time.
...now for the char pointer stuff...
Segmentation fault
g++, on the other hand, did not allow this kind of abuse, flagging every line with
error: invalid conversion from char to char*
So what ought I to have learned about my abuse of char pointers in C ? The same
thing does NOT work in C++. Is this a sign that I should immediately learn
the string class and implement its methods exclusively?
Or am I jumping to conclusions again? I often do. At this point, I think I will just
stick with gcc to write efficient code that executes correctly, before transforming
my source code into C++ source code.
I have proven that executable C source code that has been compiled with gcc will not always make it through the g++ compiler without errors. I see that my C source code is poor because I used two different types in each assignment without making an explicit cast. Thank you for pointing this out to me, B49P23TIvg. I now understand C++ is a more strongly typed language. That has forced me to confront my abuse of char pointers.
clifford, not sure what you meant by "language specific code tags"....
did you mean put a // in columns one and two of every blank line in my source code ? If this helps, I certainly will.
Thanks again, guys.
BTW,
Code:
$man gcc
No manual entry for gcc
See 'man 7 undocumented' for help when manual pages are not available.
Guess I didn't have room on my hard drive to install the man pages...either that or
something else went wrong....
|

April 22nd, 2012, 11:41 AM
|
|
Registered User
|
|
Join Date: Apr 2012
Posts: 1
Time spent in forums: 2 h 55 m 38 sec
Reputation Power: 0
|
|
|
You might want to search for a tutorial on pointers. Regardless of whether you use the C++ string library or not, you should learn about pointers because you'll run into them again later. C just makes you learn about them earlier because it doesn't have a string type in its library. It operates on arrays of characters.
As for not having GCC docs, you don't need them if you're learning. Just make sure you use the -Wall flag. It will catch a lot of your errors and warn you. It's up to you to interpret them.
For example, if the compiler produces a warning "invalid conversion from <type X> to <type Y>", you should consider looking at your code on the line noted in the file that is specified. If it's something like "char" to "char *" or even "int" to "char *", you should make sure you're not trying to assign a pointer to a character or a character/integer to a pointer.
|

April 22nd, 2012, 12:02 PM
|
 |
Contributing User
|
|
|
|
|
The gcc man pages are on line.
As is quite a lot of information.
You can even find out why
I Like Rush Limbaugh,
a group with 6 Members!
And now, to prove that dummies such as myself can use that same internet, compiling your c program with (having removed the // comments)
a=./c && make 'CFLAGS=-ansi -pedantic-errors' -k $a && $a
does indeed NOT build your c program of post 1.
As far as optimization goes---a standards conforming compiler will tell you about the problem with your source before it discards the ineffectual line of code. Anyway, it ought to. I wasn't on the standards committee. I have finally learned to spell committee first try.
How about learning how c works? This time you've done:
cptr = 'i';
I imagine this construct useful in a fiendishly clever c programming puzzle. (And then it would say (char*)'i')
Your problem is akin to Watson & Crick's. "It's a single helix! NO! It's a triple helix!" Wait---DNA is a DOUBLE helix. That is, you're searching for and shot all around
cptr = string3 + 5;
c adds 5 times the item size of *string3 to string3 and assigns that value to cptr.
(&(string3[5])) == (string3+5)
I hate this. You're probably employed, Maestro.
Worse, I actually learned something from this post. I realized as I awoke this morning that string3 (declared with []) is not merely a pointer, it is a constant pointer, hence the adoption of const keyword into c. The late Dennis Ritchie probably should have given it to us originally.*
I used to have, as a part of my personal c tool library, a macro named MARK to save the pointer, stuff a (char)0 into the position, do something, then restore the character.
About line numbering---don't number your lines. The next person has to remove them to compile your program (simple in emacs using columnar region delete) and we can use context to refer to lines. I'm not clifford, I may not be a 70% clifford, I'm pretty sure that by code tags he refers to the information you should read about how to post in the forum. Find these instructions in the sticky threads at the start of the c programming forum.
*Quantum Time Abstract
quantumrelativity.calsci.com/QuantumTime.pdf
Mark Lawrence figures out that your weight is caused by the difference in the rate time passes between your head and feet. He argues---convincingly---that Einstein should have figured this out too. To the extent I can tell. I did not take the general relativity class.
Last edited by b49P23TIvg : April 22nd, 2012 at 12:10 PM.
Reason: duplicate word removed
|

April 22nd, 2012, 03:21 PM
|
|
Contributing User
|
|
Join Date: Apr 2012
Posts: 58
Time spent in forums: 1 Day 17 h 52 m 2 sec
Reputation Power: 2
|
|
Quote: | Originally Posted by b49P23TIvg
a=./c && make 'CFLAGS=-ansi -pedantic-errors' -k $a && $a
|
I don't understand this. Am not using a make file just yet, since it's all in one source file.
David, thank you for pointing out to me the correct syntax for char pointers.
I appreciate that.
I cannot use the const keyword with string because of my char abuse (constant manipulation using char pointers in string3). However, I will bear it in mind later when coding char arrays that don't change, menus for example.
Anyway, here's my modified source code:
Code:
/* playing_with_pointers.c - copied from strings.c
Demonstrates printf, with no format specifier, prints strings initialized in
any of four ways.
Shows printf will recognize NULL as string terminator.
Shows printf will work with a string location other than zero.
Shows printf will work with both cases simultaneously.
*/
#include <stdio.h>
#include <string.h>
int main()
{
/* Example 1 */
char string1[] = "A string declared as an array.\n";
/* Example 2 */
char *string2 = "A string declared as a pointer.\n";
/* Example 3 */
char string3[30];
char *cptr;
/* Example 4 */
char string4[40]="A string initialized at compile time.";
strcpy(string3, "A string constant copied in.\n");
printf (string1);
printf (string2);
printf (string3);
printf (string4);
printf("\n");
// Now start playing with char pointer.
printf("\n...now for the char pointer stuff...\n");
cptr=string3 + 5;
*cptr='\0'; //Place NULL where first lowercase i used to be.
printf(string3); //??? should display A stri ???
cptr=string3; //Pass char pointer to printf()
printf("\n%s", cptr );
//Replace i and try printing from some other location in string.
cptr += 5; *cptr='i';
cptr=string3 + 9;
printf("\n%s", cptr );
//Now both cases together
cptr -= 9; cptr += 21;
*cptr='\0'; //Place NULL where second lowercase i used to be.
cptr=string3 + 9;
printf("\n%s\n", cptr);
return 0;
}
Its output is identical to what I posted above -- no change. That is good.
Thank you again, David, for your guidance. I regard myself as a better programmer because of it.
|

April 22nd, 2012, 07:33 PM
|
 |
Contributing User
|
|
|
|
|
You don't need a make file, the build command should work in your console window.
make invokes gcc like this:
cc -ansi -pedantic-errors c.c -o c
|
Developer Shed Advertisers and Affiliates
| Thread Tools |
Search this Thread |
|
|
|
| Display Modes |
Rate This Thread |
Linear Mode
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|
|