Passing a Char Array's Address Instead of Itself to a Function

I recently learned some pointers. And yes, they're confusing. My question is, how can we pass the char array's address to a function. Yes, I can do it with int arrays (You can see it in code 1). But with the char variable I can't, it's confusing me. And you can see code 2, it's not working how I wanted it to work.

This is necessary for a 2D array to send its address line by line, instead of sending the whole array. For example, I should send the address of the 2nd line of the array and find the other elements in the line with a loop to add 1 to the address every time.

Our teacher said this "address passing" thing is faster than sending the whole array. And yes, it's while using really big arrays.

Code 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream> //This is the code 1.

using namespace std;

void countDigits (int *myArray)
{
    cout << myArray << endl;
    cout << myArray + 1 << endl;
    cout << myArray + 2 << endl;
    cout << myArray + 3 << endl;
    cout << endl;
    cout << *(myArray) << endl;
    cout << *(myArray + 1) << endl;
    cout << *(myArray + 2) << endl;
    cout << *(myArray + 3) << endl;
    
}

int main ()
{
    int myArray [4] {1, 3, 5, 7};
    
    countDigits (&myArray [0]);

    return 0;
}


Code 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream> // This is code 2.

using namespace std;

void countDigits (char *myArray)
{
    cout << myArray << endl;
    cout << myArray + 1 << endl;
    cout << myArray + 2 << endl;
    cout << myArray + 3 << endl;
    cout << endl;
    cout << *(myArray) << endl;
    cout << *(myArray + 1) << endl;
    cout << *(myArray + 2) << endl;
    cout << *(myArray + 3) << endl;
    
}

int main ()
{
    char myArray [4] {'1', '3', '5', '7'};
    
    countDigits (&myArray [0]);

    return 0;
}
Both programs pass a pointer to the first element in the array as argument to the function.

The difference that you're seeing is because the << operator works different with char* than all other pointers. With char* it assumes the pointer points to the first element in a null-terminated "C array" and tries to print all characters in memory until it finds a null character ('\0'). In your program (code 2) the array doesn't contain a null character so it's technically undefined behaviour so there is no guarantees what will happen.

With all other pointer types the << operator will print the address that the pointer holds. If you want to do the same with a char* you can cast it to a void* before passing it to the << operator.

1
2
3
4
void countDigits (char *myArray)
{
    cout << static_cast<void*>(myArray) << endl;
}
Last edited on
Peter87, thanks for your help. I learned a new thing about pointers.

What can I do if I don not want to use << operator?

And also is printing of the values of address' on code 2 true?
What can I do if I don not want to use << operator?

There are other functions that you can use. You can use put to write a single character. You can use write to write an array of characters.

1
2
3
4
cout.put('A'); // Write the letter A

char myArray [4] {'1', '3', '5', '7'};
cout.write(myArray, sizeof(myArray)); // write all the characters in myArray 


But you cannot print an address with these functions directly. You would have to convert it to characters yourself which is something that the non-char* version of << does for you, so you probably still want to use << for this. Just cast to void* and you'll be fine.

And also is printing of the values of address' on code 2 true?

I don't understand the question. Code 2 is not correct. It might print garbage or it might crash. The C++ language specification just says it is undefined behaviour because the string is not null terminated.
Last edited on
I mean, is this a true way to write values of adresses? As you said; directly typing array's name, pointing it to its address.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream> 

using namespace std;

void countDigits (char *myArray)
{
    cout << *(myArray) << endl;
    cout << *(myArray + 1) << endl;
    cout << *(myArray + 2) << endl;
    cout << *(myArray + 3) << endl;
    
}

int main ()
{
    char myArray [4] {'1', '3', '5', '7'};
    
    countDigits (&myArray [0]);

    return 0;
}


Thanks again 🙏
Last edited on
Ah, yes those lines are perfectly fine and not undefined behaviour.

Using pointers to the first element in arrays is such a common way to handle arrays that they have even designed the language so that arrays are implicitly convertible to such pointers and you can even use the same syntax to access the elements.

The following code is exactly equivalent to what you wrote:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream> 

using namespace std;

void countDigits(char myArray[])
{
    cout << myArray[0] << endl;
    cout << myArray[1] << endl;
    cout << myArray[2] << endl;
    cout << myArray[3] << endl;
}

int main ()
{
    char myArray[4] {'1', '3', '5', '7'};
    countDigits(myArray);
}


But don't be fooled by this. myArray inside countDigits is still a pointer.
Last edited on
The last one, is sending addresses instead of the whole array, making the program runs fast? (Big big arrays)
All the code posted above (yours and mine) only pass an address (i.e. pointer to the first element in the array). The whole array is not copied.

Arrays are never copied when you pass them to functions. The only situation when that happens automatically is if the array is part of a class/struct object.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream> 

using namespace std;

struct S
{
    char myArray[4];
};

void countDigits(S s)
{
    cout << s.myArray[0] << endl;
    cout << s.myArray[1] << endl;
    cout << s.myArray[2] << endl;
    cout << s.myArray[3] << endl;
}

int main()
{
    S s {'1', '3', '5', '7'};
    countDigits(s);
}

^ This will copy the array when the S object is passed to the function. To avoid this it's common to pass such objects by reference (which are similar to pointers but not quite the same thing).
Last edited on
Then, what are we passing while directly typing array name instead of its pointer? Its address is directly passing to function?
The array is automatically converted to a pointer to its first element when you pass it to the function.

When I said my code was equivalent to yours I meant it 100%. You can do one of the changes I made (you don't need to make all of them) and it would still work.


 
void countDigits(char myArray[])
and
 
void countDigits (char *myArray)
have the exact same meaning.

The type of myArray is char* (pointer to char).


 
cout << myArray[1] << endl;
and
 
cout << *(myArray + 1) << endl;
have the exact same meaning.

This is true even if myArray is an array.


 
countDigits(myArray);
and
 
countDigits(&myArray[0]);
has the same meaning in this program.

It's possible that there would be a difference between these two for some other function but it depends on how it was declared.
Last edited on
Thanks both of you guys. Have good day!
Topic archived. No new replies allowed.