/*
ProgEx09 -- C++ Program
Continuing from where we left off in ProgEx08, there is yet another way to
initialize a string in C. The C runtime functions that deal with null
terminated character arrays all expect a char pointer variable holding the
address of the first byte of the string. As with the case of the szBuffer[]
array we've been working with so far, a char pointer variable declaration
can be combined with initialization of storage like so...
char* pszStr = "Frederick J. Harris"
printf("pszStr = %s\n", pszStr);
In the above code the term...
char* pszStr = "Frederick J. Harris"
is a variable declaration for a pointer variable named pszStr (pointer to
zero terminated string) combined with the initialization of storage for the
19 byte string plus the null terminator. As with the szBuffer array of the
last example, you can't just declare the variable by itself and then later
use the equal sign to assign the literal string "Frederick J. Harris" to it.
That would be an error. In other words, you can't do this...
char* pszStr;
pszStr="Frederick J. Harris";
You can't do it because the compiler has allocated storage to hold a char
pointer variable that is totally legitimate, but there has as of yet been no
legitimate storage allocated to which it can point. You had better read the
above sentence five or ten more times because this can be a difficult concept
to grasp. If you can understand it after reading it five or ten times you
are doing considerably better than I because I believe it took me the better
part of two years before the full implications of this in all its varied
obscure manifestations sank in.
Now let me show you what must be done for the above assignment of a literal
character string to a valid pointer. First off, memory must be allocated at
run time to hold the string. The Win32 system has a whole menagerie of
functions for allocating memory, but so far in this tutorial series we've not
used a single proprietary Win32 function. All the programs so far will
compile and run exactly as written under Unix, Linux, or Windows. Just
thought I'd mention that. So to allocate memory at run time to hold a string
we'll use a standard C runtime function named malloc(). malloc() is easy to
use. All it wants is the number or bytes requested and if it returns a
number it will be the address of where your requested bytes start. Here is
a little program showing how to do it...
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
char* pszStr=NULL; //C/C++ won't initialize variables to 0 like PowerBASIC
pszStr=(char*)malloc(sizeof("Frederick J. Harris")+1); //The (char*) before
if(pszStr) //malloc() is known as
{ //a 'cast'. malloc()
strcpy(pszStr,"Frederick J. Harris"); //is prototyped as
printf("%s\t%u\n",pszStr,(unsigned int)pszStr); //returning a void* so
free(pszStr); //the memory must be
} //cast to the correct
else //variable type which
puts("Couldn't Allocate Memory! Not Good!"); //here is a pointer to
getchar(); //a null terminated
//string.
return EXIT_SUCCESS;
}
/*
Frederick J. Harris 4079560
*/
/*
First note the includes at top. stdlib.h is needed for malloc(). stdio.h is
needed for printf() and puts(). string.h is needed for strcpy(). These are
really basic and common includes that you'll need in many C programs.
The first statement in main() declares a variable that is a pointer to a char
string. Note that both char and char* are valid variable types in C. A char
can only hold a single character though, so it is a bit limiting. A char*
though can point to a single character or a multi-character string. Note
that I initialized pszStr with NULL. Neither C nor C++ initializes its
variables to zero when declared. Therefore, if pszStr was inadvertantly used
without being initialized with valid memory, it would likely point to some
garbage address that would cause a crash. This is termed a 'wild pointer'.
After the variable declaration pszStr is set to a valid memory address
obtained through use of malloc...
pszStr=(char*)malloc(sizeof("Frederick J. Harris")+1);
In that expression we've used C's sizeof built in function to get the length
of the string, then we've added the extra byte to the string length to make
room for the null terminator. The strange looking (char*) in front of malloc
is something that you'll get used to real fast if you do any C or C++ coding.
Its known as a 'cast'. These languages are very picky when it comes to
assigning one variable to another. This is known as 'strong typing'. A
strongly typed language likes to keep all its various types of variables in
little protective boxes, so to speak, and not let them mingle too much.
Another way of looking at it is that a function such as malloc() that is
typed as returning a void* (so that it can allocate any type of variable,
i.e., int, double, etc.), has to be cajoled or coaxed into assigning its
result to anything different.
In any case, if malloc is able to come up with the requested bytes, it will
return the starting address of the memory allocation which now belongs to
you. If it can't come up with the bytes it returns NULL. If you don't check
for an allocation failure and try to stuff some bytes into a null pointer
your program will crash hard.
The strcpy function copies the literal string "Frederick J. Harris" to the
address returned by malloc, and the printf function outputs pszStr twice;
first using the %s format specifier which informs printf to interpret pszStr
as a null terminated character string, then with the %u format specifier
which tells it to interpret it as an unsigned integer, i.e., an address.
*/