For Meessen

Posted on 1998-03-13
Last Modified: 2008-03-03
Since I am a beginner in C/C++, please explain a little to me. The code you sent me, is it pure C? or C++? what makes it C++ if so?
Please answer the following questions to get the indicated number of pts. (Right now it is 10pt., but if you answer questions, I promise to increase the pts. before grading you 'A')--If you answer all the questions, I'll increase to 60 pts.

char *mystrtok( char** str, char c ){
  what's char** str? [5pt.]

char* p
  what's char* p? [5pt.]

if( !str || !*str )
  what's the difference between the two str and *str in
  this call? [5pt.]

*p++ = '\0'; /* cut string */
  what does this do? Is *p++ like an array? [5pt.]

 for( var = mystrtok( &p, '=' ); var&&*var;  var = mystrtok( &p, '=' ) )
  why '&p'? When does var&&*var terminate the for loop? [10pt.]

      /* now you may use var and val as pointers on
         variable and value string */
printf("%s: %s\n",var,val);  
  can I use var in a strcmp call and val in a strdup? [5pt.}
  what exactly is a pointer? [15pt.]
Thank you.
Question by:MaDdUCK
  • 3
  • 2
  • 2
  • +2
LVL 84

Expert Comment

ID: 1257694
char **str; declares str to be a pointer to a pointer to a character;
char *p; declares p to be a pointer to a character
the expression (*str) is the same as the expression (str[0])
the expression (*p++) is the same ((p++)[0])
&p is the address of p the rsult is a pointer to p, so (*(&p)) is the same as (p)
for(; var&&*var;) terminates the loop when var is true and *var is true
you can use var in a strcmp if it has been set to point to a valid string in memory
a pointer type describes an object who's value provides a reference to an entity of the referenced type


Author Comment

ID: 1257695
1. The script uses char** str not char **str--any difference or an error?
2. see 1.
3. if str = "abcdef", then *str="a"?
4. what is p++? I though p++; will add 1 to p.
5. Please give some examples...I don't get it
6. That's obvious. But why use a variable? Does this mean that it terminates as soon as var and *var are non-NULL? Why do I need var&&*var...wouldn't either one do?
7. how do I do that?
8. Is this like a bookmark; it is placed inside a variable (at a certain pt. in memory and when I refer to that pointer, it refers to the location in the variable? If I would insert "abc" at a pointer and the pointer is at the 3rd character of "abcdefg" would I get abcabcdefg"?

I understand that these questions are complicated and I will consider lifting points. Please let me wait for meessen to find this threat.
Thank you for your help.
LVL 84

Expert Comment

ID: 1257696
1,2 no difference
3 *str = 'a';
4 yes, and its value is the value of p before the increment, (cf ++p)
6 when var is 0, then the behavior of *var is undefined, so to avoid that var&&*var checks var first, and shortcuts *var if var is null.

I'll let messen or someone else handle the rest, but I'll check in later if there are more questions.
Windows Server 2016: All you need to know

Learn about Hyper-V features that increase functionality and usability of Microsoft Windows Server 2016. Also, throughout this eBook, you’ll find some basic PowerShell examples that will help you leverage the scripts in your environments!


Accepted Solution

meessen earned 10 total points
ID: 1257697
1. char *p is equivalent to char* p. The inpotant point is there is a star. It'srelative location is not important. It may be important for readability though. Because, it means p is a pointer on a char.

If you write char* p, a; This does not mean p and a are poiters on char. It should have been written char *p, a; Because p is only a pointer on a char. a is a char.
If you want to declare two pointers on char you really need to write char *p1, *p2.

So I should have written char  **str; to be clean. But both form will compile and yield the same result.

So this char **str means str is a pointer on a pointer on a char. Why is that for ?
As you may know a string  is in fact a pointer on the first char of the array.
When you write char string[255] you declare a pointer on a char initialized to point on a compiler allocated buffer of 255 bytes. So string is in fact a char *string. It can be used with the following syntax: string[0] etc. But the big difference is that the compiler allocates  space for 255 bytes and initialize string with the address of this buffer so you can write into it. When you write char *string you declare a pointer on a char but it is not initialized. So you have to consider it's content as random number. This may lead to memory access errors. Note also that the allocated buffer's content is unspecified and may be non null and may contain grabage text.

If you declare char string[255] = "This is a string"; You declare string as a pointer on a char pointing on a buffer of 255 bytes whoe's content is initialized with the string "This is a string". As you may guess there is plenty of space left in the buffer that may be used later if you want to append some more text. You have to make sure it doesn't oveflow the buffer space. Otherwise you may corrupt other data and variables content. Very hard to diagnose.

You can also declare char string[] = "This is a string"; In this case you declare string as being a pointer on a char initialized on a buffer initialized with the given string. In this case the buffer will have exactly the string size including the ending NULL byte.

2. Ok char *p decalre p as a pointer on a char, but p is not initialise. Once it gets a valide value, that is the address of some char in a char buffer, you can access the pointed data. That is the data at the address stored in p. There is then two ways to access this data. One trough the subscript operator [] and the other trough the dereferencing operator *.
As ozo said, p[0] is equivalent to *p. It returns the char pointed by p.
You see that a pointer may be seen as an array reference or an address. Both are perfectly equivalent. p[1] is equivalent to *(p+1). The first notation is more readable though.
But if you want to scan an array of char, it is more readable to use the star notation. (in my point of view but both yield the same result).

1 extra. Why did I use a pointer on a pointer on a char then ?
As you know a function may only return one value. But it happens some time that we want to return two or more values. How do we do then ? We pass as argument the address of the variable we want the function to change. This is what happens with mystrtok. I want to return NULL or the address of the first string part, but I also want to return a pointer on the second part of the string. Standard strtok does not provide this last information. So we pass as argument the address of the variable we want to change. In this case it is a pointer on char we want to change. If the string is split, we want to change it's value and make it point on the second string part.
This is why we have this funny double star notation which is quite uncommon I agree.

The academic sample to illustrate the use of passing addresses as arguments if a function that swap two variables content. You change two variables at the same time.

3. this is tricky C programming and not very readable code. Not a good example for learners. The if operation is testing if the content in the parenthesis is non NULL.
Thus it is equivalent to write if( a != 0 ) or if( a ). Both notation will test if a is different of zero. Then you have the opposit, if( !(a!=0) ) is equivalent to if( !a ) and is equivalent to if( a == 0 ). As you see, to yield the same result but make a more understandable code I should have written if( (str == NULL) || (*str == NULL) ). As you know NULL is 0. This is to make sure the given parameter str is a pointer that points to something that point to something. Of course it does not test if str points on a char in a string but this filters out some possible mistakes.

4. What does *p++ = '\0'; do. First '\0'; is the ending null byte. It's zero. But this is the character constant notation as you would write 'a' to specify the ascii code for the letter a. This '\0' yields the ascii code for the ending byte. It should be 0. You could write *p++ = 0;
Don't ask me why I typed it that way. I though it would make clear I ment the string ending  ascii code. (just trying to be more readable ;-)
Now this *p++. This is  a combination of two operations. It is equivalent to write *p = 0; p = p+1; Or even p[0] = 0; p = p+1; so p++ is called an increment. *p means writing at the location whoe's address stored in p. Since p is suppose to point on the found character. writing *p = 0 will overwrite that character with the value 0. Then p points on the byte holding the string's ending ascii code. Now we want p to point on the next byte, that is the first byte of the second string part. So we simply add 1 to the address stored in p to do that. Now p contains the address of the first char of the second string.
Now p = p+1 can also be written as p++; The ++ operator is called a increment operator. It simply mean add 1 to p. But in this case it was combined into a single instruction *p++ = 0; How can we be sure that p will be incremented after it will wirte 0 ? It's because it's a post increment. When the ++ follows the variable, it is incremented after the instruction is executed. When it is before it is a preincrement and the variable is incremented before executing the instruction. It would have been written *(++p) = 0; This works with integers two. You can compare the following code int i = 0; printf( "i = %d\n", i++ ); and printf( "i = %d\n", ++i );

5. what is this &p for ? As you now know, we sometimes need to give the address of variables as function arguments so the function code can modify it's content from inside the function code. &p yields the address of p. Thus on return p may have been changed according to the returned value. If it's NULL, p is unchanged, otherwise p now is the input string remainder. The right side of the string that still needs to be parsed.
If we don't find a '&' character in the string, it means we have found the last variable-value pair of the string. We shouldn't discard it. Using the strtok will result in loosing this last variable-value pair. Because this function returns NULL if it  doesn't find the '&' character and you don't have a pointer on the string remainder.  This is why I had to write our own strtok that will give us (as a modified argument) the remainder string.

5extra. var && *var. As you now know it is equivalent to (var != NULL) && (var[0]!='\0').
var is the result of mystrtok. It is the first string part if the character is found or NULL if not. So var will be NULL if no '=' character is found.

This will obviously happend when all variable-value pair in the input string are found. Since p is modified at each successfull call. The string is reduced as each call. At the end there will be no more = symbol. So soon or later the for loop will end.

Now reading my code again I may have been a bit too fast in my analysis. If the input string is simply "=...". In this case a '=' is found, but the first part will be an empty string since the first byte is the ending null value. (remember '=' is replaced by the ending null byte). In this case the for loop will also end and the rest of the string will be ignored.
This may not be what we wanted. Suppose in the sequence the user gives A=a&=b&C=c
A=a will be properly parsed but finding the =b will make the routine quit. It might have been better to trap this problem and return an apropriate error to the caller.
One may also silently skip it and search for the next variable-value pair.

So you may remove this *var test and be aware that sometimes you may have an ampty variable name string and handle it properly. The instruction then becomes
 for( var = mystrtok( &p, '=' ); var;  var = mystrtok( &p, '=' ) )

6. Yes of course. You can consider var as a string whoes value is exactly equal to what is before the '=' symbol for each variable-value pair.
So you can so a strcmp. You can make a strcpy a strcat. But do not overwrite it's value. First you loose it, and if the new value is bigger than the previous string it will overlap following values and variables.

char mybuffer[255];
strcpy( mybuffer, var ); is ok as long as the var length is shorter then 255 bytes.
Apparently you know how to handle that. Every string operation can be used because a string (character array) is in fact a pointer on char.

7. This leads to the last question. What is a pointer ? Well as you may have now understood whis should have been the first question. Maybe you have a good idea now.
A pointer is simply an address. It is called a pointer because it is said the address points on a given location. The location may contain byte sequences, but also integers, floats or a structure. Playing with pointers opens you a new dimension, the dimension of dynamic data structure. For now, playing with character arrays is a good start where you can easely see the result. For instance you can explore and experiment qith the litle sample below:

char string[255] = "This is a test string"; /* you know now what this does */
char *p = string;  /* p is a pointer initialized to point on first byte of string */

puts( p );
puts(string); /* see same result. Both are same thing */

p++; puts(p); /* what happens ? understand why ? */

p = string + 5; puts(p); puts(string);  /* and now ? */

/* now modifying the data */
*p++ = '\0'; /* cuting the string */
puts( p ); puts(string); /* understand ? We have cut the string. Both are modified.*/

p--; *p = '='; puts(p); puts(string); /* pasting then back together */

/* to show that string is also a char pointer */
p = string; /* restore p to point on first string char */

string = string+5; /* move pointer five char away, equivalent to string += 5; */
puts(p); puts(string);

string[0] = 0;string = string+1; /* another cut. equivalent result but diffrent writing */
puts(p); puts(string);

/* now tricky, moving p also. No more pointer on first byte of string ! */
p += 6;
puts( p ); puts(string);

/* now reattaching things together and returning to first byte */
--string = '='; p -= 6; string -= 5; puts(p); puts(string);

You see very simple arithmetic with pointers. It works like indices in an array. But here the array is the memory and you have special operators to access this memory.
You could move pointers outside of arrays by adding too big values. The result may depend of your operating system. It may crash, or complaining about an atempt to access unreadable memory which means in fact that you are not allowed ot read that memory.

These questions are not complicated to me. You have an excellent reaction and sure you'll be an expert very soon if you keep asking your questions and try to do it by yourself. The best way to understant things. So you better save your points for more questions. I'm not after points. It was a pleasure to share a bit of my knowledge I earned by hard work and hoped it could save you some ;-)


Author Comment

ID: 1257698
Are you sure you DON'T want the points?
I am really impressed. You are one superb guy! This is exactly what EE needs and I will attempt to follow your example. Awesome help you gave me here.

So if you want the points, post!

Expert Comment

ID: 1257699
Let's  keep it 10 points.

Oops there is a typing mistake.

     --string = '=';

should be
--string; *string = '='; .. which is equivalent to *(--string) = '='; but less readable.

--string means move the poiner one step behind.(string now contain the address of the previous byte). *string means the data whoes address is stored in string.
You can write char c = *string; to get the data 'pointed' by string or like here *string = 'x'; to change the data pointed by string.


Author Comment

ID: 1257700
Oh well, thank you then and I hope I can ever be of similar help.

Expert Comment

ID: 1257701

You have an exemplary attitude toward helping others.  I agree with MaDdUCK, EE needs more experts with your type of attitude.

Thanks for setting an example for others to follow.


Expert Comment

ID: 1257702
I'll second that. Thanks meessen.

Dan Gardner
Experts Exchange

Featured Post

Migrating Your Company's PCs

To keep pace with competitors, businesses must keep employees productive, and that means providing them with the latest technology. This document provides the tips and tricks you need to help you migrate an outdated PC fleet to new desktops, laptops, and tablets.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Have you thought about creating an iPhone application (app), but didn't even know where to get started? Here's how: ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Important pre-programming comments: I’ve never tri…
Preface I don't like visual development tools that are supposed to write a program for me. Even if it is Xcode and I can use Interface Builder. Yes, it is a perfect tool and has helped me a lot, mainly, in the beginning, when my programs were small…
The goal of this video is to provide viewers with basic examples to understand and use structures in the C programming language.
The goal of this video is to provide viewers with basic examples to understand how to use strings and some functions related to them in the C programming language.

778 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question