#include <iostream>
int main()
{
int i;
char* buffer = newchar[8]; // buffer is a char-pointer, holding the starting address to a 8x (1byte)char sized memory space allocation on the heap
char h[8] = "1234567"; // h is a char array of size 8x (1byte)chars, initiallised with "1234567"
memset(buffer, 65, 8);// initialise 8x (1byte)char memory allocations with the value 65 (ASCII "A") starting at address held in pointer buffer
std::cout << buffer << "Z" << std::endl; // print value held in 8x (1byte)chars of heap starting at address buffer followed by "Z"
for (i = 0; i < 8; i++)
{
buffer[i] = h[i]; // initialse 8x (1byte)chars of heap memory with "1234567"
}
std::cout << buffer << "Z" << std::endl; // print value held in 8x (1byte)chars of heap starting at address buffer, followed by "Z"
delete [] buffer; // release heap allocation
return 0;
};
#include <iostream>
#include <cstring>
int main()
{
int i;
char* buffer = newchar[8]; // buffer is a char-pointer, holding the starting address to a 8x (1byte)char sized memory space allocation on the heap
char h[8] = "1234567"; // h is a char array of size 8x (1byte)chars, initiallised with "1234567"
memset(buffer, 65, 7);// initialise 7x (1byte)char memory allocations with the value 65 (ASCII "A") starting at address held in pointer buffer
buffer[7] = '\n'; // adds string terminator
std::cout << buffer << "Z" << std::endl; // print value held in 8x (1byte)chars of heap starting at address buffer
for (i = 0; i < 8; i++)
{
buffer[i] = h[i]; // initialse 8x (1byte)chars of heap memory with "1234567"
}
std::cout << buffer << "Z" << std::endl; // print value held in 8x (1byte)chars of heap starting at address buffer
delete [] buffer; // release heap allocation
return 0;
};
memset(buffer, 65, 7);// initialise 8x (1byte)char memory allocations with the value 65 (ASCII "A") starting at address held in pointer buffer
buffer[7] = NULL; // add NULL string terminator
The reference page for snprintf indicates that it requires #include <cstdio> - am I reading this correctly?
Yes., include <cstdio>.
What is the difference between
In the first snippet you are telling the compiler how many elements you want in your array, the second snippet the compiler determines the number of elements by the number in the constant char C string (string literal) used to initialize the array.
One key factor of "uniform initialization" is the compiler can't perform implicit type conversions (type narrowing). A string literal can't be used to initialize a non-const C string.
The 2nd snippet is declared as being const, so it is not alterable.
The 3rd snippet is another example of "uniform initialization."
The reference page for snprintf indicates that it requires #include <cstdio> - am I reading this correctly?
iostream often does this itself depending upon the compiler used. It does with VS hence it compiled OK for me and I forgot to include cstdio explicitly...
Re snprintf(). There are also strcpy()/strncpy()/strcat()/strncat(), (excluding the _s versions which aren't standard on all compilers). The ones with the n don't guarantee null terminator and the others guarantee null terminator but not the max number of chars copied! Hence I like snprintf() which does both.
Thank you @seeplus @George P @lastchance - I really appreciate your help, and I'm learning a lot from it.
I'm just wondering why @seeplus changed my char h array into a const char h array?
Was it simply because the code didn't call for the value to be modified, or was there some other reason?
It seems to me that making h a const is a little limiting, and having played with the code bellow it seems fine to leave it as a char array, leaving open the option to manipulate the value in h with a char* ?
#include <iostream>
#include <cstring> // required for memset()
#include <cstdio> // required for snprintf()
#define LOGZ(s) std::cout << s << "Z\n"
int main() {
// char* buffer = new char[8]; While this does alloacte heap, it is un-intialised which can be problematic.
char* buffer { newchar[8]{} }; // This is Uniform Initialisation - it became the standard with C++ 11. Better as the allocated heap is intialised with n times \0 (NULL)
char h[8]{ "1234567" }; // The 8 is not required as memory will be dynamically allocated dependent on num char's between " "
char* change {h}; // change points to address of 'h'
int a{ 452 }; // This is Uniform Initialisation - it became the standard with C++ 11.
a++;
LOGZ(a);
snprintf(change, 8, "9876543"); // print char array to address pointed to by 'change' which is 'h'
LOGZ(buffer);
memset(buffer, 'A', 7);
LOGZ(buffer);
snprintf(buffer, 8, "%s", h); // uses the printf syntax to print to the pointer memory address "buffer", 8x (1byte) char, format "%s" (string), char array 'h'. string terminator is automatic
LOGZ(buffer);
delete[] buffer;
return 0;
}
I'm just wondering why @seeplus changed my char h array into a const char h array?
Because it's value isn't/shouldn't be changed in that code. I always 'const' variables that shouldn't be changed - it helps to spot issues. If a const is tried to be changed then the compiler will complain and spit out an error. Fixing a compiler error potentially costs much less to fix than having to test/debug a program to find an issue.
If at all possible, let the compiler find issues in the code.
To be fair, in code development it might not be a great idea. If you are developing incrementally (as it is definitely good practice to do) then you would be forced to go back and remove it when you do need to change the array.
It's a personal (and possibly minority) view, based to some extent on their non-requirement in the other languages that I use, that std:: and const are being over-egged here. That runs a real risk of turning people off c++, especially if all you want to do is "get something done", rather than being so risk-averse that the code is many times the length and verbosity that it needs to be.
seeplus (3972)
...
Because it's value isn't/shouldn't be changed in that code. I always 'const' variables that shouldn't be changed - it helps to spot issues. If a const is tried to be changed then the compiler will complain and spit out an error. Fixing a compiler error potentially costs much less to fix than having to test/debug a program to find an issue.
If at all possible, let the compiler find issues in the code.
Thank you @seeplus - that clarifies it for me. I did wonder if it was just best practice when you don't plan to modify a variable, but wanted to make sure I wasn't missing something.
lastchance (6281)
To be fair, in code development it might not be a great idea. If you are developing incrementally (as it is definitely good practice to do)
then you would be forced to go back and remove it when you do need to change the array.
It's a personal (and possibly minority) view, based to some extent on their non-requirement in the other languages that I use,
that std:: and const are being over-egged here. That runs a real risk of turning people off c++, especially if all you want to do is
"get something done", rather than being so risk-averse that the code is many times the length and verbosity that it needs to be
Always good to know there are a range of viewpoints - especially when people remain civil and accepting of the opposing views, which is not always a characteristic of interactions on the internet :)
It's one thing writing a few lines of code. It's another when you're dealing with thousands of lines. Good practice instilled at an early stage could save you getting bitten later on.
Mmm, but I find it bizarre when such monstrosities as void g(const Foo* const* p)
are recommended as good practice (as in that ISO cpp guide).
And why on earth would I want to write two of everything?
1 2 3 4 5 6 7
class Fred { /*...*/ };
class MyFredList {
public:
const Fred& operator[] (unsigned index) const; // Subscript operators often come in pairs
Fred& operator[] (unsigned index); // Subscript operators often come in pairs
// ...
};
I thought the whole idea of any function was to avoid code duplication?
And having swallowed const ... there's then mutable when you realise that const wasn't so great after all.
and you need the different overloaded operators for these. const is considered part of the function signature.
mutable is when in general the contents of a class is not expected to change for an operation (ie say display()) but you also want to know how say many times display() has been called. display() would be defined const as it's not expected to change the instantiation variables but cntDisplay would be defined mutable so that display() can update the count even though marked as const.