Home arrow C programming arrow A TUTORIAL ON POINTERS AND ARRAYS IN C - Part 2

Language Translator

Hacking Zone

Hacking Tools
Attacking

Configure Windows

Windows Configuration

Novels

Mix Novels

Human Personality

Body Language
A TUTORIAL ON POINTERS AND ARRAYS IN C - Part 2 Print E-mail
Article Index
A TUTORIAL ON POINTERS AND ARRAYS IN C - Part 2
Page 2
Page 3
Page 4
Page 5
Page 6

CHAPTER 6: Some more on Strings, and Arrays of Strings

 

Well, let' go back to strings for a bit. In the following all assignments are to be understood as being global, i.e. made outside of any function, including main(). We pointed out in an earlier chapter that we could write:


     char my_string[40] = "Ted";


which would allocate space for a 40 byte array and put the string in the first 4 bytes (three for the characters in the quotes and a 4th to handle the terminating '\0').
Actually, if all we wanted to do was store the name "Ted" we could write:


     char my_name[] = "Ted";


and the compiler would count the characters, leave room for the nul character and store the total of the four characters in memory the location of which would be returned by the array name, in this case my_name.
In some code, instead of the above, you might see:


     char *my_name = "Ted";


which is an alternate approach. Is there a difference between these? The answer is.. yes. Using the array notation 4 bytes of storage in the static memory block are taken up, one for each character and one for the terminating nul character. But, in the pointer notation the same 4 bytes required, plus N bytes to store the pointer variable my_name (where N depends on the system but is usually a minimum of 2 bytes and can be 4 or more). In the array notation, my_name is short for &myname[0] which is the address of the first element of the array. Since the location of the array is fixed during run time, this is a constant (not a variable). In the pointer notation my_name is a variable. As to which is the better method, that depends on what you are going to do within the rest of the program.
Let' now go one step further and consider what happens if each of these declarations are done within a function as opposed to globally outside the bounds of any function.


void my_function_A(char *ptr)
{
       char a[] = "ABCDE"
       .
       .
}
void my_function_B(char *ptr)
{
      char *cp = "FGHIJ"
      .
      .
}


In the case of my_function_A, the content, or value(s), of the array a[] is considered to be the data. The array is said to be initialized to the values ABCDE. In the case of my_function_B, the value of the pointer cp is considered to be the data. The pointer has been initialized to point to the string FGHIJ. In both my_function_A and
my_function_B the definitions are local variables and thus the string ABCDE is stored on the stack, as is the value of the pointer cp. The string FGHIJ can be stored anywhere. On my system it gets stored in the data segment.


By the way, array initialization of automatic variables as I have done in my_function_A was illegal in the older K&R C and only "came of age" in the newer ANSI C. A fact that may be important when one is considering portability and backwards compatibility. 
As long as we are discussing the relationship/differences between pointers and arrays, let' move on to multi-dimensional arrays. Consider, for example the array:


      char multi[5][10];


Just what does this mean? Well, let' consider it in the following light.


      char multi[5][10];


Let' take the underlined part to be the "name" of an array. Then prepending the char and appending the [10] we have an array of 10 characters. But, the name multi[5] is itself an array indicating that there are 5 elements each being an array of 10 characters. Hence we have an array of 5 arrays of 10 characters each..
Assume we have filled this two dimensional array with data of some kind. In memory, it might look as if it had been formed by initializing 5 separate arrays using something like:


      multi[0]    =  {'0','1','2','3','4','5','6','7','8','9'}
      multi[1]    =  {'a','b','c','d','e','f','g','h','i','j'}
      multi[2]    =  {'A','B','C','D','E','F','G','H','I','J'}
      multi[3]    =  {'9','8','7','6','5','4','3','2','1','0'}
      multi[4]    =  {'J','I','H','G','F','E','D','C','B','A'}


At the same time, individual elements might be addressable using syntax such as:


      multi[0][3] = '3'
      multi[1][7] = 'h'
      multi[4][0] = 'J'


Since arrays are contiguous in memory, our actual memory block for the above should look like:


     0123456789abcdefghijABCDEFGHIJ9876543210JIHGFEDCBA
     ^
     |_____ starting at the address &multi[0][0]


Note that I did not write multi[0] = "0123456789". Had I done so a terminating '\0' would have been implied since whenever double quotes are used a '\0'     character is appended to the characters contained within those quotes. Had that been the case I would have had to set aside room for 11 characters per row instead of 10.
My goal in the above is to illustrate how memory is laid out for 2 dimensional arrays. That is, this is a 2 dimensional array of characters, NOT an array of "strings".



 
< Prev   Next >
Your Ad Here

Donate us!!

Enter Amount:

RSS socialnet

Add to MyYahoo!
Subscribe in NewsGator Online
Add to Newsburst
Add to Google
Add to My AOL
Add to Pluck
Subscribe in FeedLounge
Add to Windows Live
Add to NetVibes
Subscribe in Rojo
Subscribe in Bloglines
Add to MyMSN
Add to Plusmo for your cellphone
Add to PageFlakes
Add to Technorati
Add to BlinkBits