1
int check_authentication(char *password) 
  // 1
{
int auth_flag = 0;
char password_buffer[16];

strcpy(password_buffer, password);      // 2
   if(strcmp(password_buffer, "brillig") == 0)
   auth_flag = 1;
   if(strcmp(password_buffer, "outgrabe") == 0)
   auth_flag = 1;
   return auth_flag;
}

check_authentication(argv[1]) // Passing a 'Command Line argument'
// ( which is a string in this example) to the check_authentication function.

I have two questions reg. the lines labelled 1 and 2 above,

  1. The function expects a character pointer as an argument. But we pass a "string" i,e an array of characters as an argument. How ?????

  2. The address held by the pointer "password" (that points to a character) is copied to the "password_buffer" array. It makes no sense to me . Pls explain.

WhozCraig
  • 65,258
  • 11
  • 75
  • 141
callyaser
  • 155
  • 11
  • 1) the *type* of a string is `char*`; 2) an expression of `char[]` "decays" to `char*` - the important thing with a C string is the object the *pointer refers to* is a valid string: the sequence of characters "in memory" terminated with a '\0' .. – user2864740 Feb 17 '15 at 21:49
  • 1
    Note aside from providing a prime target for a buffer overflow, `password_buffer` in this code is useless. – WhozCraig Feb 17 '15 at 21:53
  • Not only, it also leaves a nice signature in stack in case of crash... With a very secret password... – Valeri Atamaniouk Feb 17 '15 at 21:55
  • Besides all shortcomings in the code, the question is exact. –  Feb 17 '15 at 21:56
  • So in function declaration u define the function such that it expects a 'character pointer' .During function call u must pass a pointer only rite ? I dont get this only. i,e if a function expects int u pass int, if it requires string u pass string,,but in this case it expects a pointer but u pass an array of characters ...???/ – callyaser Feb 17 '15 at 22:04

4 Answers4

5
  1. You are passing a character pointer which points to the first character in the string. You aren't actually passing the whole string.

  2. The strcpy function reads the character being pointed to by this pointer, and then keeps reading successive characters from the next memory location until it encounters a null terminator.

The first argument of strcpy, and both arguments of strcmp, work in the same way.

M.M
  • 138,810
  • 21
  • 208
  • 365
  • Yeah I get it partially. But if we pass a "string" in other words an array of characters to the function, then y don't we declare the function like this check_authentication(char password[ ]).what is the significance of pointers in the function parameter declaration..I m confused there.! – callyaser Feb 17 '15 at 21:55
  • 1
    @callyaser [see this answer](http://stackoverflow.com/questions/22677415/why-do-c-and-c-compilers-allow-array-lengths-in-function-signatures-when-they/22677793#22677793) for a good explanation of that – M.M Feb 17 '15 at 21:59
2

The function expects a character pointer as an argument. But we pass a "string" i,e an array of characters as an argument. How ?????

Except when it is the operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.

When you call

strcpy(password_buffer, password);

the expression password_buffer has type "16-element array of char"; since the expression is not the operand of the sizeof or unary & operators, the expression is converted ("decays") to type "pointer to char", and the value of the expression is the address of the first element. This pointer value is what gets passed to strcpy.

In short, any time you pass an array expression to a function, the function will receive a pointer value. In the context of a function parameter declaration, T a[] and T a[N] will be interpreted as T *a.

Believe it or don't, Ritchie did have reasons for designing the language this way; refer to this paper for details (look for the section titled "Embryonic C").

The address held by the pointer "password" (that points to a character) is copied to the "password_buffer" array. It makes no sense to me . Pls explain.

That's not what's happening; what's happening is that strcpy is copying the contents of the buffer starting at the address given by password to password_buffer. Imagine the following memory map:

Item              Address                0x00  0x01  0x02  0x03
----              -------                ----  ----  ----  ----
"foo"             0x7fffc7cf4b22          'f'   'o'   'o'     0

argv[1]           0x7fffc7cf2670         0x00  0x00  0x7f  0xff
                                         0xc7  0xcf  0x4b  0x22

password          0x7ffffdbe1878         0x00  0x00  0x7f  0xff  
                                         0xfd  0xbe  0x2v  0x22

password_buffer   0x7ffffdbe1880         0x??  0x??  0x??  0x??
                                         0x??  0x??  0x??  0x??
                                         0x??  0x??  0x??  0x??
                                         0x??  0x??  0x??  0x??

where 0x?? indicates an unknown/indeterminate byte value.

The command line argument string "foo" is stored at address 0x7fffc7cf4b22. Note that in C, a string is simply a sequence of character values terminated by a 0-valued byte. Strings are stored as arrays of char (const char in C++), but not all arrays of char contain a string.

The argv[1] expression evaluates to the address of the first command line argument, which is the address of the string "foo", which is 0x7fffc7cf4b22. This value is passed to the check_authentication function and is stored to the password parameter. Note that argv[1] and password are different items in memory (they have different addresses), but both contain the same value (the address of the string "foo").

The password_buffer array starts at address 0x7ffffdbe1880. Since it wasn't declared static and doesn't have an explicit initializer, the contents of the array are indeterminate.

The strcpy function copies the contents of the string starting at address 0x7fffc7cf4b22 into the buffer starting at address 0x7ffffdbe1880 until it sees that 0-valued byte. After the call to strcpy, our memory looks like this:

Item              Address                0x00  0x01  0x02  0x03
----              -------                ----  ----  ----  ----
"foo"             0x7fffc7cf4b22          'f'   'o'   'o'     0

argv[1]           0x7fffc7cf2670         0x00  0x00  0x7f  0xff
                                         0xc7  0xcf  0x4b  0x22

password          0x7ffffdbe1878         0x00  0x00  0x7f  0xff  
                                         0xfd  0xbe  0x2v  0x22

password_buffer   0x7ffffdbe1880          'f'   'o'   'o'     0
                                         0x??  0x??  0x??  0x??
                                         0x??  0x??  0x??  0x??
                                         0x??  0x??  0x??  0x??
John Bode
  • 119,563
  • 19
  • 122
  • 198
1

Strings are really just arrays of characters that are terminated with a null byte \0. The array is the string itself, the char pointer however is the memory location of the zeroth position of the array.

strcpy reads characters beginning from the memory location pointed at by the char pointer until it encounters the null termination character.

TheHorse
  • 234
  • 2
  • 9
  • 1
    The array is a region of storage; the string exists in that storage. (the string might not use up the entire array). – M.M Feb 17 '15 at 22:00
  • So in function declaration u define the function such that it expects a 'character pointer' .During function call u must pass a pointer only rite ? I dont get this only. i,e if a function expects int u pass int, if it requires string u pass string,,but in this case it expects a pointer but u pass an array of characters ...???/ – callyaser Feb 17 '15 at 22:05
1
  1. Array actually isn't passed as such. What gets passed is a pointer to the very first element of the array. A string in C is actually an array of chars with a terminating NUL and it's a pointer to its first element that gets passed.

  2. You really should read strcpy manpage carefully http://linux.die.net/man/3/strcpy . No addresses ever get copied there. All the function does is taking a string (an array of chars) password pointer points at and copy all the chars found at that address up to the NUL to the address pointed by password_buffer pointer.

Igor S.K.
  • 999
  • 6
  • 17