0

In this code, we made a const char pointer id, as it is a char so it should store only one element address. but in default constructor we assigned, "NULL" to that id, how is that id is holding 4 char? and in parameterized constructor we pass i[] array and assign the value to id, same again how char id is holding complete array? further why we need const char?

class Employee
{
    public:
        string name;
        const char *id;
        int age;
        long salary;

        Employee ()
        {
            name = "NULL";
            id = "NULL";
            age =0;
            salary = 0;
        };

        // Employee(string n, char id[], int a, long s): name(n), id(id), age(a), salary(s)
        // {};
        Employee (string n,const char i[], int a, long s)    //const use krne k baighar warning a rhe
        {
            name = n;
            id = i;
            age = a;
            salary = s;
        };
        void getData()
        {
            cout<< "Employee ID: "<< id <<endl;
            cout<< "Employee Name: "<< name <<endl;
            cout<< "Employee Age: "<< age <<endl;
            cout<< "Employee Salary: "<< salary <<endl;
        };

};

I am confused that if id is char then how it is holding a string literal of 5 character. CHAR type can store only single character, but if i am making it a pointer then it is holding many character. Please clear this point, i am very confused as how it is working.

  • `id` is a pointer, the only thing it "holds" is the address of an object - it does not "hold" the entire array – UnholySheep Jul 14 '20 at 14:19
  • How do you know how many chars it holds? – vahancho Jul 14 '20 at 14:20
  • 1
    If you are using `std::string` for `name`, why is `id` a `char *`? – crashmstr Jul 14 '20 at 14:25
  • 1
    Yeah, it *is* funny. In C and C++ pointers to single characters are also used to point to the first (or any!) character in a whole array. Which one is meant cannot be concluded from the language, you have to look at the code and the documentation. If a pointer is used to point to the first element in an array, there is usually a length coming with it because there is no other general way to know how many elements are stored behind that first one. (With printable characters one can (and the standard library functions do) look for a terminating zero byte, but that fails for binary data.) – Peter - Reinstate Monica Jul 14 '20 at 14:43
  • As an aside, both C and C++ *can* point to whole arrays, but that's not very useful in C because each array length constitutes its own, distinct type, so you cannot pass or assign pointers to arrays of different lengths to the same functions or variables. (It's more useful in C++ where the length can be a template parameter.) So you could take the address of an entire array and assign it to a properly typed pointer: `const char (*p)[5] = &"NULL"; putchar((*p)[0]);`. But that's an unusual idiom. – Peter - Reinstate Monica Jul 14 '20 at 14:50
  • @Peter-ReinstateMonica so in c++ it is built in that by using pointer, we can have address of whole array. As here in constructor, we pass char i[] and write id=i; so now id can automatically have address of all elements of i[] and we can access all those elements using id pointer? –  Jul 14 '20 at 15:00
  • ***id can automatically have address of all elements of i[]*** It does not really do that. It has the address of the first element only. By definition the rest of the elements are in contiguous addresses. The only way to tell the end is the presence of a null terminator. This is special for c-strings and not other array types. – drescherjm Jul 14 '20 at 15:02
  • @drescherjm i have a same query and asked that why using const, but its not working without const cuz anything we are passing it is treated as const char[n] .like even if i dont write const char* "NULL" is being treated as const char [5] –  Jul 14 '20 at 15:04
  • @drescherjm so you are saying that c++ compiler take all the consecutive address until reach the null terminator and in this way whole array can be accessed. I am really thankful for your help. I have been confused on these things from a long time, i am really really thankful –  Jul 14 '20 at 15:07
  • @Miles Budnek gave a good answer on that. – drescherjm Jul 14 '20 at 15:08
  • With all of this said, once you understand what is going on you should avoid c-strings this and use `std::string` instead almost every time. std::string is the proper `c++` string. – drescherjm Jul 14 '20 at 15:10
  • 1
    @drescherjm Note that `id` itself is not const, it *points* to const. You can change what it points to in the program. In fact, if it were const you could not assign to it even in the constructor; you'd have to *initialize* it. That it points to const, by the way, does not prevent you from assigning the address of a non-const character (array)! It just indicates that the *contents* of what it points to is not to be changed by the class. – Peter - Reinstate Monica Jul 14 '20 at 16:36

2 Answers2

2

The string literal "NULL", is an array of 5 chars (the fifth being a null character to signal the end of the string). Arrays in C++ are laid out sequentially in memory. What this means is that if you have a pointer to the first element of an array, you can find the subsequent elements using simple arithmetic.

Because of this, arrays in C++ can be implicitly converted to a pointer to their first element. When you write id = "NULL", id will be assigned to point to the first character of that array of 5 characters (the 'N' at the beginning of "NULL"). Your object will be laid out in memory something like this:

Employee
+--------+
| name   |
|        |
+--------+
| id     |
|    +----------+
+--------+      |
| age    |      v
|        |    +-+-+---+---+---+----+
+--------+    | N | U | L | L | \0 |
| salary |    +---+---+---+---+----+
|        |
+--------+

Since the rest of the characters are laid out sequentially in memory, you can find the 'U' simply by adding one byte to the address stored in id, and the first 'L' by adding two bytes, etc. You can keep adding one until you find a '\0' character, which signals that you've reached the end of the string.

Miles Budnek
  • 28,216
  • 2
  • 35
  • 52
  • As we have not explicitly incremented the pointer. do compiler implicitly do that to point to the next character until '\0' reaches? –  Jul 15 '20 at 06:52
  • The string manipulation functions that work on C-style strings (such as `strcpy` or `cout`'s `<<` operator overload for `const char*`) do that internally. – Miles Budnek Jul 15 '20 at 11:47
0

It's because the compiler is told to allocate a const char and to be pointed an object with type char array with length of 5 (since NULL is has a length of 4 excluding a null-terminator) and it's initialized with a string literal.

Everything's good until you dereference it. When you do so, you'll get only N char printed, not the full string. But they're stored contiguously in the memory so they're printed until a null terminator for the string literal \0 occurs in std::cout to terminate reading the string afterwards it.

Also, notice that you can't change their values once it get pointed, they're no more replaceable.


You don't need to use const char * when you can simply use std::string to work with those strings extensively in C++.

Rohan Bari
  • 7,482
  • 3
  • 14
  • 34
  • 1
    Errr... `"NULL"` is an array of 5 chars, against intuition. It is also distinct from `NULL` (which may be defined and has a size of 4 bytes on some systems). – Peter - Reinstate Monica Jul 14 '20 at 14:35
  • @Peter-ReinstateMonica oh yes, The err has now fixed, thanks! – Rohan Bari Jul 14 '20 at 14:36
  • 2
    "length of 4 including null-terminator" is even worse than before -- it's either **5** including null-terminator or **4** **ex**cluding null-terminator ;-). – Peter - Reinstate Monica Jul 14 '20 at 14:38
  • @RohanBari a char* can hold address of any length of char[] or string? and then hold address of all the char in that string or array in a sequence? –  Jul 14 '20 at 14:41
  • @LittleStar almost similar but `std::string` and `char *` are different things. `char *` can hold the address of any length of `char[]` is right. – Rohan Bari Jul 14 '20 at 15:08